PDFsharp & MigraDoc Foundation

PDFsharp - A .NET library for processing PDF & MigraDoc Foundation - Creating documents on the fly
It is currently Thu Dec 14, 2017 6:15 am

All times are UTC




Post new topic Reply to topic  [ 7 posts ] 
Author Message
PostPosted: Thu Dec 17, 2015 2:42 pm 
Offline

Joined: Thu Dec 17, 2015 2:20 pm
Posts: 4
Hello,
I found a bug with landscape page.
Each time I load and save a landscape page, the MediaBox get rotated by 90 degree.

Example:
Original landscape PDF
Attachment:
Page original.jpg
Page original.jpg [ 25.26 KiB | Viewed 3194 times ]


Here is the PDF just opened and re-saved, as you can see the boundary are turned by 90 degree.
Attachment:
Page 1st save.jpg
Page 1st save.jpg [ 19.6 KiB | Viewed 3194 times ]


If I open the resaved file, and save it again, then the media box get turned again.

To me this seem a bug in PdfSharp, is it possible to fix it?

The code to get this bug is very simple:

Code:
     'read the original pdf
        pdfDoc = PdfReader.Open(currentPath & "\Page Landscape.pdf")
        'save the pdf, this will mess up the media-box
        pdfDoc.Save(currentPath & "\Page Landscape - 1st save, WRONG.pdf")


I've attached the sourcecode of a working example.
Attachment:
BugPdfSharpLandscape Source.zip [30.42 KiB]
Downloaded 116 times



I also put together some code that seem to fix this bug... it works in some case, but I don't know if it's the correct way to fix the issue.
Also, I don't know if the issue happen during the file loading, or during the file saving.



Here is my quick and dirty fix, that works in some situation, but fail in others... (landscape turned by 90degree, it works, landscape turned by 270 degree, it fail... it need more testing, or just a fix in the library)
Code:
    Public Shared Sub FixLandscapePages(pdfDoc As PdfSharp.Pdf.PdfDocument)

        'landscape pages fix
        'the fix must be the last action executed against the page, and it must be done exactly one time for each page

        For Each page As PdfPage In pdfDoc.Pages
            If page.MediaBox.Width <> page.Width.Point Or page.MediaBox.Height <> page.Height.Point Then
                page.MediaBox = New PdfRectangle(New XPoint(0, 0), New XPoint(page.Width.Point, page.Height.Point))
            End If

        Next

    End Sub



Thanks,
Max


Top
 Profile  
Reply with quote  
PostPosted: Sat Dec 19, 2015 8:57 pm 
Offline
User avatar

Joined: Sat Mar 14, 2015 10:15 am
Posts: 308
Location: CCAA
Hi, Max,

Yes, this bug should be fixed in the library.

I made an experimental change in class PdfPage.cs:
Code:
internal PdfPage(PdfDictionary dict)
    : base(dict)
{
    // Set Orientation depending on /Rotate.
    //int rotate = Elements.GetInteger(InheritablePageKeys.Rotate);
    //if (Math.Abs((rotate / 90)) % 2 == 1)
    //    _orientation = PageOrientation.Landscape;
}


I don't know if this works in all cases, but it works with your test code.

PDFsharp source is available on CodePlex, SourceForge, GitHub - in case you want to test it.

_________________
Best regards
Thomas
(Freelance Software Developer with several years of MigraDoc/PDFsharp experience)


Top
 Profile  
Reply with quote  
PostPosted: Mon Dec 21, 2015 2:25 pm 
Offline

Joined: Thu Dec 17, 2015 2:20 pm
Posts: 4
TH-Soft wrote:
Hi, Max,

Yes, this bug should be fixed in the library.

I made an experimental change in class PdfPage.cs:
Code:
internal PdfPage(PdfDictionary dict)
    : base(dict)
{
    // Set Orientation depending on /Rotate.
    //int rotate = Elements.GetInteger(InheritablePageKeys.Rotate);
    //if (Math.Abs((rotate / 90)) % 2 == 1)
    //    _orientation = PageOrientation.Landscape;
}


I don't know if this works in all cases, but it works with your test code.

PDFsharp source is available on CodePlex, SourceForge, GitHub - in case you want to test it.


Thank you for looking into my issue.
Now I'm trying the modified code (I'm using the source version 1.32).
I'll let you know if I have other issues.


Top
 Profile  
Reply with quote  
PostPosted: Tue Dec 22, 2015 3:12 pm 
Offline

Joined: Thu Dec 17, 2015 2:20 pm
Posts: 4
Hello
after much testing, I've come up with different code to try to fix this bug:

Modification 1
Code:
internal PdfPage(PdfDictionary dict)
  : base(dict)
{
   //// Set Orientation depending on / Rotate
   //int rotate = Elements.GetInteger(PdfPage.Keys.Rotate);
   //if (Math.Abs((rotate / 90)) % 2 == 1)
   //    this.orientation = PageOrientation.Landscape;

   bool dimensionsLooksLandscape = false;
   bool rotationLooksLandscape = false;

    //check if the rotation seem to be landscape (this is only true if the starting page was portrait, whic IS NOT always the case)
   int rotate = Elements.GetInteger(PdfPage.Keys.Rotate);
   if (Math.Abs((rotate / 90)) % 2 == 1)
      rotationLooksLandscape = true;

   //check if the page dimensions seem to be from a landscape page (which IS the case if the pdf document is a scan of a landscape A4)
   if (this.Width > this.Height)
      dimensionsLooksLandscape = true;

   //now, if the PDF was a landscape A4 (so dimensionsLooksLandscape == true) and was rotated by 270° (so rotationLooksLandscape == true) then it will looks portrait
   if (dimensionsLooksLandscape ^ rotationLooksLandscape)
      this.orientation = PageOrientation.Landscape;
}



Modification 2 (I've only commented out some code, my modifications are preceded by //-----------------------// )

Code:
        internal override void WriteObject(PdfWriter writer)
        {
            // HACK: temporarily flip media box if Landscape
            PdfRectangle mediaBox = MediaBox;
            // TODO: Take /Rotate into account



            //-----------------------//Commented by MaxDna
            //-----------------------//if (orientation == PageOrientation.Landscape)
            //-----------------------//    MediaBox = new PdfRectangle(mediaBox.X1, mediaBox.Y1, mediaBox.Y2, mediaBox.X2);



            //#warning THHO4STLA: warum nicht new PdfRectangle(mediaBox.Y1, mediaBox.X1, mediaBox.Y2, mediaBox.X2)? - siehe auch Orientation
            //#warning THHO4STLA: CropBox, BleedBox etc. auch drehen?

#if true
            // Add transparency group to prevent rendering problems of Adobe viewer
            this.transparencyUsed = true; // TODO: check XObjects
            if (this.transparencyUsed && !Elements.ContainsKey(Keys.Group))
            {
                PdfDictionary group = new PdfDictionary();
                this.elements["/Group"] = group;
                if (this.document.Options.ColorMode != PdfColorMode.Cmyk)
                    group.Elements.SetName("/CS", "/DeviceRGB");
                else
                    group.Elements.SetName("/CS", "/DeviceCMYK");
                group.Elements.SetName("/S", "/Transparency");
                group.Elements["/I"] = new PdfBoolean(false);
                group.Elements["/K"] = new PdfBoolean(false);
            }
#endif

#if DEBUG_
      PdfItem item = Elements["/MediaBox"];
      if (item != null)
        item.GetType();
#endif
            base.WriteObject(writer);



            //-----------------------//Commented by MaxDna
            //-----------------------//  if (this.orientation == PageOrientation.Landscape)
            //-----------------------//      MediaBox = mediaBox;

        }


Now, with this code, works for some, but not all PDF files that I need to manage.
In my software I need to load existing PDF, add some test annotations in specific positions, ant then save the new PDF.
With these modification, I'm able to Load PDF, Add text annotations in specific places, and save the PDF on:
*) Normal Portrait PDF
*) Normal Landscape PDF (rotation = 90°)

My modification DON'T works well with Landscape PDF with a rotation of 270°, in this case the positioning/rotation of the added TextAnotations is messed up.

I think that PDF rotated by 270° don't works because of the code in the file PdfFormXObject.cs at line 210 and following...

Code:
      // Take /Rotate into account
      PdfRectangle rect = importPage.Elements.GetRectangle(PdfPage.Keys.MediaBox);
      int rotate = importPage.Elements.GetInteger(PdfPage.Keys.Rotate);
      //rotate = 0;
      if (rotate == 0)
      {
        // Set bounding box to media box
        this.Elements["/BBox"] = rect;
      }
      else
      {
        // TODO: Have to adjust bounding box? (I think not, but I'm not sure -> wait for problem)
        this.Elements["/BBox"] = rect;

        // Rotate the image such that it is upright
        XMatrix matrix = new XMatrix();  //XMatrix.Identity;
        double width = rect.Width;
        double height = rect.Height;
        matrix.RotateAtPrepend(-rotate, new XPoint(width / 2, height / 2));

        // Translate the image such that its center lies on the center of the rotated bounding box
        double offset = (height - width) / 2;
        if (height > width)
          matrix.TranslatePrepend(offset, offset);
        else
          matrix.TranslatePrepend(-offset, -offset);

        //string item = "[" + PdfEncoders.ToString(matrix) + "]";
        //Elements[Keys.Matrix] = new PdfLiteral(item);
        Elements.SetMatrix(Keys.Matrix, matrix);
      }


Looking at this code, to me it seem that the possible rotation taken in consideration are "0°" and "not 0°" (90°?)
Probably the "not 0°" should be extended to handle 90°, 180°, 270° rotations separately, but I dont know enough about PDF / PdfSharp internals to try to fix this...


Top
 Profile  
Reply with quote  
PostPosted: Mon Mar 07, 2016 10:19 am 
Offline
empira Employee
User avatar

Joined: Mon Oct 16, 2006 8:16 am
Posts: 2740
Location: Cologne, Germany
Note to self: also check CropBox when making changes.
See also:
viewtopic.php?p=9799#p9799

_________________
Regards
Thomas Hoevel
PDFsharp Team


Top
 Profile  
Reply with quote  
PostPosted: Mon Jan 09, 2017 8:32 pm 
Offline

Joined: Mon Jan 09, 2017 8:12 pm
Posts: 2
I ran into this issue as well. We are attempting to populate forms from db values rather than having a person type them in. I very quickly was able to open an existing pdf, read the form, and populate fields, then save a new completed form to file. However, one of our forms is part of a larger pdf that sends lots of info, and the info pages are landscape, while the form (the first page) is portrait oriented.

The open/fill/save resulted in a good form, but 1/3 of the landscape data being cut off.

It appears on looking at some outputs that there may be a redundant swapping of height and width values when defining the "MediaBox" object of a "PdfPage" object. I say redundant because you'll see that the orientation is "Landscape" AND the "Rotation" is 90. I have not dived deep into the PdfSharp source code, but hope this will point the way to a quick easy fix for someone that is familiar with the source code.

I have enclosed some example outputs, and a very short "fix" that I implemented in my test to correct the saving of landscaped pages. The red box of the code snippet is the fix, please not that it is AFTER the outputs were generated. The green box in the output is the portrait page that is opened/filled/saved correctly, the red box in the output highlights that the "MediaBox" height and width are actually swapped.

Also note, I tried changing the "Rotation" to 0 and this resulted in the page reading from top to bottom with 1/3 of the info still being cutoff from the top edge. Changing the "Orientation" produced correct results.

Attachment:
File comment: Output Example:
pdfSharpOutput.jpg
pdfSharpOutput.jpg [ 188.65 KiB | Viewed 1800 times ]


Attachment:
File comment: Code Example:
pdfSharpCode.jpg
pdfSharpCode.jpg [ 187.06 KiB | Viewed 1800 times ]


Top
 Profile  
Reply with quote  
PostPosted: Mon Jan 09, 2017 9:29 pm 
Offline
User avatar

Joined: Sat Mar 14, 2015 10:15 am
Posts: 308
Location: CCAA
kevin.gregg wrote:
It appears on looking at some outputs that there may be a redundant swapping of height and width values when defining the "MediaBox" object of a "PdfPage" object.
Please try the change proposed here:
viewtopic.php?p=9591#p9591

_________________
Best regards
Thomas
(Freelance Software Developer with several years of MigraDoc/PDFsharp experience)


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group