我在使用PDFBox时遇到麻烦。我在PDF中有一个空白页,我想在其中插入图像。因为我还处理带签名的PDF,所以所有更改都必须另存为“ saveIncremental”。
当我只插入一张图像时,一切都很好(图像已插入)。当我尝试在此PDF中插入另一张图像时,尚未插入该图像,并且在Adobe Acrobat Reader中打开该图像时,显示“此页面上存在错误。Adobe可能无法正确显示该页面...”。
奇怪的事情-PDF不仅是空白页,而且例如具有图像的空白页,一切正常(使用saveIncremental正确插入了第一张和第二张图像)。
插入和保存图像的代码:
PDImageXObject pdImage = PDImageXObject.createFromFile(tmpSig.getFileName(), doc);
PDPageContentStream contentStream = new PDPageContentStream(doc, tmpPage, PDPageContentStream.AppendMode.APPEND, true, true);
contentStream.drawImage(pdImage, finalX, (finalPageHeight - finalY - finalHeight), finalWidth, finalHeight);
contentStream.close();
// update before save
tmpPage.getCOSObject().setNeedToBeUpdated(true);
tmpPage.getResources().getCOSObject().setNeedToBeUpdated(true);
doc.getDocumentCatalog().getPages().getCOSObject().setNeedToBeUpdated(true);
doc.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true);
// save
doc.saveIncremental(new FileOutputStream(pdfFile));
所有可用文件here
使用PDFBox 2.0.7版,但我也尝试了最新版本(2.0.15),但没有帮助。
感谢所有创意!
编辑: 我尝试以此方式更新XObject和资源(在注释“保存之前更新”下添加了此代码):
pdImage.getCOSObject().setNeedToBeUpdated(true);
PDResources pdResources = tmpPage.getResources();
for (COSName name : pdResources.getXObjectNames()) {
pdResources.getXObject(name).getCOSObject().setNeedToBeUpdated(true);
}
问题仍然存在,什么都没有改变……
答案 0 :(得分:1)
除了您已经标记为已更新的字典之外
tmpPage.getCOSObject().setNeedToBeUpdated(true);
tmpPage.getResources().getCOSObject().setNeedToBeUpdated(true);
doc.getDocumentCatalog().getPages().getCOSObject().setNeedToBeUpdated(true);
doc.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true);
还请在资源字典中将 XObject 条目标记为已更新:
tmpPage.getResources().getCOSObject().getCOSDictionary(COSName.XOBJECT).setNeedToBeUpdated(true);
在原始PDF中,资源字典中还没有 XObject 条目。因此,它是重新生成的,因此被隐式标记为已更新。
在该其他文件中,资源字典中的 XObject 条目是直接对象,即它立即包含在资源字典中。
4 0 obj
<<
/Type /Page
/Resources <<
/ProcSets [/PDF /Text /ImageB /ImageC /ImageI]
/ExtGState <</G3 5 0 R /gs2 6 0 R /gs3 7 0 R>>
/XObject <</Im1 8 0 R /Im2 9 0 R>>
>>
/MediaBox [0 0 611.03998 864.95996]
/Contents [10 0 R 11 0 R 12 0 R 13 0 R 14 0 R]
/StructParents 0
/Parent 2 0 R
>>
endobj
因此,每当写入资源字典的新副本时,也会隐式写入 XObject 条目的新副本。
但是,在PDFBox在资源字典中创建 XObject 条目的文件中,PDFBox将其创建为间接对象,即在资源字典中 XObject 仅映射引用对象编号,并在带有该编号的对象中找到实际的输入字典。
2 0 obj
<<
/Type /Page
/Resources <<
/ProcSets [/PDF /Text /ImageB /ImageC /ImageI]
/ExtGState <</G3 3 0 R>>
/XObject 7 0 R
>>
/MediaBox [0 0 611.03998 864.95996]
/Contents [8 0 R 4 0 R 9 0 R]
/StructParents 0
/Parent 5 0 R
>>
endobj
7 0 obj
<<
/Im1 10 0 R
>>
endobj
因此,在写入资源字典的新副本时,在这种情况下不会写入 XObject 条目字典的隐式新副本。
顺便说一句,您当前的方法不会帮助您完成任务
因为我也使用签名的PDF,所以所有更改都必须另存为“ saveIncremental”。
将图像添加到页面内容是不允许对签名的PDF进行更改的,因此Adobe Reader仍将指示您的签名无效。有关签名后允许和不允许的更改的摘要,请查看this answer及其引用的文档。
您应该尝试在注释中添加图像。