固定 PDF 的方向以缩放它

Fix the orientation of a PDF in order to scale it

我在使用 Xerox 扫描仪创建的包含旋转 属性 的 PDF 时遇到了一些问题。 下面的函数最初是为了按变量 scaleHeight 给定的量来缩放输入 PDF 的高度而创建的。 这适用于没有旋转的输入文档。

在测试文档旋转 270 度时,我发现忽略了会使文档以纵向显示的旋转 属性。相反,该文档在输出 PDF 中显示为横向。 所以我更新了下面的函数以仅在没有旋转时应用缩放,并使用我在网上找到的另一个示例来尝试修复旋转。 此 无效,并且 生成纵向格式的原始文档的镜像。

所以现在我有两个问题: 1.如何正确旋转文档内容。 2.如何缩放旋转后的内容

如果我能解决第 1 项,我可以简单地再次调用该函数(删除旋转 属性)来修复第 2 项。

感谢您的帮助,功能如下。 引用 rotationEvent 的注释掉的行在这里也没有帮助。

public String resizePDF (String pdfIn, float x, float y, float scaleHeight) throws Exception {
    String pdfOut = pdfIn.substring(0, pdfIn.length() - 4) + "_resize.pdf";
    PdfReader reader = new PdfReader(pdfIn);
    int rotation = reader.getPageRotation(1);
    com.itextpdf.text.Document doc = new com.itextpdf.text.Document(reader.getPageSizeWithRotation(1), 0, 0, 0, 0);
    PdfWriter writer = PdfWriter.getInstance(doc, new FileOutputStream(pdfOut));
    doc.open();
    PdfContentByte cb = writer.getDirectContent();
    Rotate rotationEvent = new Rotate();
    writer.setPageEvent(rotationEvent);
    for(int i=1; i<=reader.getNumberOfPages(); i++){
        float pageWidth = reader.getPageSizeWithRotation(i).getWidth();
        float pageHeight = reader.getPageSizeWithRotation(i).getHeight();
        doc.newPage();
        PdfImportedPage page = writer.getImportedPage(reader, i);
        if (rotation == 0) {
            cb.addTemplate(page, 1f, 0, 0, scaleHeight, x, y);
            //rotationEvent.setRotation(PdfPage.PORTRAIT);
        } else if (rotation == 90) {
            cb.addTemplate(page, 0, -1f, 1f, 0, 0, pageHeight);
            //rotationEvent.setRotation(PdfPage.LANDSCAPE);
        } else if (rotation == 180) {
            cb.addTemplate(page, 1f, 0, 0, -1f, pageWidth, pageHeight);
            //rotationEvent.setRotation(PdfPage.INVERTEDPORTRAIT);
        } else if (rotation == 270) {
            cb.addTemplate(page, 0, -1f, 1f, 0, 0, pageHeight);
            //cb.addTemplate(page, 0, 1f, -1f, 0, pageWidth, 0);
            //rotationEvent.setRotation(PdfPage.SEASCAPE);
        }
    }
    doc.close();
    return pdfOut;
}

我不明白你的代码,但是当我告诉别人时"please throw away your code and start anew",很多人觉得被冒犯了(虽然我肯定不是有意冒犯他们)。

我了解到您想缩放现有 PDF 的内容并保持旋转或将其删除(该部分并不完全清楚)。

因此我给你写了一个名为 ScaleDown 的例子,它可以用来缩小,保持方向。删除单行即可删除方向。

这个例子使用了一个页面事件(我把它命名为ScaleEvent):

public class ScaleEvent extends PdfPageEventHelper {

    protected float scale = 1;
    protected PdfDictionary pageDict;

    public ScaleEvent(float scale) {
        this.scale = scale;
    }

    public void setPageDict(PdfDictionary pageDict) {
        this.pageDict = pageDict;
    }

    @Override
    public void onStartPage(PdfWriter writer, Document document) {
        writer.addPageDictEntry(PdfName.ROTATE, pageDict.getAsNumber(PdfName.ROTATE));
        writer.addPageDictEntry(PdfName.MEDIABOX, scaleDown(pageDict.getAsArray(PdfName.MEDIABOX), scale));
        writer.addPageDictEntry(PdfName.CROPBOX, scaleDown(pageDict.getAsArray(PdfName.CROPBOX), scale));
    }
}

创建事件时,您传递一个值 scale 来定义比例因子。我将缩放比例应用于宽度和高度,如果您只想缩放高度,请随意调整它。

有关页面大小和旋转的信息存储在页面字典中。显然 ScaleEvent 需要原始文档的值,这就是为什么我们要为我们复制的每一页传递一个 pageDict

每次创建新页面时,我们都会copy/replace:

  • /Rotate 值。如果要去掉旋转,去掉这一行,
  • /MediaBox 值。这定义了页面的完整大小。
  • /CropBox 值。这定义了页面的可见大小。

由于我们要缩放页面,我们使用下面的scaleDown()方法:

public PdfArray scaleDown(PdfArray original, float scale) {
    if (original == null)
        return null;
    float width = original.getAsNumber(2).floatValue()
            - original.getAsNumber(0).floatValue();
    float height = original.getAsNumber(3).floatValue()
            - original.getAsNumber(1).floatValue();
    return new PdfRectangle(width * scale, height * scale);
}

假设我想将页面的宽度和高度缩小到原来宽度和高度的50%,那么我创建的事件是这样的:

PdfReader reader = new PdfReader(src);
float scale = 0.5f;
ScaleEvent event = new ScaleEvent(scale);
event.setPageDict(reader.getPageN(1));

我可以用我想要的任何页面大小定义一个 Document,因为无论如何 ScaleEvent 中的大小都会改变。显然,为了让它工作,我需要向 PdfWriter 实例声明事件:

Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(dest));
writer.setPageEvent(event);
document.open();

现在只需要遍历页面即可:

int n = reader.getNumberOfPages();
Image page;
for (int p = 1; p <= n; p++) {
    page = Image.getInstance(writer.getImportedPage(reader, p));
    page.setAbsolutePosition(0, 0);
    page.scalePercent(scale * 100);
    document.add(page);
    if (p < n) {
        event.setPageDict(reader.getPageN(p + 1));
    }
    document.newPage();
}
document.close();

我将导入的页面包装在 Image 中,因为我个人认为 Image class 可用的方法比定义 [=] 的参数更容易使用30=] 方法。如果您想使用 addTemplate() 而不是 Image,请随意使用;结果将是相同的(与您在评论中所写的相反,将页面包裹在图像中不会导致任何损失 "resolution" 因为所有文本仍然可以作为矢量数据使用)。

请注意,我会为每个新页面更新 pageDict

此代码将文件 orientations.pdf measuring 8.26 by 11.69 in and transforms it into the file scaled_down.pdf 尺寸为 4.13 x 5.85 英寸。

如果您希望所有页面都是纵向的,只需删除以下行:

writer.addPageDictEntry(PdfName.ROTATE, pageDict.getAsNumber(PdfName.ROTATE));