使用pdfbox从单独的pdf(不同页面大小)添加页面作为图层 [英] Add page as layer from separate pdf(different page size) using pdfbox

查看:1681
本文介绍了使用pdfbox从单独的pdf(不同页面大小)添加页面作为图层的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果页面大小不同,如何将外部pdf文档中的页面添加到目标pdf?
以下是我想要完成的事情:

How can I add a page from external pdf doc to destination pdf if pages have different sizes? Here is what I'd like to accomplish:

我尝试使用LayerUtility(就像在这个例子中一样 PDFBox LayerUtility - 将图层导入现有PDF ,但是一旦我从外部pdf导入页面,该过程就会挂起:

I tried to use LayerUtility (like in this example PDFBox LayerUtility - Importing layers into existing PDF), but once I import page from external pdf the process hangs:

PDDocument destinationPdfDoc = PDDocument.load(fileInputStream);
PDDocument externalPdf = PDDocument.load(EXTERNAL PDF);

List<PDPage> destinationPages = destinationPdfDoc.getDocumentCatalog().getAllPages();

LayerUtility layerUtility = new LayerUtility(destinationPdfDoc);

// process hangs here
PDXObjectForm firstForm = layerUtility.importPageAsForm(externalPdf, 0);

AffineTransform affineTransform = new AffineTransform();
layerUtility.appendFormAsLayer(destinationPages.get(0), firstForm, affineTransform, "external page");


destinationPdfDoc.save(resultTempFile);

destinationPdfDoc.close();
externalPdf.close();

我做错了什么?

推荐答案

PDFBox依赖



主要问题是PDFBox有三个核心组件和一个必需依赖项。缺少一个核心组件。

在评论中,OP澄清了


实际上,进程没有挂起,文件根本就没有创建。

Actually process doesn't hangs, the file is just not created at all.

这听起来似乎有可能异常或错误,尝试将代码封装为 try {...} catch(Throwable t){t.printStackTrace();在聊天中提出了。事实上,

As this sounds like there might have been an exception or error, trying to envelope the code as a try { ... } catch (Throwable t) { t.printStackTrace(); } block has been proposed in chat. And indeed,

java.lang.NoClassDefFoundError: org/apache/fontbox/util/BoundingBox 
    at org.apache.pdfbox.util.LayerUtility.importPageAsForm(LayerUtility.java:203) 
    at org.apache.pdfbox.util.LayerUtility.importPageAsForm(LayerUtility.java:135) 
    at ...

事实证明,OP的设置中缺少fontbox.jar。

As it turned out, fontbox.jar was missing from the OP's setup.

此处描述了PDFBox版本1.8.x依赖项。特别是有三个核心组件 pdfbox fontbox jempbox 所有这些组件都应存在于同一版本中,并且需要依赖公共日志记录

The PDFBox version 1.8.x dependencies are described here. Especially there are the three core components pdfbox, fontbox, and jempbox all of which shall be present in the same version, and there is the required dependency commons-logging.

一旦添加了缺失的组件,样本就能正常工作。

As soon as the missing component had been added, the sample worked properly.

导入的页面可以通过<$ c $中的翻译定位在目标页面上c> AffineTransform 参数。该参数还允许其他变换,例如,缩放,旋转,镜像,倾斜,... *

The imported page can be positioned on the target page by means of a translation in the AffineTransform parameter. This parameter also allows for other transformations, e.g. to scale, rotate, mirror, skew,...*

对于原始样本文件此PDF页面

For the original sample files this PDF page

被添加到此页面上

导致此页

OP然后想知道


如何定位导入的图层

how to position the imported layer

<$> b $中的参数c $ c> layerUtility.appendFormAsLayer call是 AffineTransform affineTransform 。 OP在这里使用了新的AffineTransform(),它创建了一个单位矩阵,这又使得源页面被添加到坐标系的原点,在本例中是在底部。

The parameter for that in the layerUtility.appendFormAsLayer call is the AffineTransform affineTransform. The OP used new AffineTransform() here which creates an identity matrix which in turn causes the source page to be added at the origin of coordinate system, in this case at the bottom.

使用翻译代替身份,例如

By using a translation instead of the identity, e.g

PDRectangle destCrop = destinationPages.get(0).findCropBox();
PDRectangle sourceBox = firstForm.getBBox();
AffineTransform affineTransform = AffineTransform.getTranslateInstance(0, destCrop.getUpperRightY() - sourceBox.getHeight());

可以将源页面放在别处,例如在顶部:

one can position the source page elsewhere, e.g. at the top:

不幸的是,结果是 layerUtility.appendFormAsLayer 将表单附加到页面而不重置图形上下文。

Unfortunately it turns out that layerUtility.appendFormAsLayer appends the form to the page without resetting the graphics context.

layerUtility.appendFormAsLayer 使用此代码添加其他内容流:

layerUtility.appendFormAsLayer uses this code to add an additional content stream:

PDPageContentStream contentStream = new PDPageContentStream(
        targetDoc, targetPage, true, !DEBUG);

不幸的是,此构造函数生成的内容流将继承现有内容末尾的图形状态目标页面。这尤其意味着用户空间坐标系可能不再处于其默认状态。一些软件例如镜像坐标系使y坐标向下增加。

Unfortunately a content stream generated by this constructor inherits the graphics state as is at the end of the existing content of the target page. This especially means that the user space coordinate system may not be in its default state anymore. Some software e.g. mirrors the coordinate system to have y coordinates increasing downwards.

如果相反

PDPageContentStream contentStream = new PDPageContentStream(
        targetDoc, targetPage, true, !DEBUG, true);

已被使用,图形状态将被重置为其默认状态,因此,已知。

had been used, the graphics state would have been reset to its default state and, therefore, be known.

因此,这种方法本身不能以受控方式用于任意输入。

By itself, therefore, this method is not usable in a controlled manner for arbitrary input.

幸运但是, LayerUtility 还有一个方法 wrapInSaveRestore(PDPage)通过操纵给定的内容来克服这个弱点页面在结尾处具有默认图形状态。

Fortunately, though, the LayerUtility also has a method wrapInSaveRestore(PDPage) to overcome this weakness by manipulating the content of the given page to have the default graphics state at the end.

因此,应该替换

layerUtility.appendFormAsLayer(destinationPages.get(0), firstForm, affineTransform, "external page");

by

PDPage destPage = destinationPages.get(0);
layerUtility.wrapInSaveRestore(destPage);
layerUtility.appendFormAsLayer(destPage, firstForm, affineTransform, "external page");

这篇关于使用pdfbox从单独的pdf(不同页面大小)添加页面作为图层的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆