0

我很困惑,为什么 iTextsharp 无法从 pdf 读取或获取图像(pdf 从 msword、excel、powerpoint 转换而来)

这就是我所做的,我打开 msword 文件,然后将 msword 文件转换为 pdf,然后使用 iTextsharp 读取 pdf 文件,它无法识别 pdf 文件是否有图像或形状。

我也尝试从 powerpoint 到 pdf,然后读取 pdf 文件,它也不读取图像。

这是代码:在图像下方....已编辑...

这是无法提取的图像: 在此处输入图像描述

这是我前段时间测试的图像很好,我不知道为什么无法检测到其他图像,或者它错误。 在此处输入图像描述

截至目前,我将代码更改为:但也无法在圆形上检测到它的图像。

    For pn As Integer = 1 To pc
        Dim pg As PdfDictionary = pdfr.GetPageN(pn)
        Dim res As PdfDictionary = DirectCast(PdfReader.GetPdfObject(pg.Get(PdfName.RESOURCES)), PdfDictionary)
        Dim xobj As PdfDictionary = DirectCast(PdfReader.GetPdfObject(res.Get(PdfName.XOBJECT)), PdfDictionary)

        MessageBox.Show("THE ERROR IS HERE, IT BYPASS, SO XOBJ IS NOTHING IN THAT IMAGE")

        If xobj IsNot Nothing Then
            For Each name As PdfName In xobj.Keys
                Dim obj As PdfObject = xobj.Get(name)
                If obj.IsIndirect() Then
                    Dim tg As PdfDictionary = DirectCast(PdfReader.GetPdfObject(obj), PdfDictionary)
                    Dim type As PdfName = DirectCast(PdfReader.GetPdfObject(tg.Get(PdfName.SUBTYPE)), PdfName)
                    Dim XrefIndex As Integer = Convert.ToInt32(DirectCast(obj, PRIndirectReference).Number.ToString(System.Globalization.CultureInfo.InvariantCulture))
                    Dim pdfObj As PdfObject = pdfr.GetPdfObject(XrefIndex)
                    Dim pdfStrem As PdfStream = DirectCast(pdfObj, PdfStream)
                    If PdfName.IMAGE.Equals(type) Then
                        Dim bytes As Byte() = PdfReader.GetStreamBytesRaw(DirectCast(pdfStrem, PRStream))
                        If (bytes IsNot Nothing) Then
                            Dim strat As New ImageInfoTextExtractionStrategy()
                            iTextSharp.text.pdf.parser.PdfTextExtractor.GetTextFromPage(pdfr, pn, strat)
                        End If
                    End If
                End If
            Next
        End If
    Next
4

1 回答 1

3

为什么您当前的代码没有找到或提取这些形状:

笑脸图像和花朵图像在本质上完全不同:花朵图像是存储在 PDF 中的位图图像,作为子类型/Image的/XObject ( eXternal Object ),而笑脸图像是存储在 PDF 中的矢量图像作为一部分页面内容流作为路径定义和绘图操作的(不一定是连续的)序列。

您的代码仅搜索存储为外部对象的位图图像,并且以一种有点复杂的方式进行搜索:它首先使用低级方法扫描图像 xobject,并且只有在找到这样的 xobject 时,它才会使用 iText 高级提取功能。如果一开始只使用 iText 图像提取功能,它会不那么复杂,同时它还可以识别内联位图图像。

您可能想查看iText in Action — 第 2 版第 15 章Webified iTextSharp 示例,尤其是为此使用MyImageRenderListener.cs的 ExtractImages.cs。虽然该代码的灵感可以改进您当前的代码,但它还不能帮助您解决手头的问题。

使用 iText 查找或提取形状所需的操作:

不幸的是,您的问题并不完全清楚您实际想要达到的目标。

  1. 您是否只需要检测某个页面上是否有某些图像(位图或矢量图形)?
  2. 您是否需要有关图像的一些信息,例如页面上的大小或位置?
  3. 或者你真的想提取图像?

虽然使用上述 iText 高级提取功能可以很容易地为位图图形实现这些目标,但对于矢量图形它们却相当难以实现。

对于通用 PDF,它们实际上是不可能实现的,因为单个图形的绘图操作不需要在一起,更糟糕的是,同一页面上不同图形的绘图操作,页面上的下划线以及其他图形效果甚至可能以看似随机的顺序混合在一大堆操作中。

但是,在您的情况下,您有一个优势:Office 似乎可以正确标记 PDF 中的数字。这至少使得检测页面上不同(即不同标记)矢量图形的数量变得容易,并且还允许区分哪个绘图操作属于哪个图形。

因此,这里有一些关于如何为标记为示例 PDF 的 PDF 实现上述目标的指示。由于我自己没有使用 VB,所以我没有示例代码。但是由于您的示例代码表明您已经知道如何遵循对象引用以及如何解释 PDF 对象信息,这些指针应该足以说明方法。

1. 检测某个页面上是否有某个图像。

当页面内容被标记时,从文档目录中的/StructTreeRoot条目开始扫描结构层次就足够了(使用PdfReader.Catalog,选择其中的值PdfName.STRUCTTREEROOT,然后深入研究它)。

例如,对于样本的第 1 页(在 PDF 对象 4 0 中)(顶部有“1233”,下面有笑脸),您会发现一个带有字典的数组:

<<
  /Pg 4 0 R
  /K [0]
  /S /P
  /P 24 0 R
>>

<<
  /Pg 4 0 R
  /K [1]
  /Alt   ()
  /S /Figure
  /P 22 0 R
>>

每个都引用页面 ( /Pg 4 0 R)。第一个是/P类型,一个段落(你的“1233”),第二个是/Figure类型,一个数字(你的笑脸)。第二个元素的存在表示页面上存在图形。因此,使用这些数据已经实现了目标 1。

(有关详细信息,请参阅 PDF 规范ISO 32000-1:2008第 14.7 和 14.8 节。)

2. 检索图像上的一些信息,例如页面上的大小或位置。

为此,您必须提取负责创建相关图形的图形运算符。/K [1]当它被标记时,您必须在与上面/Figure字典中给出的标记内容 ID 相关联的标记内容块中提取运算符,即1

在内容流中,您会发现:

/P <</MCID 1>> BDC 0.31 0.506 0.741 rg
108.6 516.6 m
108.6 569.29 160.18 612 223.8 612 c
287.42 612 339 569.29 339 516.6 c
339 463.91 287.42 421.2 223.8 421.2 c
160.18 421.2 108.6 463.91 108.6 516.6 c
h
f*
[...]
108.6 516.6 m
108.6 569.29 160.18 612 223.8 612 c
287.42 612 339 569.29 339 516.6 c
339 463.91 287.42 421.2 223.8 421.2 c
160.18 421.2 108.6 463.91 108.6 516.6 c
h
S
EMC

/MCID 1的BDCEMC之间的这一部分包含您寻求的图形操作。如果您想获得有关它们所代表的图形的一些信息,则必须对其进行分析。

这是所有这一切的一个非常低级的视图,人们可能希望更高级别的 API 来检索它。

iText 确实具有用于文本和位图图像处理的类似操作的高级 API,使用parser命名空间类PdfReaderContentParser以及一些适当RenderListener的实现,例如您的ImageInfoTextExtractionStrategy.不幸的是,PdfReaderContentParser尚未正确预处理与矢量图形相关的运算符。

因此,要使用 iText 执行此操作,您要么必须扩展底层PdfContentStreamProcessor以添加缺少的预处理(这是可行的,因为该解析器类是使用单独的侦听器实现的,并且您可以轻松注册新的侦听器图形运算符);或者您必须检索页面内容并自己解析。

3. 提取图像。

由于 PDF 中的矢量图像使用 PDF 特定的矢量图形运算符,因此您首先必须决定要以哪种格式导出图像。除非您对原始 PDF 运算符感兴趣,否则您很可能需要一些库来帮助您创建所需格式的文件。

一旦决定了,您首先按照前面的说明提取有问题的图形运算符,然后将它们提供给该库以创建您选择的可导出图像。

于 2013-06-24T10:56:25.123 回答