Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rotate a single page 90 degrees with iTextSharp/VB in an existing multi-page PDF

I am trying to integrate iTextSharp into an existing Document Imaging application that allows users to rotate individual pages that may have been scanned in at an incorrect angle (it happens more often than I would have thought).

I have the actual page data rotating correctly across 90/180 degrees, but the page orientation is not rotating along with it. I have just started working with iTextSharp, so I'm still a little unfamiliar with its methods, but was able to cobble together what I have so far using posts from StackOverflow. It's close, but not quite there.

Here's what I have so far:

' Get the input document and total number of pages
Dim inputPdf As New iTextSharp.text.pdf.PdfReader(fileName)
Dim pageCount As Integer = inputPdf.NumberOfPages

' Load the input document 
Dim inputDoc As New iTextSharp.text.Document(inputPdf.GetPageSizeWithRotation(1))

' Set up the file stream for our output document
Dim outFileName As String = Path.ChangeExtension(fileName, "pdf")
Using fs As New FileStream(outFileName, FileMode.Create)
    ' Create the output writer
    Dim outputWriter As iTextSharp.text.pdf.PdfWriter = iTextSharp.text.pdf.PdfWriter.GetInstance(inputDoc, fs)
    inputDoc.Open()

    ' Copy pages from input to output document
    Dim cb As iTextSharp.text.pdf.PdfContentByte = outputWriter.DirectContent
    For index As Integer = 1 To pageCount
        inputDoc.SetPageSize(inputPdf.GetPageSizeWithRotation(index))
        inputDoc.NewPage()

        ' If this is our page to be rotated, perform the desired transform
        ' TODO - 90 degree rotations need to change the page orientation as well
        Dim page As iTextSharp.text.pdf.PdfImportedPage = outputWriter.GetImportedPage(inputPdf, index)
        If index = pageNum Then
            Select Case angle
                Case 90
                    cb.AddTemplate(page, 0, -1, 1, 0, 0, page.Height)
                Case 180
                    cb.AddTemplate(page, -1, 0, 0, -1, page.Width, page.Height)
                Case 270
                    cb.AddTemplate(page, 0, 1, -1, 0, page.Width, 0)
                Case Else
                    ' Should not be here, but don't do anything
                    cb.AddTemplate(page, 1, 0, 0, 1, 0, 0)
            End Select
        Else
            ' No rotation; add as is
            cb.AddTemplate(page, 1, 0, 0, 1, 0, 0)
        End If
    Next
    inputDoc.Close()
End Using

I tried adding the following code to the top to grab the page size from the existing page and swap the dimensions if the rotation angle was 90 or 270:

For index As Integer = 1 To pageCount
Dim pageSize As iTextSharp.text.Rectangle = inputPdf.GetPageSizeWithRotation(index)
If angle = 90 OrElse angle = 270 Then
    ' For 90-degree rotations, change the orientation of the page, too
    pageSize = New iTextSharp.text.Rectangle(pageSize.Height, pageSize.Width)
End If
inputDoc.SetPageSize(pageSize)
inputDoc.NewPage()

Unfortunately, this had the effect of rotating every page 90 degrees, and the data on the page I wanted rotated didn't show up in the correct spot anyway (it was shifted down and off the page a bit).

Like I said, I'm not really familiar with the inner workings of the API. I have checked out the examples online at the sourceforge page, and have taken a look at the book (both editions), but I don't see anything that fits the bill. I saw an example here that shows page orientation for newly-composed PDFs, but nothing for existing ones. Can anybody help me out? Thanks!

like image 593
Mike Loux Avatar asked Dec 17 '10 13:12

Mike Loux


1 Answers

You're making this harder than it needs to be.

Rather than rotating the page contents, you want to rotate the page itself:

PdfReader reader = new PdfReader(path);
PdfStamper stamper = new PdfStamper( reader, outStream );

PdfDictionary pageDict = reader.getPageN(desiredPage);
int desiredRot = 90; // 90 degrees clockwise from what it is now
PdfNumber rotation = pageDict.getAsNumber(PdfName.ROTATE);
if (rotation != null) {
  desiredRot += rotation.intValue();
  desiredRot %= 360; // must be 0, 90, 180, or 270
}
pageDict.put(PdfName.ROTATE, new PdfNumber(desiredRot);


stamper.close();

That's it. You can play around with desiredPage and desiredRot to get whatever effect you're after. Enjoy.

like image 105
Mark Storer Avatar answered Nov 02 '22 22:11

Mark Storer