Java 将PDFBox从版本2.08更新到2.12/2.16后,使用PDPageContentStream.drawImage绘制某些16位透明图像时出现问题
我有一些将图像插入现有PDF的基本代码:Java 将PDFBox从版本2.08更新到2.12/2.16后,使用PDPageContentStream.drawImage绘制某些16位透明图像时出现问题,java,pdfbox,Java,Pdfbox,我有一些将图像插入现有PDF的基本代码: public class InsertImg { public static void main (final String[] args) throws IOException { PDDocument document = PDDocument.load (new File ("original.pdf")); PDPage page = document.getPage (0); b
public class InsertImg
{
public static void main (final String[] args) throws IOException
{
PDDocument document = PDDocument.load (new File ("original.pdf"));
PDPage page = document.getPage (0);
byte[] imgBytes = Files.readAllBytes (Paths.get ("signature.png"));
PDImageXObject pdImage = PDImageXObject.createFromByteArray (document, imgBytes, "name_of_image");
PDPageContentStream content = new PDPageContentStream (document, page, AppendMode.APPEND, true, true);
content.drawImage (pdImage, 50.0f, 350.0f, 100.0f, 25.0f);
content.close ();
document.save (new File ("result.pdf"));
document.close ();
}
}
虽然该代码在PdfBox 2.08中对所有图像文件都能正常工作,但它在2.012版本下仅对某些图像有效,不再适用于所有图像文件
(背景:我们希望将签名图像插入现有和已生成的信函中。所有签名都是使用相同的软件生成的。在版本2.12中,不能再插入所有签名。在版本2.08中,可以插入所有签名)
无法在Acrobat Reader中打开生成的pdf文件“result.pdf”。Acrobat Reader仅显示原始pdf“original.pdf”,但不显示签名图像。上面写着“页面错误,请联系pdf的创建者”
但是,大多数图像都可以插入,因此问题很可能取决于所使用的图像
这些图像都是正常的,它们是png的,并且通过各种成像程序进行检查和验证,例如gimp或irfanview
此外,上面的代码在PdfBox 2.08中始终运行良好。将PdfBox更新到2.12版后,问题出现了,最新的2.16版仍然会产生错误。仍然在同一个图像文件上,而不是在所有图像文件上
注意:当我在注释中输入以下行时,AcrobatReader中没有显示错误,所以问题一定在drawImage中的某个地方
// content.drawImage (pdImage, 50.0f, 350.0f, 100.0f, 25.0f);
代码的其余部分似乎很好
此外,我刚刚尝试从一个空PDF开始,而不是加载一个已经生成的PDF
PDDocument document = new PDDocument ();
PDPage page = new PDPage ();
document.addPage (page);
[...]
这里的问题仍然是一样的,所以这个问题不依赖于底层的PDF。这是一个错误,因为2.0.12版(使用无损工厂创建的灰色图像的错误备用颜色空间)已在中修复,并将在2.0.17版中发布。显示适用于除Adobe Reader之外我测试过的所有查看器,尽管在ICC颜色空间可用时不应使用备用颜色空间。下面是一些修复PDF的代码(假设图像仅位于页面的顶层,即不考虑其他结构中的图像)
for(PDPage:doc.getPages())
{
PDResources=page.getResources();
if(资源==null)
{
继续;
}
for(COSName名称:resources.getXObjectNames())
{
PDXObject xObject=resources.getXObject(名称);
if(PDImageXObject的xObject实例)
{
PDImageXObject img=(PDImageXObject)xObject;
if(img.getColorSpace()实例为PDICCBased)
{
PDICCBased icc=(PDICCBased)img.getColorSpace();
if(icc.getNumberOfComponents()==1&&PDDeviceRGB.INSTANCE.equals(icc.getAlternateColorSpace())
{
列表=新的ArrayList();
添加(PDDeviceGray.INSTANCE);
icc.SetAlternateColorSpace(列表);
}
}
}
}
}
您自己说“问题很可能取决于所使用的图像。”因此,很可能需要示例图像来分析问题。是的,当然。但是,由于图像是有效的签名,我只能以个人方式提供示例,例如通过电子邮件。请发送给snafu dot de的tilman。在这几年中,已经进行了很多优化。
for (PDPage page : doc.getPages())
{
PDResources resources = page.getResources();
if (resources == null)
{
continue;
}
for (COSName name : resources.getXObjectNames())
{
PDXObject xObject = resources.getXObject(name);
if (xObject instanceof PDImageXObject)
{
PDImageXObject img = (PDImageXObject) xObject;
if (img.getColorSpace() instanceof PDICCBased)
{
PDICCBased icc = (PDICCBased) img.getColorSpace();
if (icc.getNumberOfComponents() == 1 && PDDeviceRGB.INSTANCE.equals(icc.getAlternateColorSpace()))
{
List<PDColorSpace> list = new ArrayList<>();
list.add(PDDeviceGray.INSTANCE);
icc.setAlternateColorSpaces(list);
}
}
}
}
}