我非常困惑,为什么iTextsharp无法从pdf读取或获取图像(pdf转换自msword,excel,powerpoint)
这是我做的,我打开msword文件,然后将msword文件转换为pdf,然后使用iTextsharp读取pdf文件,它不能识别pdf文件是否有图像或形状。< / p>
我也试过从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
答案 0 :(得分:3)
为什么您当前的代码无法找到或提取这些形状:
笑脸图像和花朵图像在性质上完全不同:花朵图像是存储在PDF中的位图图像,作为 / XObject ( eXternal Object )子类型 / Image ,而笑脸是作为页面内容流的一部分存储在PDF中的矢量图像,作为路径定义和绘图操作的(不一定是连续的)序列。
您的代码仅搜索存储为外部对象的位图图像,并且它以一种有点复杂的方式执行:它首先使用低级方法扫描图像xobjects,并且只有当它找到这样的xobject时,它才会使用iText高级提取功能。如果它仅使用iText图像提取功能开始,它就不那么复杂了,同时它也会识别内联的位图图像。
您可能需要查看iText in Action — 2nd Edition第15章Webified iTextSharp Examples,尤其是使用ExtractImages.cs MyImageRenderListener.cs的ISO 32000-1:2008。虽然该代码的灵感可以改善您当前的代码,但它仍然无法帮助您处理手头的问题。
使用iText查找或提取形状时需要做些什么:
不幸的是,你的问题并不完全清楚你实际想要实现的目标。
虽然使用前面提到的iText高级提取功能可以很容易地为位图图形实现这些目标,但它们很难用于矢量图形。
对于通用PDF,它们实际上是不可能实现的,因为单个图形的绘图操作不需要在一起,更糟糕的是,同一页面上的不同图形的绘制操作,页面上的下划线以及其他图形效果甚至可能以看似随机的顺序混合在一大堆操作中。
但是,在您的情况下,您有一个优势:Office似乎正确标记PDF中的数字。这至少可以检测页面上不同(即不同标记的)矢量图形的数量,并且还可以区分哪个绘图操作属于哪个图形。
因此,这里有一些指示如何实现上述PDF标记的目标,如PDF样本。由于我自己没有使用VB,因此我没有示例代码。但是,当您的示例代码显示您已经知道如何遵循对象引用以及如何解释PDF对象信息时,这些指针应该足以显示方式。
<强> 1。检测某些页面上是否有某些图像。
在标记页面内容时,只需从文档目录中的 / StructTreeRoot 条目开始扫描结构层次结构(使用PdfReader.Catalog,
选择PdfName.STRUCTTREEROOT
的值在其中,深入研究它。)
E.g。对于样本的第1页(在PDF对象4 0中)(使用&#34; 1233&#34;在顶部,以及下面的笑脸),您将找到带有词典的数组:
<<
/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 类型,段落(您的&#34; 1233&#34;),第二个类型是 / Figure < / strong>,数字(你的笑脸)。第二个元素的存在表明页面上存在图形。因此,目标1已经通过这些数据实现。
(详见参见PDF规范{{3}}第14.7和14.8节。)
<强> 2。检索图像上的一些信息,例如页面上的大小或位置。
为此,您必须提取负责创建相关图形的图形运算符。在标记时,您必须在与上面 / Figure 字典中/K [1]
给出的标记内容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 的 BDC 和 EMC 之间的此部分包含您寻求的图形操作。如果你想获得他们所代表的数字的一些信息,你必须分析它们。
这是关于所有这些的非常低级别的视图,并且可能需要更高级别的API来检索它。
iText确实有一个高级API,用于使用parser
命名空间类PdfReaderContentParser
进行文本和位图图像处理的类似操作,以及与RenderListener
一样的ImageInfoTextExtractionStrategy.
实现但遗憾的是,PdfReaderContentParser
尚未正确预处理与矢量图形相关的运算符。
因此,要使用iText执行此操作,您必须扩展底层PdfContentStreamProcessor
以添加缺少的预处理(这是可行的,因为该解析器类是使用单独的侦听器为各个操作实现的,并且您可以轻松地为图形运算符注册新的侦听器);或者您必须检索页面内容并自行解析。
第3。提取图像。
由于PDF中的矢量图像使用PDF特定的矢量图形运算符,因此首先必须确定要导出图像的格式。除非您对原始PDF运算符感兴趣,否则您很可能需要一些库来帮助您创建所需格式的文件。
确定后,首先按照前面的说明提取有问题的图形运算符,然后将它们提供给该库,以创建您选择的可导出图像。