在.net中的ITEXTSHARP,提取图像代码,我无法使其工作

时间:2012-02-11 04:39:32

标签: .net itextsharp

我希望简单地从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)

1 个答案:

答案 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 caseswitch语句写成,以处理filter的各种值。您引用的方法仅处理FlateDecode,这是非常常见的,尽管实际上有10个标准过滤器,例如CCITTFaxDecodeJBIG2DecodeDCTDecode(PDF规范7.4 - 过滤器)。您应该修改方法以包含某种类型的捕获(ElseDefault情况),以便您至少知道未设置处理的图像。

此外,在/FlatDecode部分,您会看到以下这一行:

Select Case Integer.Parse(bpp)

这是读取与图像对象关联的属性,该属性告诉渲染器在解析时应为每种颜色使用多少位。在这种情况下,您再次成为PDF渲染器,因此您可以自行决定要做什么。您引用的代码仅考虑单色(1 bpp)或真彩色(24 bpp)图像,但其他代码应该被考虑在内,尤其是8 bpp。

所以总结一下,希望代码可以为你工作,但如果它抱怨很多和/或错过图像,不要感到惊讶。实际上,提取图像实际上非常令人沮丧。如果您遇到问题,请在此处引用一个新问题,并希望我们可以为您提供更多帮助!