2010-04-14 26 views
13

Tengo un pdf que se generó a partir del software de escaneo. El pdf tiene 1 imagen TIFF por página. Quiero extraer la imagen TIFF de cada página.Extraer imagen de PDF con/CCITTFaxDecode filter

Estoy usando iTextSharp y he encontrado con éxito las imágenes y puedo recuperar los bytes sin procesar del método PdfReader.GetStreamBytesRaw. El problema es que, como muchos antes que yo hayan descubierto, iTextSharp no contiene un método PdfReader.CCITTFaxDecode.

¿Qué más sé? Incluso sin iTextSharp Puedo abrir el pdf en el bloc de notas y encontrar los arroyos con /Filter /CCITTFaxDecode y sé de la /DecodeParams que está utilizando grupo CCITTFaxDecode 4.

¿Alguien por ahí sabe cómo puedo obtener las imágenes Filtro CCITTFaxDecode de mi pdf?

Saludos, Kahu

+0

por si alguien está interesado en una solución exclusivamente iTextSharp, hay este otro enlace (http://kuujinbo.info/iTextSharp/CCITTFaxDecodeExtract.aspx) que sugiere el uso de una nueva característica introducida en iTextSharp 5xx llamada Parser - en realidad funciona. créditos a @kuunjinbo es solo que en mi caso tuve que usar ImageConverter en el resultado para crear un mapa de bits (no estoy seguro por qué) –

Respuesta

0

Tal vez usted puede tratar de descomprimir el pdf con pdftk? La sintaxis es

pdftk infile.pdf output uncompressed.pdf uncompress 

No tengo un pdf codificado CCITTFax aquí, así que no puedo probarlo.

+1

Este comando descomprimir no parece estar relacionado con el campo libtiff COMPRESSION. Intenté esto en un pdf con imágenes CCITTFaxdecode, y no pareció hacer ninguna diferencia. – nealmcb

6

Esta biblioteca ... http://www.bitmiracle.com/libtiff/ y este ejemplo de abajo que debe obtener el 99% de la manera allí

string filter = pd.Get(PdfName.FILTER).ToString(); 
string width = pd.Get(PdfName.WIDTH).ToString(); 
string height = pd.Get(PdfName.HEIGHT).ToString(); 
string bpp = pd.Get(PdfName.BITSPERCOMPONENT).ToString(); 

switch (filter) 
{ 
    case "/CCITTFaxDecode": 

     byte[] data = PdfReader.GetStreamBytesRaw((PRStream)pdfStream); 
     int tiff = TIFFOpen("example.tif", "w"); 
     TIFFSetField(tiff, (uint)BitMiracle.LibTiff.Classic.TiffTag.IMAGEWIDTH,(uint)Int32.Parse(width)); 
     TIFFSetField(tiff, (uint)BitMiracle.LibTiff.Classic.TiffTag.IMAGEHEIGHT, (uint)Int32.Parse(height)); 
     TIFFSetField(tiff, (uint)BitMiarcle.LibTiff.Classic.TiffTag.COMPRESSION, (uint)BitMiracle.Libtiff.Classic.Compression.CCITTFAX4); 
     TIFFSetField(tiff, (uint)BitMiracle.LibTiff.Classic.TiffTag.BITSPERSAMPLE, (uint)Int32.Parse(bpp)); 
     TIFFSetField(tiff, (uint)BitMiarcle.Libtiff.Classic.TiffTag.SAMPLESPERPIXEL,1); 

     IntPtr pointer = Marshal.AllocHGlobal(data.length); 
     Marshal.copy(data, 0, pointer, data.length); 
     TIFFWriteRawStrip(tiff, 0, pointer, data.length); 
     TIFFClose(tiff); 

     break; 




     break; 

} 
+0

Y NuGet aquí: [BitMiracle.LibTiff.NET] (https://www.nuget.org/packages/BitMiracle.LibTiff.NET/). –

13

En realidad, la respuesta de vbcrlfuser me ayudó, pero el código no era correcto para la versión actual de BitMiracle.LibTiff.NET, ya que podría descargarlo. En la versión actual, código equivalente es el siguiente:

using iTextSharp.text.pdf; 
using BitMiracle.LibTiff.Classic; 

... 
     Tiff tiff = Tiff.Open("C:\\test.tif", "w"); 
     tiff.SetField(TiffTag.IMAGEWIDTH, UInt32.Parse(pd.Get(PdfName.WIDTH).ToString())); 
     tiff.SetField(TiffTag.IMAGELENGTH, UInt32.Parse(pd.Get(PdfName.HEIGHT).ToString())); 
     tiff.SetField(TiffTag.COMPRESSION, Compression.CCITTFAX4); 
     tiff.SetField(TiffTag.BITSPERSAMPLE, UInt32.Parse(pd.Get(PdfName.BITSPERCOMPONENT).ToString())); 
     tiff.SetField(TiffTag.SAMPLESPERPIXEL, 1); 
     tiff.WriteRawStrip(0, raw, raw.Length); 
     tiff.Close(); 

Usando el código anterior, que finalmente tengo un archivo TIFF válido en C: \ Test.tif. Gracias, vbcrlfuser!

+0

¿Qué es 'raw'? Podrías mostrar el ejemplo completo –

+0

B.K. esto podría ser un poco tarde, pero supongo que es esto. ver la respuesta de vbcrlfuser ... byte [] data = PdfReader.GetStreamBytesRaw ((PRStream) pdfStream); (usado de la misma manera que en bruto) – planty182

4

Aquí es la aplicación de pitón:

import PyPDF2 
import struct 

""" 
Links: 
PDF format: http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/pdf_reference_1-7.pdf 
CCITT Group 4: https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-T.6-198811-I!!PDF-E&type=items 
Extract images from pdf: http://stackoverflow.com/questions/2693820/extract-images-from-pdf-without-resampling-in-python 
Extract images coded with CCITTFaxDecode in .net: http://stackoverflow.com/questions/2641770/extracting-image-from-pdf-with-ccittfaxdecode-filter 
TIFF format and tags: http://www.awaresystems.be/imaging/tiff/faq.html 
""" 


def tiff_header_for_CCITT(width, height, img_size, CCITT_group=4): 
    tiff_header_struct = '<' + '2s' + 'h' + 'l' + 'h' + 'hhll' * 8 + 'h' 
    return struct.pack(tiff_header_struct, 
         b'II', # Byte order indication: Little indian 
         42, # Version number (always 42) 
         8, # Offset to first IFD 
         8, # Number of tags in IFD 
         256, 4, 1, width, # ImageWidth, LONG, 1, width 
         257, 4, 1, height, # ImageLength, LONG, 1, lenght 
         258, 3, 1, 1, # BitsPerSample, SHORT, 1, 1 
         259, 3, 1, CCITT_group, # Compression, SHORT, 1, 4 = CCITT Group 4 fax encoding 
         262, 3, 1, 0, # Threshholding, SHORT, 1, 0 = WhiteIsZero 
         273, 4, 1, struct.calcsize(tiff_header_struct), # StripOffsets, LONG, 1, len of header 
         278, 4, 1, height, # RowsPerStrip, LONG, 1, lenght 
         279, 4, 1, img_size, # StripByteCounts, LONG, 1, size of image 
         0 # last IFD 
         ) 

pdf_filename = 'scan.pdf' 
pdf_file = open(pdf_filename, 'rb') 
cond_scan_reader = PyPDF2.PdfFileReader(pdf_file) 
for i in range(0, cond_scan_reader.getNumPages()): 
    page = cond_scan_reader.getPage(i) 
    xObject = page['/Resources']['/XObject'].getObject() 
    for obj in xObject: 
     if xObject[obj]['/Subtype'] == '/Image': 
      """ 
      The CCITTFaxDecode filter decodes image data that has been encoded using 
      either Group 3 or Group 4 CCITT facsimile (fax) encoding. CCITT encoding is 
      designed to achieve efficient compression of monochrome (1 bit per pixel) image 
      data at relatively low resolutions, and so is useful only for bitmap image data, not 
      for color images, grayscale images, or general data. 

      K < 0 --- Pure two-dimensional encoding (Group 4) 
      K = 0 --- Pure one-dimensional encoding (Group 3, 1-D) 
      K > 0 --- Mixed one- and two-dimensional encoding (Group 3, 2-D) 
      """ 
      if xObject[obj]['/Filter'] == '/CCITTFaxDecode': 
       if xObject[obj]['/DecodeParms']['/K'] == -1: 
        CCITT_group = 4 
       else: 
        CCITT_group = 3 
       width = xObject[obj]['/Width'] 
       height = xObject[obj]['/Height'] 
       data = xObject[obj]._data # sorry, getData() does not work for CCITTFaxDecode 
       img_size = len(data) 
       tiff_header = tiff_header_for_CCITT(width, height, img_size, CCITT_group) 
       img_name = obj[1:] + '.tiff' 
       with open(img_name, 'wb') as img_file: 
        img_file.write(tiff_header + data) 
       # 
       # import io 
       # from PIL import Image 
       # im = Image.open(io.BytesIO(tiff_header + data)) 
pdf_file.close() 
+1

Según la etiqueta y el cuerpo de la pregunta, el operador usa iTextSharp. A * python Realization *, por lo tanto, no responde a esta pregunta. – mkl

+1

Según la especificación TIFF ([link] (http://www.itu.int/itudoc/itu-t/com16/tiff-fx/docs/tiff6.html)), creo que su variable 'tiff_header_struct' debería leer ''<' + '2s' + 'H' + 'L' + 'H' + 'HHLL' * 8 + 'L''.Tenga en cuenta en particular el '' L''al final. – Taar

0

Se ha escrito extension para de esta .Es tan simple

PdfDictionary item; 
if (item.IsImage()) { 
    Image image = item.ToImage(); 
}