2012-02-11 56 views
1

我正在寻找简单地从PDF中提取所有图像。我发现一些代码,看起来像它到底是什么,我需要ITEXTSHARP in .net,提取图像代码,我无法获得此工作

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 

现在我的问题很简单,我怎么能叫这个,我不知道是什么设置字典变量或图像列表?

因此,如果我有一个位于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

引用您在其他地方找到的代码时,请包含引用该来源的链接。通常来源有答案,我们不必每次重新发明轮子。 http://stackoverflow.com/a/1220959/231316 – 2012-02-13 14:01:57

回答

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渲染器将处理将字节转换为实际图像的工作。在这个罐子里,you是PDF渲染器,所以它的工作是弄清楚如何将字节数组作为图像进行处理。

具体来说,您将在该方法中看到,有这么读取一行:

If filter = "/FlateDecode" Then 

这通常写为select caseswitch语句来处理的filter的各种值。虽然实际上有10个标准过滤器,例如CCITTFaxDecodeJBIG2DecodeDCTDecode(PDF规格7.4 - 过滤器),但您参考的方法仅处理FlateDecode,这很常见。您应该修改该方法以包含某种类型的捕获(ElseDefault个案),以便至少知道您未设置要处理的图像。

此外,/FlatDecode段内,你会看到这样一行:

Select Case Integer.Parse(bpp) 

这是阅读与图像对象,告诉渲染器有多少位应在解析时用于每种颜色相关的属性。在这种情况下,您再次是PDF渲染器,所以您可以自己决定要做什么。您引用的代码只包含单色(1 bpp)或真彩色(24 bpp)图像,但其他代码必须考虑在内,尤其是8 bpp。

因此总结一下,希望代码能够按原样运行,但如果它抱怨很多并且/或者图像丢失,请不要感到惊讶。提取图像有时会非常令人沮丧。如果您遇到问题,请在此引用一个新问题,并希望我们能够为您提供更多帮助!