0

I am shrinking pdf using below code. Before shrinking PDF pages can be seen in Portrait, but after shrinking their orientation is changing to Landscape. When I print rotation of page before shrinking it is coming as 270 degree. What is causing page to rotate after shrinking? (The PDF which i am trying to shrink has old scanned images)

public  void shrinkPDF(String strFilePath , String strFileName) throws Exception {      
    PdfReader reader = new PdfReader(strFilePath+"//"+strFileName);
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(strFilePath+"//Shrink_"+strFileName));
    int n = reader.getNumberOfPages();
    for (int p = 1; p <= 1; p++) {
        float offsetX = (reader.getPageSize(p).getWidth() * (1 - xPercentage)) / 2;
        float offsetY = (reader.getPageSize(p).getHeight() * (1 - yPercentage)) / 2;
        PdfDictionary page;
        PdfArray crop;
        PdfArray media;
        page = reader.getPageN(p);
        System.out.println("reader.getPateRoatation-->"+reader.getPageRotation(p));
        media = page.getAsArray(PdfName.CROPBOX);
        if (media == null) {
            media = page.getAsArray(PdfName.MEDIABOX);
        }
        crop = new PdfArray();
        crop.add(new PdfNumber(0));
        crop.add(new PdfNumber(0));
        crop.add(new PdfNumber(media.getAsNumber(2).floatValue()));
        crop.add(new PdfNumber(media.getAsNumber(3).floatValue()));
        page.put(PdfName.MEDIABOX, crop);
        page.put(PdfName.CROPBOX, crop);
        Rectangle mediabox = reader.getPageSize(p);
        stamper.getUnderContent(p).setLiteral(
                String.format("\nq %s %s %s %s %s %s cm\nq\n",
                xPercentage, mediabox.getLeft(),mediabox.getBottom(), yPercentage,  offsetX, offsetY));
        stamper.getOverContent(p).setLiteral("\nQ\nQ\n");           
    }
    stamper.close();
    reader.close();
}
mkl
  • 90,588
  • 15
  • 125
  • 265
Chetan_C
  • 5
  • 2
  • please share a sample pdf. And unless that code is all you do during stamping, share a more complete code sample. – mkl Feb 03 '18 at 20:59
  • Is it ok if i send sample on your mail id "mkl@wir-sind-cool.org"? – Chetan_C Feb 04 '18 at 04:58
  • That's ok. Chances are I'll have time tomorrow for looking into that. – mkl Feb 04 '18 at 07:31
  • That been said, I just looked at your code once again and saw that (in contrast to the code in your earlier question) you use non-zero values as second and third parameter of your **cm** operation. That of course will result in some rotation and/or skewing. – mkl Feb 04 '18 at 08:03

1 Answers1

0

The cause

The cause for the issue is a feature of iText:

iText tries to simplify adding information to a rotated page by starting both the overcontent and the undercontent with a rotation of the current transformation matrix. This makes additions to the page appear upright in a PDF viewer without the need to add individual rotations.

Even though the undercontent is drawn before the original page content, this normally has no effect on that original content because the whole undercontent is enveloped in a save-graphics-state / restore-graphics-state instruction pair.

The literal you use as undercontent, though, contains two save-graphics-state instructions and no restore-graphics-state instruction. This makes the added rotation suddenly affect the original content, too. Thus, your original content is rotated even though you only want to scale.

The fix

iText allows you to switch off the feature described above. You can do so by setting the PdfStamper property RotateContents to false right after creating the PdfStamper:

PdfStamper stamper = new PdfStamper(reader, result);
stamper.setRotateContents(false);
int n = reader.getNumberOfPages();

Now iText won't add that rotation anymore to the undercontent and your original only is scaled.

The PdfStamper property RotateContents has been discussed more deeply in this answer.

Annotation considerations

iText does not only add the rotation to undercontent and overcontent of page content streams, it also manipulates the dimensions of annotations added to rotated pages, and unfortunately the PdfStamper property RotateContents is not taken into account for that.

A work-around in that case is to temporarily remove the page Rotation entry before adding the annotation to the page and to put it back again later. This has already been discussed in more detail in this answer, this answer, and this answer.

Your remaining code

  • Your changes to crop box and media box seem unnecessary and might have unexpected and undesired results.

  • You add the shrinking like this:

    stamper.getUnderContent(p).setLiteral(
            String.format("\nq %s %s %s %s %s %s cm\nq\n",
            xPercentage, mediabox.getLeft(),mediabox.getBottom(), yPercentage,  offsetX, offsetY));
    

    Setting the second and third parameter to mediabox.getLeft() and mediabox.getBottom() respectively often will have no bad effect (as these values often are 0) but in some cases you'll experience extremely distorted views of (enlarged parts of) your page.

mkl
  • 90,588
  • 15
  • 125
  • 265