2010-04-14 4 views
13

J'ai un fichier pdf généré à partir d'un logiciel de numérisation. Le pdf a 1 image TIFF par page. Je veux extraire l'image TIFF de chaque page. J'utilise iTextSharp et j'ai réussi à trouver les images et je peux récupérer les octets bruts de la méthode PdfReader.GetStreamBytesRaw. Le problème est, comme beaucoup l'ont découvert avant moi, iTextSharp ne contient pas une méthode PdfReader.CCITTFaxDecode.Extraction d'une image à partir du PDF avec le filtre/CCITTFaxDecode

Que puis-je savoir d'autre? Même sans iTextSharp je peux ouvrir le fichier PDF dans le bloc-notes et trouver les cours d'eau avec /Filter /CCITTFaxDecode et je sais de la /DecodeParams qu'il utilise groupe CCITTFaxDecode 4.

Quelqu'un sait-il là-bas comment je peux obtenir les images de filtre CCITTFaxDecode de ma pdf?

Cheers, Kahu

+0

au cas où quelqu'un est intéressé par une solution uniquement iTextSharp, il y a cet autre lien (http://kuujinbo.info/iTextSharp/CCITTFaxDecodeExtract.aspx) qui suggère d'utiliser une nouvelle fonctionnalité introduite dans iTextSharp 5xx appelée Parser - cela fonctionne réellement. crédits à @kuunjinbo c'est juste que dans mon cas, j'ai dû utiliser ImageConverter sur le résultat pour créer un bitmap hors de lui (pas sûr pourquoi) –

Répondre

0

vous pouvez peut-être essayer de décompresser le pdf avec pdftk? La syntaxe est

pdftk infile.pdf output uncompressed.pdf uncompress 

Je n'ai pas pdf codé CCITTFax ici, donc je ne peux pas tester.

+1

Cette commande décompresser ne semble pas liée au champ LIBRESSE COMPRESSION. J'ai essayé ceci sur un pdf avec des images de CCITTFaxdecode, et cela n'a pas semblé faire n'importe quelle différence. – nealmcb

6

Cette bibliothèque ... http://www.bitmiracle.com/libtiff/ et cet exemple ci-dessous devrait vous obtenir 99% du chemin

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

Et le NuGet ici: [BitMiracle.LibTiff.NET] (https://www.nuget.org/packages/BitMiracle.LibTiff.NET/). –

13

En fait, la réponse de vbcrlfuser m'a aidé, mais le code n'a pas été tout à fait correct pour la version actuelle BitMiracle.LibTiff.NET, comme je pourrais le télécharger. Dans la version actuelle, le code équivalent ressemble à ceci:

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(); 

En utilisant le code ci-dessus, je enfin obtenu un fichier Tiff valide dans C: \ Test.tif. Merci, vbcrlfuser!

+0

Qu'est-ce qui est 'raw'? Pourriez-vous montrer l'exemple complet. –

+0

B.K. cela pourrait être un peu tard, mais je suppose que c'est ça. voir la réponse de vbcrlfuser ... byte [] data = PdfReader.GetStreamBytesRaw ((PRStream) pdfStream); (utilisé de la même manière que brut) – planty182

4

est ici mise en œuvre du python:

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

Selon l'étiquette et le corps de la question, l'op utilise iTextSharp. Une réalisation * python * ne répond donc pas à cette question. – mkl

+1

Selon la spécification TIFF ([link] (http://www.itu.int/itudoc/itu-t/com16/tiff-fx/docs/tiff6.html)), je pense que votre variable 'tiff_header_struct' devrait lire ''<' + '2s' + 'H' + 'L' + 'H' + 'HHLL' * 8 + 'L''.Notez en particulier le '' L''à la fin. – Taar

0

Il a été écrit extension pour cette .It simple, est si

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