web-dev-qa-db-fra.com

iTextSharp comment faire pivoter/changer de page d'un paysage à un portrait

J'utilise iTextSharp pour fusionner plusieurs fichiers PDF en un seul fichier PDF. J'ai trouvé un exemple de code ou deux sur le Web pour savoir comment accomplir cette tâche.

Ils fonctionnent tous sans problèmes apparents, car je suis capable de fusionner plusieurs fichiers PDF en un seul fichier PDF. 

Le problème que j’ai, c’est que je voudrais que toutes les pages soient dans PORTRAIT, car certains des fichiers PDF ont des pages dans LANDSCAPE et je voudrais qu’elles soient tournées vers PORTRAIT. Cela ne me dérange pas qu'ils soient à l'envers ou sur le côté, mais ils doivent tous être en portrait.

En regardant les sections de code dans les exemples énumérés:

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

renvoie toujours la valeur de rotation de page à 0 (zéro) donc la section de code

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

n'est jamais exécuté (si c'est ce que l'on est censé faire, tourner la page).

Donc, en fonction du code dans le lien du premier exemple de code page = writer.GetImportedPage(reader, i), comment changer la mise en page de la page de Paysage à Portrait, avant de l'ajouter au nouveau document fusionné PDF avec cb.AddTemplate...?

PS Déterminer si une page est en paysage ou en portrait, j'utilise le morceau suivant de code obtenu à partir de SO (adapté pour l'exemple de code ci-dessus):

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

Toute aide serait appréciée.

Merci

16
Riaan

comme vous l'avez découvert, vous ne pouvez pas toujours compter sur PdfReader.GetPageRotation () .

par exemple, si l'objet Document est créé comme ceci:

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

PdfReader.GetPageRotation() sera toujours retournera 0.

une vraiment manière simplifiée de décider si une page est en portrait ou en paysage consiste à comparer la largeur et la hauteur de chaque page de chaque PDF que vous combinez. si la largeur est supérieure à la hauteur d'une page individuelle, ajoutez une entrée de dictionnaire à cette page et définissez explicitement sa rotation. quelque chose comme le gestionnaire HTTP suivant :

<%@ 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();
    }
  }
}

jetez un oeil à la classe PdfDictionary . et voici un bon fil de la liste de diffusion expliquant comment iText [Sharp] enregistre la rotation de page dans chaque page. 

et bien sûr, vous voudrez peut-être investir dans le book .

6
kuujinbo

J'ai utilisé quelque chose comme ça. 

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

avec cet exemple http://alex.buayacorp.com/merge-pdf-files-with-itext-and-net.html J'ai ajouté la ligne suivante:

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;

Mes fichiers PDF sont construits à partir de SSRS et ont la même taille. J'utilise donc la première page du premier document (je suppose).

3
avalla
// 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);
0
user1945972