【问题标题】:How to translate x, y origin of a PDPage?如何翻译 PDPage 的 x、y 原点?
【发布时间】:2014-01-09 09:49:59
【问题描述】:

我是 Apache 的 PDFBox 的新手。我使用的是 2.0.0 版本,取自 SVN 存储库。

其实我尝试增加 PDPage 对象的 cropbox。好吧,没有挑战。但页面内容仍保留在 cropbox 的左下角。我希望它位于新的 cropbox 空间的中心。

我了解所有内容都绝对定位在 PDF 中。所以我的问题是:有没有办法使用 PDFBox 来翻​​译我的 PDPage 或内容元素的原点 (x, y)?

问候
汉斯

【问题讨论】:

  • 只改变调整裁剪矩形的方式会更容易。您的措辞建议您通过更改 UpperRightX/Y 来设置宽度和高度。尝试更改 LowerLeftX/Y。
  • 已经做到了。但是改变 LowerLeft 只会改变裁剪框在媒体框中的位置。页面内容保留在裁剪框中的位置。
  • 请显示您用于裁剪框操作的中心代码。
  • @ mkl,请。见下文

标签: coordinates pdfbox


【解决方案1】:

操作裁剪框的核心代码如下:

@Override
protected void treeNodeChanged(PDFTreeNode node)
{
    if (node instanceof PDFFloatNode)
    {
        PDFFloatNode nodeF = (PDFFloatNode)node;
        String strDataKey = node.getDataKey();
        if ("x".equals(strDataKey))
        {
            m_rect.setLowerLeftX(nodeF.getFloat());
        }
        else if ("y".equals(strDataKey))
        {
            m_rect.setLowerLeftY(nodeF.getFloat());
        }
        else if ("width".equals(strDataKey))
        {
            m_rect.setUpperRightX(nodeF.getFloat());
        }
        else if ("height".equals(strDataKey))
        {
            m_rect.setUpperRightY(nodeF.getFloat());
        }
    }

    if (m_parent != null)
    {
        m_parent.treeNodeChanged(node);
    }
}

其中 m_rect 是 PDRectangle 的一个实例。事实上,这些信息对你没有帮助,@mkl。在这之间,我找到了解决问题的信息(我希望如此)。 PDFBox中有一个明显不知道的操作。

<</PageOffset [-20 20]>> setpagedevice

现在我正在寻找一种将其实现到 PDF 中的方法。

谢谢 汉斯

【讨论】:

  • 事实上,这些信息对你没有帮助 - 正确。我不知道它适用于什么......
【解决方案2】:

Pageoffset 字典条目不是很有帮助。它可以用作 GhostScript 的参数。但是 GS 并没有真正创建字典条目。相反,它会抵消所有页面的内容。 PDFBox 中不存在的功能。

我找到了使用 LayerUtility 的解决方案:

    PDDocument docIn = null;
    try
    {
        docIn = PDDocument.load("./pdf/Test1.pdf");

        float fBorder = 10 * MM_TO_UNITS; // Arbitrary 10 mm

        PDDocument docOut = new PDDocument();

        PDPage pageIn = (PDPage)docIn.getDocumentCatalog().getPages().getKids().get(0);

        PDRectangle rectCrop = pageIn.findCropBox();

        PDPage pageClone = clonePage(docOut, pageIn, true),
            pageOut = new PDPage(
                    new PDRectangle(rectCrop.getWidth() + 2 * fBorder, rectCrop.getHeight() + 2 * fBorder)
                    );

        docOut.addPage(pageOut);
        PDPageContentStream stream = new PDPageContentStream(docOut, pageOut);
        stream.close();

        LayerUtility lu = new LayerUtility(docOut);
        lu.wrapInSaveRestore(pageOut);

        PDXObjectForm xobj = lu.importPageAsForm(docIn, pageClone);

        AffineTransform at = new AffineTransform();

        // That's the point where x,y offset takes place
        at.setToTranslation(fBorder, fBorder);

        lu.appendFormAsLayer(pageOut, xobj, at, "layerx");

        docOut.addPage(pageOut);
        docOut.save("./pdf/Test1out.pdf");
    }
    finally
    {
        if (docIn != null)
        {
            docIn.close();
        }
    }

我对此不太满意。因为它改变了页面结构。但至少我有一个解决方案。

问候 汉斯

【讨论】:

    【解决方案3】:

    第一种方法是像这样简单地更改裁剪框:

        PDDocument document = PDDocument.load(new File("data/test.pdf"));
        PDDocumentCatalog catalog = document.getDocumentCatalog();
        @SuppressWarnings("unchecked")
        List<PDPage> pages = catalog.getAllPages();
        float expand = 72;
    
        for (PDPage page : pages)
        {
            PDRectangle cropBox = page.findCropBox();
            PDRectangle newCropBox = new PDRectangle();
            newCropBox.setLowerLeftX(cropBox.getLowerLeftX() - expand);
            newCropBox.setLowerLeftY(cropBox.getLowerLeftY() - expand);
            newCropBox.setUpperRightX(cropBox.getUpperRightX() + expand);
            newCropBox.setUpperRightY(cropBox.getUpperRightY() + expand);
            page.setCropBox(newCropBox);
        }
    
        document.save("data/out/test-expand-crop-simple.pdf");
    

    这仅在某些时候有效,因为根据规范 ISO 32000-1,第 14.11.2 节 页面边界

    裁剪、出血、修剪和艺术框通常不得超出媒体框的边界。如果他们这样做了,他们就会被有效地简化为与媒体框的交集。

    (另见this answer

    因此,我们必须确保裁剪框即使在放大后仍然适合媒体框,例如像这样:

        PDDocument document = PDDocument.load(new File("data/test.pdf"));
        PDDocumentCatalog catalog = document.getDocumentCatalog();
        @SuppressWarnings("unchecked")
        List<PDPage> pages = catalog.getAllPages();
        float expand = 72;
    
        for (PDPage page : pages)
        {
            PDRectangle cropBox = page.findCropBox();
            PDRectangle newCropBox = new PDRectangle();
            newCropBox.setLowerLeftX(cropBox.getLowerLeftX() - expand);
            newCropBox.setLowerLeftY(cropBox.getLowerLeftY() - expand);
            newCropBox.setUpperRightX(cropBox.getUpperRightX() + expand);
            newCropBox.setUpperRightY(cropBox.getUpperRightY() + expand);
            page.setCropBox(newCropBox);
    
            PDRectangle mediaBox = page.findMediaBox();
            PDRectangle newMediaBox = new PDRectangle();
            newMediaBox.setLowerLeftX(mediaBox.getLowerLeftX() - expand);
            newMediaBox.setLowerLeftY(mediaBox.getLowerLeftY() - expand);
            newMediaBox.setUpperRightX(mediaBox.getUpperRightX() + expand);
            newMediaBox.setUpperRightY(mediaBox.getUpperRightY() + expand);
            page.setMediaBox(newMediaBox);
        }
    
        document.save("data/out/test-expand-crop-and-media.pdf");
    

    【讨论】:

    • 非常感谢您的工作,@mkl。这有很大帮助。 Adobe Reader 显示的结果完全正确。现在我必须找出我的 PageDrawer 实现中出了什么问题。
    • 好的,我的 PageDrawer 现在也可以正常工作了。我找到了出错的原因。我将 MediaBox 视为坐标系的来源。所以我在 CropBox 中的更改总是在错误的方向上。非常感谢汉斯
    • @Hans 那太好了。如果这基本上回答了原始问题,请接受为答案(在答案的左侧,您可以将其标记为已接受)。
    【解决方案4】:

    要增加 CropBox,您可以像这样设置 MediaBox:

    PDRectangle box = new PDRectangle(pageWidth, pageHeight);
    page.setMediaBox(box); // MediaBox > BleedBox > TrimBox/CropBox
    

    【讨论】:

    • 这与问题的关系如何?特别是为什么要更改 MediaBox 通常要更改 CropBox
    • “我尝试增加 PDPage 对象的裁剪框”。 MediaBox 是 pdf 的外部限制。它在其他 sdk 中可能无法以这种方式工作,但对于 pdfbox 它确实有效
    • “但对于 pdfbox 来说它确实有效” - 一般不会。裁剪框默认为媒体框。因此,如果没有明确的裁剪框,您的代码会通过此默认值进行更改。但是如果有明确的裁剪框,一般只改变媒体框是不够的。
    • 不完全正确。我不是 PDF 专家,但根据我的经验,pdfbox 的实现是它的工作原理。除非您首先更改媒体框,否则您无法增加裁剪框 - 而且它会将裁剪框设置为媒体框的大小,从而增加裁剪框的大小。
    • “除非您先更改媒体框,否则您无法增加裁剪框” - 您无法有效地将裁剪框增加到媒体框之外。真的。但是您的答案根本没有触及裁剪框。 “它将裁剪框设置为媒体框的大小” - 不,我只是查看了来源,它使裁剪框保持不变。 (不过,如前所述,如果没有明确设置裁剪框,它默认为媒体框。您的 cmets 听起来就像您只需要在没有明确裁剪框设置的情况下处理此类 PDF。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-14
    • 1970-01-01
    • 2012-01-29
    • 2012-01-27
    • 2011-11-10
    • 2012-02-13
    • 2022-11-26
    相关资源
    最近更新 更多