PDFBox - "saveIncremental" 插入第二张图片后不起作用
PDFBox - "saveIncremental" after inserting second image doesn't work
我在使用 PDFBox 时遇到问题。我有一个 PDF 格式的空白页,我想在其中插入图像。因为我还处理签名的 PDF,所以所有更改都必须保存为 "saveIncremental"。
当我只插入一张图片时一切正常(图片已插入)。当我尝试在此 PDF 中插入另一张图片时,它没有被插入,并且在 Adobe Acrobat Reader 中打开时显示 "An error exists on this page. Adobe may not display the page correctly ...".
奇怪的事情 - 当 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 和 Resources(在评论 "update before save" 下添加了这段代码):
pdImage.getCOSObject().setNeedToBeUpdated(true);
PDResources pdResources = tmpPage.getResources();
for (COSName name : pdResources.getXObjectNames()) {
pdResources.getXObject(name).getCOSObject().setNeedToBeUpdated(true);
}
问题依旧,没有任何改变...
除了您已经标记为已更新的词典之外
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 条目字典的隐式新副本。
顺便说一句,您当前的方法不会帮助您完成任务
Because I also work with signed PDFs, all changes have to be saved as "saveIncremental".
将图像添加到页面内容不允许对已签名的 PDF 进行更改,因此 Adobe Reader 仍会指示您的签名无效。有关签名后允许和不允许更改的摘要,请查看 this answer 和其中引用的文档。
您应该尝试在注释中添加图片。
我在使用 PDFBox 时遇到问题。我有一个 PDF 格式的空白页,我想在其中插入图像。因为我还处理签名的 PDF,所以所有更改都必须保存为 "saveIncremental"。
当我只插入一张图片时一切正常(图片已插入)。当我尝试在此 PDF 中插入另一张图片时,它没有被插入,并且在 Adobe Acrobat Reader 中打开时显示 "An error exists on this page. Adobe may not display the page correctly ...".
奇怪的事情 - 当 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 和 Resources(在评论 "update before save" 下添加了这段代码):
pdImage.getCOSObject().setNeedToBeUpdated(true);
PDResources pdResources = tmpPage.getResources();
for (COSName name : pdResources.getXObjectNames()) {
pdResources.getXObject(name).getCOSObject().setNeedToBeUpdated(true);
}
问题依旧,没有任何改变...
除了您已经标记为已更新的词典之外
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 条目字典的隐式新副本。
顺便说一句,您当前的方法不会帮助您完成任务
Because I also work with signed PDFs, all changes have to be saved as "saveIncremental".
将图像添加到页面内容不允许对已签名的 PDF 进行更改,因此 Adobe Reader 仍会指示您的签名无效。有关签名后允许和不允许更改的摘要,请查看 this answer 和其中引用的文档。
您应该尝试在注释中添加图片。