Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iTextSharp how to rotate/switch page from landscape to portrait

Tags:

c#

itext

I'm using iTextSharp to merge multiple PDF files into a single Pdf. I found a code sample or two on the web as to how to accomplish this task.

They all work, with no apparent issues, as I'm able to merge multiple PDF files into a single PDF.

The issue that I do have is that I would like for all the pages to be in PORTRAIT, as some of the PDF files have pages in LANDSCAPE and I would like for them to be rotated to PORTRAIT. I do not mind that they will either be upside down or sideways, but they must all be in portrait.

Looking at the code sections in the examples listed:

page = writer.GetImportedPage(reader, i);
rotation = reader.GetPageRotation(i);

always returns the page rotation value as 0 (zero) thus the code section

if (rotation == 90 rotation == 270)
{
    cb.AddTemplate(page, 0, -1f, 1f, 0, 0, 
                         reader.GetPageSizeWithRotation(i).Height);
}

never gets executed (if that is what is supposed to do, rotating the page).

So, based on the code in the link of the 1st code sample page = writer.GetImportedPage(reader, i) how would I go about to change the page layout of the page from Landscape to Portrait, before I add it to the new merged PDF document with cb.AddTemplate...?

PS. Determining whether a page is either landscape or portrait I use the following piece of code obtained from SO (adapted for the code example above):

float pageXYRatio = page.Width / page.Height;
if (XYRatio > 1f)
{
    //page is landscape
}
else
{
    //page is portrait
}

Any help would be appreciated.

Thanks

like image 767
Riaan Avatar asked Mar 17 '11 20:03

Riaan


3 Answers

I used something like this.

cb.PdfDocument.NewPage();
PdfImportedPage page1 = writer.GetImportedPage(reader, i);

Rectangle psize = reader.GetPageSizeWithRotation(i);
switch (psize.Rotation)
{
    case 0:
        cb.AddTemplate(page1, 1f, 0, 0, 1f, 0, 0);
        break;
    case 90:
        cb.AddTemplate(page1, 0, -1f, 1f, 0, 0, psize.Height);
        break;
    case 180:
        cb.AddTemplate(page1, -1f, 0, 0, -1f, 0, 0);
        break;
    case 270:
        cb.AddTemplate(page1, 0, 1.0F, -1.0F, 0, psize.Width, 0);
        break;
    default:
        break;
}
like image 118
Guilherme de Jesus Santos Avatar answered Oct 14 '22 22:10

Guilherme de Jesus Santos


as you've found out, you cannot always count on PdfReader.GetPageRotation().

for example, if the Document object is created like this:

Document doc = new Document( new Rectangle(792, 612) );

PdfReader.GetPageRotation() will always return 0.

a really simplified way to decide whether a page is portrait or landscape is to compare the width and height of each page of each PDF you're combining. if the width is greater than the height of an individual page, add a dictionary entry to that page and explicitly set it's rotation. something like the following HTTP handler:

<%@ WebHandler Language='C#' Class='LandscapeToPortrait' %>
using System;
using System.IO;
using System.Web;
using iTextSharp.text;
using iTextSharp.text.pdf;

public class LandscapeToPortrait : IHttpHandler {
  public void ProcessRequest (HttpContext context) {
    HttpResponse Response = context.Response;
    Response.ContentType = "application/pdf";
    PdfReader[] readers = {
      new PdfReader(CreateReaderBytes(false)),
      new PdfReader(CreateReaderBytes(true))
    };

    using (Document doc = new Document()) {
      using (PdfCopy copy = new PdfCopy(doc, Response.OutputStream)) {
        doc.Open();
        foreach (PdfReader reader in readers) {
          int n = reader.NumberOfPages;
          for (int page = 0; page < n;) {
            ++page;
            float width = reader.GetPageSize(page).Width;
            float height = reader.GetPageSize(page).Height;
            if (width > height) {
              PdfDictionary pageDict = reader.GetPageN(page);
              pageDict.Put(PdfName.ROTATE, new PdfNumber(90));
            }
            copy.AddPage(copy.GetImportedPage(reader, page));
          }
        }        
      }
    }
  }
  public bool IsReusable {
    get { return false; }
  }
  public byte[] CreateReaderBytes(bool isLandscape) {
    using (MemoryStream ms = new MemoryStream()) {
      Rectangle r = isLandscape
        ? new Rectangle(792, 612)
        : PageSize.LETTER
      ;
      using (Document doc = new Document(r)) {
        PdfWriter.GetInstance(doc, ms);
        doc.Open();
        for (int i = 0; i < 5; ++i) {
          doc.Add(new Phrase("hello world"));
          doc.NewPage();
        }
      }
      return ms.ToArray();
    }
  }
}

take a look at the PdfDictionary class. and here's a good thread from the mailing list explaining how iText[Sharp] stores the page rotation in every page.

and of course, you might want to invest in the book.

like image 43
kuujinbo Avatar answered Oct 14 '22 22:10

kuujinbo


with that example http://alex.buayacorp.com/merge-pdf-files-with-itext-and-net.html I added the following line:

newDocument.SetPageSize(documents[0].GetPageSizeWithRotation(1));*

newDocument = new Document();
PdfWriter pdfWriter = PdfWriter.GetInstance(newDocument, outputStream);

// START PAGE ORIENTATION FROM 1st Document 1st Page
newDocument.SetPageSize(documents[0].GetPageSizeWithRotation(1));
// END PAGE ORIENTATION
newDocument.Open();
PdfContentByte pdfContentByte = pdfWriter.DirectContent;

My pdfs are built from SSRS and they have the same size, so I use the 1st page of the 1st document (I suppose)

like image 3
avalla Avatar answered Oct 14 '22 23:10

avalla