【问题标题】:pdfbox and itext extracting image with incorrect dpipdfbox和itext提取dpi不正确的图像
【发布时间】:2015-01-25 19:08:34
【问题描述】:

当我使用 pdfbox 提取图像时,某些 PDF 的图像 dpi 不正确。当我使用 Photoshop 或 Acrobat Reader Pro 提取图像时,我可以使用 windows 照片查看器看到图像的 dpi 为 200,但是当我使用 pdfbox 提取图像时,dpi 为 72。

为了提取图像,我使用以下代码: Not able to extract images from PDFA1-a format document

当我检查日志时,我看到一个不寻常的条目: 2015-01-23-main--DEBUG-org.apache.pdfbox.util.TIFFUtil:

     <?xml version="1.0" encoding="UTF-8"?><javax_imageio_jpeg_image_1.0>
      <JPEGvariety>
    <app0JFIF majorVersion="1" minorVersion="2" resUnits="0" Xdensity="1" Ydensity="1" thumbWidth="0" thumbHeight="0"/>
  </JPEGvariety>
  <markerSequence>
    <dqt>
      <dqtable elementPrecision="0" qtableId="0"/>
      <dqtable elementPrecision="0" qtableId="1"/>
    </dqt>
    <dht>
      <dhtable class="0" htableId="0"/>
      <dhtable class="0" htableId="1"/>
      <dhtable class="1" htableId="0"/>
      <dhtable class="1" htableId="1"/>
    </dht>
    <sof process="0" samplePrecision="8" numLines="0" samplesPerLine="0" numFrameComponents="3">
      <componentSpec componentId="1" HsamplingFactor="2" VsamplingFactor="2" QtableSelector="0"/>
      <componentSpec componentId="2" HsamplingFactor="1" VsamplingFactor="1" QtableSelector="1"/>
      <componentSpec componentId="3" HsamplingFactor="1" VsamplingFactor="1" QtableSelector="1"/>
    </sof>
    <sos numScanComponents="3" startSpectralSelection="0" endSpectralSelection="63" approxHigh="0" approxLow="0">
      <scanComponentSpec componentSelector="1" dcHuffTable="0" acHuffTable="0"/>
      <scanComponentSpec componentSelector="2" dcHuffTable="1" acHuffTable="1"/>
      <scanComponentSpec componentSelector="3" dcHuffTable="1" acHuffTable="1"/>
    </sos>
  </markerSequence>
</javax_imageio_jpeg_image_1.0>

我试图用谷歌搜索,但我可以通过这个日志找出 pdfbox 的含义。这是什么意思?

您可以从此链接下载一个包含此问题的示例 pdf: http://myslams.com/test/1.pdf

我什至尝试过 itext,但它正在提取 96 dpi 的图像。

我做错了吗?还是pdfbox和itext有这个限制?

【问题讨论】:

  • 通常 dpi 在 PDF 中的位图上下文中没有意义。
  • 你是说我上面提到的示例pdf包含位图图像。
  • 从 PDF 中提取图像之后期望图像具有 DPI 值是没有意义的。如果你想知道图像的 DPI当它还在 PDF 中时,你需要阅读这个问题的答案:Getting Image DPI in PDF files using iText你不应该声称 iText 和 PdfBox 给了你错误DPI。是你对 DPI 的理解是错误的。
  • 另外,当您发布示例 PDF 时,请确保它没有显示:在此服务器上找不到请求的 URL /test/1.pdf。
  • @bruno 由于机密性原因,我不得不删除 pdf 文件。抱歉...明天将提供示例 PDF 文件。

标签: java itext pdfbox


【解决方案1】:

经过一番挖掘,我找到了你的 1.pdf。因此,...

PDFBox

this recent answer @Tilman 的 cmets 中,您正在讨论 this older answer,其中 @Tilman 指向 PrintImageLocations PDFBox 示例。我为您的文件运行它并得到:

Processing page: 0
*******************************************************************
Found image [Im0]
position = 0.0, 0.0
size = 1704px, 888px
size = 613.44, 319.68
size = 8.52in, 4.44in
size = 216.408mm, 112.776mm

Processing page: 1
*******************************************************************
Found image [Im0]
position = 0.0, 0.0
size = 1704px, 2800px
size = 613.44, 1008.0
size = 8.52in, 14.0in
size = 216.408mm, 355.6mm

Processing page: 2
*******************************************************************
Found image [Im0]
position = 0.0, 0.0
size = 1704px, 2800px
size = 613.44, 1008.0
size = 8.52in, 14.0in
size = 216.408mm, 355.6mm

Processing page: 3
*******************************************************************
Found image [Im0]
position = 0.0, 0.0
size = 1704px, 1464px
size = 613.44, 527.04
size = 8.52in, 7.3199997in
size = 216.408mm, 185.928mm

在所有页面上,x 和 y 方向的分辨率均为 200 dpi(1704px / 8.52in = 888px / 4.44in = 2800px / 14.0in = 1464px / 7.32in = 200 dpi)。

所以 PDFBox 会为您提供所需的 dpi 值。

(@Tilman:该示例的当前 2.0.0-SNAPSHOT 版本返回完全废话;您可能需要解决此问题。)

iText

该 PDFBox 示例的简化 iText 版本如下:

public void printImageLocations(InputStream stream) throws IOException
{
    PdfReader reader = new PdfReader(stream);
    PdfReaderContentParser parser = new PdfReaderContentParser(reader);
    ImageRenderListener listener = new ImageRenderListener();

    for (int page = 1; page <= reader.getNumberOfPages(); page++)
    {
        System.out.printf("\nPage %s:\n", page);
        parser.processContent(page, listener);
    }
}

static class ImageRenderListener implements RenderListener
{
    public void beginTextBlock() { }
    public void renderText(TextRenderInfo renderInfo) { }
    public void endTextBlock() { }

    public void renderImage(ImageRenderInfo renderInfo)
    {
        try
        {
            PdfDictionary imageDict = renderInfo.getImage().getDictionary();

            float widthPx = imageDict.getAsNumber(PdfName.WIDTH).floatValue(); 
            float heightPx = imageDict.getAsNumber(PdfName.HEIGHT).floatValue();
            float widthUu = renderInfo.getImageCTM().get(Matrix.I11);
            float heigthUu = renderInfo.getImageCTM().get(Matrix.I22);

            System.out.printf("Image %.0fpx*%.0fpx, %.0fuu*%.0fuu, %.2fin*%.2fin\n", widthPx, heightPx, widthUu, heigthUu, widthUu/72, heigthUu/72);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
}

(注意:我假设图像未旋转且未倾斜。)

您的文件的结果:

Page 1:
Image 1704px*888px, 613uu*320uu, 8,52in*4,44in

Page 2:
Image 1704px*2800px, 613uu*1008uu, 8,52in*14,00in

Page 3:
Image 1704px*2800px, 613uu*1008uu, 8,52in*14,00in

Page 4:
Image 1704px*1464px, 613uu*527uu, 8,52in*7,32in

因此,一直都是 200dpi。因此,iText 也可以为您提供所需的 dpi 值。

您的代码

显然,code you referenced 没有机会报告在 PDF 上下文中合理的 dpi 值,因为它只提取资源中找到的图像,而忽略各个图像如何资源在页面上使用

当作者在页面内容中使用图像资源时,可以以任何方式拉伸、旋转、倾斜……。

顺便说一句,dpi 值只有在作者没有倾斜且仅旋转 90° 倍数时才有意义。

【讨论】:

  • 我使用 Maven 自动提供所需的依赖项。 Maven 坐标是&lt;dependency&gt;&lt;groupId&gt;org.apache.pdfbox&lt;/groupId&gt;&lt;artifactId&gt;pdfbox-examples&lt;/artifactId&gt;&lt;version&gt;1.8.8&lt;/version&gt;&lt;/dependency&gt;
  • thx .... 我正在检查答案。他们是我需要检查的少数 PDF 样本,我会回复您。
  • @mkl:感谢您提请我注意。已在 PDFBOX-2635 中修复。 (希望)
  • @sameersingh 早些时候,当我尝试运行 PrintImageLocations.java 示例时,我遇到了很多导入问题 - 很可能是版本不匹配,也许你得到了当前 PDFBox 的示例开发版本 2.0.0 快照。我建议使用 maven 来收集所需的依赖项。
  • @sameersingh 另一个让生活更轻松的技巧是使用 pdfbox-app 和 preflight-app。但除此之外,maven 真的很有用。我们 PDFBox 使用它。
猜你喜欢
  • 1970-01-01
  • 2011-07-25
  • 1970-01-01
  • 1970-01-01
  • 2011-10-23
  • 2018-02-04
  • 1970-01-01
  • 2018-05-02
  • 2018-09-17
相关资源
最近更新 更多