ITEXTSHARP в .net, Извлечь код изображения, я не могу заставить это работать - PullRequest
1 голос
/ 11 февраля 2012

Я хочу просто извлечь все изображения из 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 или список изображений??

Итак, если у меня есть файл PDF, расположенный в C: \ temp \ test.pdf, содержащий изображения, как я могу это назвать?

    Dim x As New FileStream("C:\image\test.pdf", FileMode.Open)
    Dim reader As New iTextSharp.text.pdf.PdfReader(x)
    getAllImages(?????, ?????? ,reader)

1 Ответ

2 голосов
/ 13 февраля 2012

То, как этот человек написал этот метод, может показаться странным, если вы не понимаете внутренности 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 Spec 7.4 - Фильтры). Вам следует изменить метод, включив в него какой-то улов (случай Else или Default), чтобы вы как минимум знали о изображениях, которые вы не настроили для обработки.

Кроме того, в разделе /FlatDecode вы увидите эту строку:

Select Case Integer.Parse(bpp)

Это чтение атрибута, связанного с объектом изображения, который сообщает средству визуализации, сколько битов следует использовать для каждого цвета при разборе. Опять же, вы в этом случае являетесь рендером PDF, так что вам решать, что делать. Код, на который вы ссылаетесь, учитывает только монохромные (1 бит / с) или truecolor (24 бит / с) изображения, но другие обязательно должны учитываться, особенно 8 бит / с.

Итак, подводя итог, можно надеяться, что код работает для вас как есть, но не удивляйтесь, если он много жалуется и / или пропускает изображения. Извлечение изображений иногда может быть очень неприятным. Если вы столкнетесь с проблемами, начните новый вопрос со ссылкой на этот вопрос, и мы надеемся, что мы можем помочь вам больше!

...