当文件在印刷厂光栅化时,iTextSharp 旋转的 PDF 页面恢复方向

iTextSharp rotated PDF page reverts orientation when file is rasterized at print house

我正在使用 iTextSharp 创建一个由现有 PDF 集合组成的 PDF,其中一些包含的 PDF 是横向的,需要旋转。所以,我执行以下操作:

    private static void AdjustRotationIfNeeded(PdfImportedPage pdfImportedPage, PdfReader reader, int documentPage)
    {
        float width = pdfImportedPage.Width;
        float height = pdfImportedPage.Height;

        if (pdfImportedPage.Rotation != 0)
        {
            PdfDictionary pageDict = reader.GetPageN(documentPage);
            pageDict.Put(PdfName.ROTATE, new PdfNumber(0));
        }

        if (width > height)
        {
            PdfDictionary pageDict = reader.GetPageN(documentPage);
            pageDict.Put(PdfName.ROTATE, new PdfNumber(270));
        }
    }

效果很好。如果需要,包含的 PDF 会旋转为纵向。 PDF 在我的本地打印机上打印正确。

此文件已发送至履行机构,不幸的是,包含景观的文件在经过打印机和光栅化过程时无法正确打印。他们使用 Kodak (Creo) NexRip 11.01 或 Kodak (Creo) Prinergy 6.1。机器。履行之家的建议是:"generate a new PDF file after we rotate pages or make any changes to a PDF. It is as easy as exporting out to a PostScript and distilling back to a PDF."

我知道 iTextSharp 不支持 PostScript。 iTextSharp 是否有另一种方法可以旋转包含的 PDF 以在光栅化时保持方向?

首先让我向您保证,更改页面字典中的旋转是实现您想要的目标的正确过程。据我所见,您的代码没有任何问题。你做对了。

不幸的是,您面对的是您无法控制的第三方产品做正确的事情。如何解决?

我写了一个例子叫IncorrectExample。我这样命名它是因为我不希望它在与您不同的上下文中使用。您可以安全地忽略我添加的所有警告:它们不适合您。此示例非常针对您的问题。

请尝试以下代码:

public void manipulatePdf(String src, String dest)
    throws IOException, DocumentException {
    // Creating a reader
    PdfReader reader = new PdfReader(src);
    // step 1
    Rectangle pagesize = getPageSize(reader, 1);
    Document document = new Document(pagesize);
    // step 2
    PdfWriter writer
        = PdfWriter.getInstance(document, new FileOutputStream(dest));
    // step 3
    document.open();
    // step 4
    PdfContentByte cb = writer.getDirectContent();
    for (int i = 1; i <= reader.getNumberOfPages(); i++) {
        pagesize = getPageSize(reader, i);
        document.setPageSize(pagesize);
        document.newPage();
        PdfImportedPage page = writer.getImportedPage(reader, i);
        if (isPortrait(reader, i)) {
            cb.addTemplate(page, 0, 0);
        }
        else {
            cb.addTemplate(page, 0, 1, -1, 0, pagesize.getWidth(), 0);
        }
    }
    // step 4
    document.close();
    reader.close();
}

public Rectangle getPageSize(PdfReader reader, int pagenumber) {
    Rectangle pagesize = reader.getPageSizeWithRotation(pagenumber);
    return new Rectangle(
            Math.min(pagesize.getWidth(), pagesize.getHeight()),
            Math.max(pagesize.getWidth(), pagesize.getHeight()));
}

public boolean isPortrait(PdfReader reader, int pagenumber) {
    Rectangle pagesize = reader.getPageSize(pagenumber);
    return pagesize.getHeight() > pagesize.getWidth();
}

我以pages.pdf文件为例。这个文件的特殊之处在于它有两个以不同方式创建的横向页面:

  • 一个页面是宽度小于高度的页面(听起来像纵向页面),但是由于页面字典中添加了 /Rotate90 , 它是横向显示的。
  • 另一个页面没有旋转,但它的高度小于宽度。

在我的示例中,我使用 类 DocumentPdfWriter 创建原始文档的副本。这是错误的一般,因为它丢弃了所有交互。我应该改用 PdfStamperPdfCopy,但在您的特定情况下 是正确的 因为您不需要交互性:PDF 的最终目的是待打印。

使用 Document,我使用新 Rectangle 创建新页面,该新页面使用现有页面尺寸的最小值作为宽度,最大值作为高度。这样,页面将始终为纵向。请注意,我使用方法 getPageSizeWithRotation() 来确保获得正确的宽度和高度,同时考虑到任何可能的旋转。

然后我在作者的直接内容上加一个PdfImportedPage。我使用 isPortrait() 方法来确定是否需要旋转页面。观察 isPortrait() 方法查看页面大小 而没有 考虑旋转。如果我们确实考虑了旋转,我们会旋转不需要旋转的页面。

可以在此处找到生成的 PDF:pages_changed.pdf

如您所见,一些信息丢失了:最后一页上有一个注释:它不见了。为原始文档定义了特定的查看器首选项:它们已经消失了。但这在您的具体情况下应该无关紧要,因为对您来说重要的是页面打印正确。