将 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);
}
}
}
}
}
我有一些非常基本的代码,可以将图像插入现有的 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);
}
}
}
}
}