我希望简单地从pdf中提取所有图像。我发现一些代码看起来就像我需要的那样
Private Sub getAllImages(ByVal dict As pdf.PdfDictionary, ByVal images As List(Of Byte()), ByVal doc As pdf.PdfReader)
Dim res As pdf.PdfDictionary = CType(pdf.PdfReader.GetPdfObject(dict.Get(pdf.PdfName.RESOURCES)), pdf.PdfDictionary)
Dim xobj As pdf.PdfDictionary = CType(pdf.PdfReader.GetPdfObject(res.Get(pdf.PdfName.XOBJECT)), pdf.PdfDictionary)
If xobj IsNot Nothing Then
For Each name As pdf.PdfName In xobj.Keys
Dim obj As pdf.PdfObject = xobj.Get(name)
If (obj.IsIndirect) Then
Dim tg As pdf.PdfDictionary = CType(pdf.PdfReader.GetPdfObject(obj), pdf.PdfDictionary)
Dim subtype As pdf.PdfName = CType(pdf.PdfReader.GetPdfObject(tg.Get(pdf.PdfName.SUBTYPE)), pdf.PdfName)
If pdf.PdfName.IMAGE.Equals(subtype) Then
Dim xrefIdx As Integer = CType(obj, pdf.PRIndirectReference).Number
Dim pdfObj As pdf.PdfObject = doc.GetPdfObject(xrefIdx)
Dim str As pdf.PdfStream = CType(pdfObj, pdf.PdfStream)
Dim bytes As Byte() = pdf.PdfReader.GetStreamBytesRaw(CType(str, pdf.PRStream))
Dim filter As String = tg.Get(pdf.PdfName.FILTER).ToString
Dim width As String = tg.Get(pdf.PdfName.WIDTH).ToString
Dim height As String = tg.Get(pdf.PdfName.HEIGHT).ToString
Dim bpp As String = tg.Get(pdf.PdfName.BITSPERCOMPONENT).ToString
If filter = "/FlateDecode" Then
bytes = pdf.PdfReader.FlateDecode(bytes, True)
Dim pixelFormat As System.Drawing.Imaging.PixelFormat
Select Case Integer.Parse(bpp)
Case 1
pixelFormat = Drawing.Imaging.PixelFormat.Format1bppIndexed
Case 24
pixelFormat = Drawing.Imaging.PixelFormat.Format24bppRgb
Case Else
Throw New Exception("Unknown pixel format " + bpp)
End Select
Dim bmp As New System.Drawing.Bitmap(Int32.Parse(width), Int32.Parse(height), pixelFormat)
Dim bmd As System.Drawing.Imaging.BitmapData = bmp.LockBits(New System.Drawing.Rectangle(0, 0, Int32.Parse(width), Int32.Parse(height)), System.Drawing.Imaging.ImageLockMode.WriteOnly, pixelFormat)
Marshal.Copy(bytes, 0, bmd.Scan0, bytes.Length)
bmp.UnlockBits(bmd)
Using ms As New MemoryStream
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png)
bytes = ms.GetBuffer
End Using
End If
images.Add(bytes)
ElseIf pdf.PdfName.FORM.Equals(subtype) Or pdf.PdfName.GROUP.Equals(subtype) Then
getAllImages(tg, images, doc)
End If
End If
Next
End If End Sub
现在我的问题很简单,我怎么称呼它,我不知道将dict变量设置为什么或图像列表?
因此,如果我在包含图像的C:\ temp \ test.pdf中有PDF,我该如何调用它?
Dim x As New FileStream("C:\image\test.pdf", FileMode.Open)
Dim reader As New iTextSharp.text.pdf.PdfReader(x)
getAllImages(?????, ?????? ,reader)
答案 0 :(得分:2)
如果你不理解PDF和/或iTextSharp的内部,这个人编写这种方法的方式看起来很奇怪。该方法有三个参数,第一个是PdfDictionary
,您可以通过在每个页面上调用GetPageN(Integer)
来获取这些参数。第二个是通用列表,在调用它之前需要自己初始化。此方法旨在为PDF中的每个页面循环调用,并且每个调用都会将图像附加到此列表。你已经理解的最后一个参数。
所以这是调用此方法的代码:
''//Source file to read images from
Dim InputFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "FileWithImages.pdf")
''//List to dump images into
Dim Images As New List(Of Byte())
''//Main PDF reader
Dim Reader As New PdfReader(InputFile)
''//Total number of pages in the PDF
Dim PageCount = Reader.NumberOfPages
''//Loop through each page (first page is one, not zero)
For I = 1 To PageCount
getAllImages(Reader.GetPageN(I), Images, Reader)
Next
非常非常重要 - iTextSharp 不 是一个PDF渲染器,它是一个PDF作曲家。这意味着它知道它具有类似图像的对象,但它并不一定了解它们。换句话说,iTextSharp知道给定的字节数组表示PDF标准所说的图像,但它不知道或不关心它是JPEG,TIFF,BMP还是其他东西。所有iTextSharp关心的是这个对象有一些标准属性可以操作,如X,Y和有效宽度和高度。 PDF渲染器将处理将字节转换为实际图像的工作。在这个可以,你是PDF渲染器,所以你的工作是弄清楚如何将字节数组作为图像处理。
具体来说,您会在该方法中看到有一行显示为:
If filter = "/FlateDecode" Then
这通常用select case
或switch
语句写成,以处理filter
的各种值。您引用的方法仅处理FlateDecode
,这是非常常见的,尽管实际上有10个标准过滤器,例如CCITTFaxDecode
,JBIG2Decode
和DCTDecode
(PDF规范7.4 - 过滤器)。您应该修改方法以包含某种类型的捕获(Else
或Default
情况),以便您至少知道未设置处理的图像。
此外,在/FlatDecode
部分,您会看到以下这一行:
Select Case Integer.Parse(bpp)
这是读取与图像对象关联的属性,该属性告诉渲染器在解析时应为每种颜色使用多少位。在这种情况下,您再次成为PDF渲染器,因此您可以自行决定要做什么。您引用的代码仅考虑单色(1 bpp)或真彩色(24 bpp)图像,但其他代码应该被考虑在内,尤其是8 bpp。
所以总结一下,希望代码可以为你工作,但如果它抱怨很多和/或错过图像,不要感到惊讶。实际上,提取图像实际上非常令人沮丧。如果您遇到问题,请在此处引用一个新问题,并希望我们可以为您提供更多帮助!