iTextSharp how to rotate/switch page from landscape to portrait

37,481

Solution 1

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.

Solution 2

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;
}

Solution 3

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)

Share:
37,481
Riaan
Author by

Riaan

My programming languages of choice are C# and Delphi, although I do have experience in Java. In addition, I also have a little bit of C++ knowledge, which formed part of my National Certificate in Datametrics from the University of South Africa (UNISA). As of late, I started dabbling in some web development, mainly ASP.NET MVC, ASP.NET Core, jQuery and Javascript. I graduated in 2019 with my BCom Honours degree with a specialisation in Information Systems from the University of Cape Town (UCT). I also have more than 20 years of experience in most things IT related from building and selling Personal Computers and lending IT support to those in need.

Updated on July 29, 2022

Comments

  • Riaan
    Riaan almost 2 years

    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