修复PDF的方向以缩放它

时间:2015-03-19 18:28:33

标签: pdf rotation itext scanning

我遇到了一些包含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;
}

1 个答案:

答案 0 :(得分:2)

我不明白你的代码,但是当我告诉别人“请丢掉你的代码然后重新开始”时,很多人都觉得冒犯了(虽然我当然不打算冒犯他们)。

据我所知,您希望缩放现有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

每次创建新页面时,我们都会复制/替换:

  • /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类可用的方法比定义addTemplate()方法的参数更容易使用。如果您想使用addTemplate()代替Image,请随意执行此操作;结果将是相同的(与您在评论中写的相反,在图像中包装页面不会导致任何“分辨率”丢失,因为所有文本仍然可用作矢量数据)。

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

此代码将文件orientations.pdf测量为8.26乘11.69 in并将其转换为文件scaled_down.pdf,测量4.13乘5.85英寸。

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

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