read example python image pdf extract pypdf

python - example - pypdf2 extract text



Extrae imágenes de PDF sin remuestrear, en Python? (10)

A menudo, en un PDF, la imagen simplemente se almacena tal cual. Por ejemplo, un PDF con un jpg insertado tendrá un rango de bytes en algún lugar en el medio que cuando se extrae es un archivo jpg válido. Puede usar esto para extraer muy fácilmente los rangos de bytes del PDF. Escribí sobre esto hace algún tiempo, con un código de muestra: extracción de JPG de archivos PDF .

¿Cómo se pueden extraer todas las imágenes de un documento pdf, en resolución y formato nativos? (Significado extraer tiff como tiff, jpeg como jpeg, etc. y sin remuestrear). El diseño no es importante, no me importa si la imagen de origen se encuentra en la página.

Estoy usando Python 2.7 pero puedo usar 3.x si es necesario.


Agregué todos estos en PyPDFTK here .

Mi propia contribución es manejar los archivos /Indexed como tales:

for obj in xObject: if xObject[obj][''/Subtype''] == ''/Image'': size = (xObject[obj][''/Width''], xObject[obj][''/Height'']) color_space = xObject[obj][''/ColorSpace''] if isinstance(color_space, pdf.generic.ArrayObject) and color_space[0] == ''/Indexed'': color_space, base, hival, lookup = [v.getObject() for v in color_space] # pg 262 mode = img_modes[color_space] if xObject[obj][''/Filter''] == ''/FlateDecode'': data = xObject[obj].getData() img = Image.frombytes(mode, size, data) if color_space == ''/Indexed'': img.putpalette(lookup.getData()) img = img.convert(''RGB'') img.save("{}{:04}.png".format(filename_prefix, i))

Tenga en cuenta que cuando se encuentran los archivos /Indexed , no puede simplemente comparar /ColorSpace con una cadena, ya que se trata de un ArrayObject . Entonces, debemos verificar la matriz y recuperar la paleta indexada ( lookup en el código) y configurarla en el objeto de la imagen PIL, de lo contrario permanece sin inicializar (cero) y toda la imagen se muestra en negro.

Mi primer instinto fue guardarlos como GIF (que es un formato indexado), pero mis pruebas resultaron que los PNG eran más pequeños y tenían el mismo aspecto.

Encontré esos tipos de imágenes al imprimir en PDF con la impresora PDF de Foxit Reader.


Después de buscar, encontré el siguiente script que funciona muy bien con mis PDF. Solo aborda JPG, pero funcionó perfectamente con mis archivos no protegidos. Además, no requiere ninguna biblioteca externa.

Para no tomar ningún crédito, el guión proviene de Ned Batchelder, y no yo. Código de Python3: extrae los jpg de los pdf. Rápido y sucio

import sys with open(sys.argv[1],"rb") as file: file.seek(0) pdf = file.read() startmark = b"/xff/xd8" startfix = 0 endmark = b"/xff/xd9" endfix = 2 i = 0 njpg = 0 while True: istream = pdf.find(b"stream", i) if istream < 0: break istart = pdf.find(startmark, istream, istream + 20) if istart < 0: i = istream + 20 continue iend = pdf.find(b"endstream", istart) if iend < 0: raise Exception("Didn''t find end of stream!") iend = pdf.find(endmark, iend - 20) if iend < 0: raise Exception("Didn''t find end of JPG!") istart += startfix iend += endfix print("JPG %d from %d to %d" % (njpg, istart, iend)) jpg = pdf[istart:iend] with open("jpg%d.jpg" % njpg, "wb") as jpgfile: jpgfile.write(jpg) njpg += 1 i = iend


Empecé con el código de @sylvain Hubo algunos errores, como la excepción NotImplementedError: unsupported filter /DCTDecode de getData, o el hecho de que el código no pudo encontrar imágenes en algunas páginas porque estaban en un nivel más profundo que la página.

Ahí está mi código:

import PyPDF2 from PIL import Image import sys from os import path import warnings warnings.filterwarnings("ignore") number = 0 def recurse(page, xObject): global number xObject = xObject[''/Resources''][''/XObject''].getObject() for obj in xObject: if xObject[obj][''/Subtype''] == ''/Image'': size = (xObject[obj][''/Width''], xObject[obj][''/Height'']) data = xObject[obj]._data if xObject[obj][''/ColorSpace''] == ''/DeviceRGB'': mode = "RGB" else: mode = "P" imagename = "%s - p. %s - %s"%(abspath[:-4], p, obj[1:]) if xObject[obj][''/Filter''] == ''/FlateDecode'': img = Image.frombytes(mode, size, data) img.save(imagename + ".png") number += 1 elif xObject[obj][''/Filter''] == ''/DCTDecode'': img = open(imagename + ".jpg", "wb") img.write(data) img.close() number += 1 elif xObject[obj][''/Filter''] == ''/JPXDecode'': img = open(imagename + ".jp2", "wb") img.write(data) img.close() number += 1 else: recurse(page, xObject[obj]) try: _, filename, *pages = sys.argv *pages, = map(int, pages) abspath = path.abspath(filename) except BaseException: print(''Usage :/nPDF_extract_images file.pdf page1 page2 page3 …'') sys.exit() file = PyPDF2.PdfFileReader(open(filename, "rb")) for p in pages: page0 = file.getPage(p-1) recurse(p, page0) print(''%s extracted images''% number)


En Python con PyPDF2 para el filtro CCITTFaxDecode:

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://.com/questions/2693820/extract-images-from-pdf-without-resampling-in-python Extract images coded with CCITTFaxDecode in .net: http://.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()


En Python con las bibliotecas PyPDF2 y Pillow es simple:

import PyPDF2 from PIL import Image if __name__ == ''__main__'': input1 = PyPDF2.PdfFileReader(open("input.pdf", "rb")) page0 = input1.getPage(0) xObject = page0[''/Resources''][''/XObject''].getObject() for obj in xObject: if xObject[obj][''/Subtype''] == ''/Image'': size = (xObject[obj][''/Width''], xObject[obj][''/Height'']) data = xObject[obj].getData() if xObject[obj][''/ColorSpace''] == ''/DeviceRGB'': mode = "RGB" else: mode = "P" if xObject[obj][''/Filter''] == ''/FlateDecode'': img = Image.frombytes(mode, size, data) img.save(obj[1:] + ".png") elif xObject[obj][''/Filter''] == ''/DCTDecode'': img = open(obj[1:] + ".jpg", "wb") img.write(data) img.close() elif xObject[obj][''/Filter''] == ''/JPXDecode'': img = open(obj[1:] + ".jp2", "wb") img.write(data) img.close()


Instalé ImageMagick en mi servidor y luego Popen llamadas de línea de comando a través de Popen :

#!/usr/bin/python import sys import os import subprocess import settings IMAGE_PATH = os.path.join(settings.MEDIA_ROOT , ''pdf_input'' ) def extract_images(pdf): output = ''temp.png'' cmd = ''convert '' + os.path.join(IMAGE_PATH, pdf) + '' '' + os.path.join(IMAGE_PATH, output) subprocess.Popen(cmd.split(), stderr=subprocess.STDOUT, stdout=subprocess.PIPE)

Esto creará una imagen para cada página y las almacenará como temp-0.png, temp-1.png ... Esto es solo ''extracción'' si tienes un pdf con solo imágenes y sin texto.



Puedes usar el módulo PyMuPDF. Esto produce todas las imágenes como archivos .png, pero se resuelven de inmediato y es rápido.

import fitz doc = fitz.open("file.pdf") for i in range(len(doc)): for img in doc.getPageImageList(i): xref = img[0] pix = fitz.Pixmap(doc, xref) if pix.n < 5: # this is GRAY or RGB pix.writePNG("p%s-%s.png" % (i, xref)) else: # CMYK: convert to RGB first pix1 = fitz.Pixmap(fitz.csRGB, pix) pix1.writePNG("p%s-%s.png" % (i, xref)) pix1 = None pix = None

mira aquí para más recursos


Solución mucho más fácil:

Use el paquete poppler-utils. Para instalarlo, use homebrew (homebrew es específico de MacOS, pero puede encontrar el paquete poppler-utils para Widows o Linux aquí: https://poppler.freedesktop.org/ ). La primera línea de código a continuación instala poppler-utils usando homebrew. Después de la instalación, la segunda línea (ejecutar desde la línea de comandos) luego extrae imágenes de un archivo PDF y las denomina "imagen *". Para ejecutar este programa desde dentro de Python use el sistema operativo o el módulo de subproceso. La tercera línea es el código que usa el módulo os, debajo se encuentra un ejemplo con un subproceso (Python 3.5 o posterior para la función run ()). Más información aquí: https://www.cyberciti.biz/faq/easily-extract-images-from-pdf-file/

brew install poppler

pdfimages file.pdf image

import os os.system(''pdfimages file.pdf image'')

o

import subprocess subprocess.run(''pdfimages file.pdf image'', shell=True)