2011-03-17 130 views
15

Estoy usando iTextSharp para unir varios archivos PDF en un solo Pdf. Encontré un code sample o two en la web sobre cómo lograr esta tarea.iTextSharp cómo rotar/cambiar página de paisaje a retrato

Todos funcionan, sin problemas aparentes, ya que puedo fusionar varios archivos PDF en un único PDF.

El problema que tengo es que me gustaría que todas las páginas estén en PORTRAIT, ya que algunos de los archivos PDF tienen páginas en LANDSCAPE y me gustaría que se roten a RETRATO. No me importa que estén al revés o de lado, pero todos deben estar en retrato.

En cuanto a las secciones de código en los ejemplos que figuran:

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

siempre devuelve el valor de la página de rotación como 0 (cero) por lo tanto la sección de código

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

es ejecutado (si eso es qué se supone que debe hacer, rotando la página).

Por lo tanto, basado en el código en el enlace de la primera muestra de código page = writer.GetImportedPage(reader, i) cómo hago para cambiar el diseño de página de la page de horizontal a vertical, antes de agregar que el nuevo documento PDF combinado con cb.AddTemplate...?

PS. La determinación de si una página es horizontal o vertical utilizo el siguiente fragmento de code obtenido a partir de SO (adaptada para el ejemplo de código anterior):

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

Cualquier ayuda sería apreciada.

Gracias

Respuesta

6

Como has descubierto, no siempre puedes contar con PdfReader.GetPageRotation().

por ejemplo, si se crea el objeto del documento así:

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

PdfReader.GetPageRotation() se siempre retorno 0.

un muy manera simplificado para decidir si una página es vertical u horizontal es comparar el ancho y el alto de cada página de cada PDF que está combinando. si el ancho es mayor que el alto de una página individual, agregue una entrada de diccionario a esa página y establezca explícitamente su rotación. algo así como lo siguiente 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(); 
    } 
    } 
} 

echar un vistazo a la PdfDictionary class. y here's a good thread del mailing list explicando cómo iText [Sharp] almacena la rotación de página en cada página.

y por supuesto, es posible que desee invertir en the book.

+0

Gracias. Funciona de maravilla. – Riaan

10

He usado algo como esto.

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

Gracias. Lo he intentado también, la ruta del Rectángulo. Cuando ejecuto el código con un PDF en formato horizontal, los valores de Rectángulo son: base {iTextSharp.text.Element} = {Rectángulo: 841.8898x595.2756 (putrefacción: 0 grados)} Cuando ejecuto el mismo código con un PDF en Los valores Rectángulo del retrato son: base {iTextSharp.text.Element} = {Rectángulo: 595x842 (putrefacción: 0 grados)} A partir de los diferentes valores XY, puede ver que los archivos son Horizontal o Vertical, pero la rotación permanece 0 en ambos casos. – Riaan

+0

Debo agregar, que si uso el XYRatio según mi código de ejemplo, la página se da vuelta, lo cual está bien, pero no se estira todo el tamaño de página A4, está más a medio camino. Si solo puedo encontrar más detalles sobre los parámetros para AddTemplate en lugar de solo 'float a' ... 'float f' – Riaan

+0

Funciona mejor en mi situación, gracias por el código! – VinnyG

3

con ese ejemplo http://alex.buayacorp.com/merge-pdf-files-with-itext-and-net.html que añade la línea siguiente:

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; 

Mis pdfs se construyen a partir de SSRS y tienen el mismo tamaño, por lo que utilizan la primera página de la primera documento (supongo)

+0

gracias, eso hizo el truco con mi informe ssrs. – Lareau

0
// Instantiate the imported page as an Image 

const float HALF_INCH = 36f; 
// currentPosY is used to keep track of the current Y position. 

PdfImportedPage page = writer.GetImportedPage(reader, j); 
float scale = ((currentPosY - HALF_INCH - 10f)/page.Height); 
Image imgP = Image.GetInstance(page); 

if (page.Width > page.Height) { // Auto-detect landscape 
scale = ((currentPosY - HALF_INCH - 10f)/page.Width); 
imgP.RotationDegrees = 90f; // could be 270f 
} 

imgP.ScalePercent(scale * 100f); 
imgP.SetAbsolutePosition(HALF_INCH, HALF_INCH); 
imgP.CompressionLevel = 9; 
imgP.Border = Image.BOX; 
imgP.BorderWidth = 1f; 

document.Add(imgP); 
Cuestiones relacionadas