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

Problem drawing some 16bit transparent images with PDPageContentStream.drawImage after updating PDFBox from Version 2.08 to 2.12/2.16

我有一些非常基本的代码,可以将图像插入现有的 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 版本中可以插入所有签名)。

生成的 pdf 文件 "result.pdf" 无法在 Acrobat Reader 中打开。 Acrobat Reader 仅显示原始 pdf "original.pdf",但不显示签名图像。它说 "error in page. please contact the creator of the pdf".

但是,大多数图片都可以插入,所以问题很可能取决于所使用的图片。

图像都没有问题,它们是 png 格式的,并且使用各种成像程序进行了检查和验证,例如gimp 或 irfanview.

此外,上面的代码在 PdfBox 2.08 上一直运行良好。将 PdfBox 更新到 2.12 版后,问题出现了,而且最新的 2.16 版仍然产生错误。仍然在相同的图像文件上,但仍然不在所有图像文件上。

注意:当我将以下行添加到注释中时,Acrobat 中没有错误显示 Reader,因此问题一定出在 drawImage 中。

    // content.drawImage (pdImage, 50.0f, 350.0f, 100.0f, 25.0f);

其余代码似乎没问题。

另外,我刚刚尝试从一个空的 PDF 文件开始,而不是加载一个已经生成的文件。

    PDDocument document = new PDDocument ();
    PDPage page = new PDPage ();
    document.addPage (page);
    [...]

这里的问题还是一样,所以问题不依赖于底层PDF。

这是自 2.0.12 以来的一个错误(使用 LosslessFactory 创建的灰色图像的替代颜色空间错误)已在 PDFBOX-4607 中修复并将在 2.0.17 版本中修复。显示适用于我测试过的所有查看器,Adobe Reader 除外,尽管当 ICC 色彩空间可用时不应使用备用色彩空间。这是修复 PDF 的一些代码(假设图像仅位于页面的顶层,即不考虑其他结构中的图像)

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