Java 将PDFBox从版本2.08更新到2.12/2.16后,使用PDPageContentStream.drawImage绘制某些16位透明图像时出现问题

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

我有一些将图像插入现有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);

        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);
                }
            }
        }
    }
}