Extraer una página de un pdf como jpeg

96

En el código python, ¿cómo guardar de manera eficiente una determinada página en un pdf como un archivo jpeg? (Caso de uso: tengo un servidor web python flask donde se cargarán los pdf-s y los jpeg-s correspondientes a cada página son las tiendas).

Esta solución está cerca, pero el problema es que no convierte toda la página a jpeg.

vishvAs vAsuki
fuente
1
Dependiendo de la imagen, puede ser mejor extraer como png. Esto se aplicaría si la página contiene principalmente texto.
Paul Rooney

Respuestas:

126

Se puede utilizar la biblioteca pdf2image.

Puede instalarlo simplemente usando,

pip install pdf2image

Una vez instalado, puede usar el siguiente código para obtener imágenes.

from pdf2image import convert_from_path
pages = convert_from_path('pdf_file', 500)

Guardar páginas en formato jpeg

for page in pages:
    page.save('out.jpg', 'JPEG')

Editar: el repositorio de Github pdf2image también menciona que usa pdftoppmy que requiere otras instalaciones:

pdftoppm es el software que hace la magia real. Se distribuye como parte de un paquete mayor llamado poppler . Los usuarios de Windows deberán instalar poppler para Windows . Los usuarios de Mac deberán instalar poppler para Mac . Los usuarios de Linux tendrán pdftoppm preinstalado con la distribución (probado en Ubuntu y Archlinux) si no es así, ejecútelo sudo apt install poppler-utils.

Puede instalar la última versión en Windows usando anaconda haciendo:

conda install -c conda-forge poppler

nota: las versiones de Windows hasta 0.67 están disponibles en http://blog.alivate.com.au/poppler-windows/ pero tenga en cuenta que 0.68 se lanzó en agosto de 2018, por lo que no obtendrá las últimas funciones ni correcciones de errores.

Keval Dave
fuente
4
Hola, el poppler es solo un archivo comprimido, no instala nada, ¿qué se supone que debe hacer uno con los archivos dll o bin?
gaurwraith
@gaurwraith: Utilice el siguiente enlace para hacer poppler . Por alguna razón, el enlace en la descripción de Rodrigo no es el mismo que en el repositorio de github.
Tobias
@Keval Dave ¿Ha instalado poppler y ha probado pdf2image en una máquina con Windows? ¿Qué Windows por favor?
SKR
1
@elPastor puede agregar first_page y last_page en el argumento de la función conver_from_path para convertir solo la página especificada
Keval Dave
1
@Jacob 500 es el dpi. Se compensa entre la resolución requerida y el cálculo disponible. En mis experimentos, 500 funcionó bien en la mayoría de los casos, mientras que 300 me dieron imágenes de baja resolución.
Keval Dave
36

Encontré esta solución simple, PyMuPDF , salida a archivo png. Tenga en cuenta que la biblioteca se importa como "fitz", un nombre histórico para el motor de renderizado que utiliza.

import fitz

pdffile = "infile.pdf"
doc = fitz.open(pdffile)
page = doc.loadPage(0)  # number of page
pix = page.getPixmap()
output = "outfile.png"
pix.writePNG(output)
JJPty
fuente
1
Agregue una explicación a su respuesta.
Shanteshwar Inde
1
Una buena biblioteca y se instala en Windows 10 sin problemas (no se requieren ruedas). github.com/pymupdf
Camarada Che
7
Esta es la mejor respuesta. Este fue el único código que no requirió una instalación adicional en mi sistema operativo. Los scripts de Python deben centrarse en trabajar dentro del sistema Python. No necesitaba instalar poppler, pdftoppm, imageMagick o ghostscript, etc. (Python 3.6)
ZStoneDPM
1
En realidad, requiere otra instalación (biblioteca fitz, importada sin siquiera ser referenciada y sus dependencias), esta respuesta está incompleta (como todas las respuestas a esta pregunta)
Tommaso Guerrini
1
@JJPty En lugar de un archivo pdf tomado de la ruta, ¿podemos tomarlo de pdfurl? Además, ¿es posible que el archivo png sea datos in-stream en lugar de un archivo png de salida?
Shubham Agrawal
18

La biblioteca de Python pdf2image(utilizada en la otra respuesta) de hecho no hace mucho más que simplemente iniciar pdttoppm con subprocess.Popen, por lo que aquí hay una versión corta que lo hace directamente:

PDFTOPPMPATH = r"D:\Documents\software\____PORTABLE\poppler-0.51\bin\pdftoppm.exe"
PDFFILE = "SKM_28718052212190.pdf"

import subprocess
subprocess.Popen('"%s" -png "%s" out' % (PDFTOPPMPATH, PDFFILE))

Aquí está el enlace de instalación de Windows para pdftoppm(contenido en un paquete llamado poppler): http://blog.alivate.com.au/poppler-windows/

Basj
fuente
4
Hola, el enlace de instalación de Windows para pdftoppm es solo un montón de archivos comprimidos, ¿qué tienes que hacer con ellos para que funcionen? ¡Gracias!
gaurwraith
14

No es necesario instalar Poppler en su sistema operativo. Esto funcionará:

pip instalar varita

from wand.image import Image

f = "somefile.pdf"
with(Image(filename=f, resolution=120)) as source: 
    for i, image in enumerate(source.sequence):
        newfilename = f[:-4] + str(i + 1) + '.jpeg'
        Image(image).save(filename=newfilename)
DevB2F
fuente
10
La biblioteca ImageMagick debe estar instalada para que funcione en Wand.
Neeraj Gulia
2
Intenté esto y también necesitaba instalar Ghostscript (usando Windows 10 y Python 3.7). Lo hice y funcionó perfectamente.
jcf
1
¿Para qué es la f [: - 4]? no se hace referencia en ningún otro lugar
Ari
@Ari f [: - 4] cortará ".pdf" del nombre de archivo (corte de cadena) para crear un nuevo nombre de archivo con otra extensión.
Fabian
9

@gaurwraith, instale poppler para Windows y use pdftoppm.exe de la siguiente manera:

  1. Descargue el archivo zip con los binarios / dlls más recientes de Poppler desde http://blog.alivate.com.au/poppler-windows/ y descomprímalo en una nueva carpeta en la carpeta de archivos de su programa. Por ejemplo: "C: \ Archivos de programa (x86) \ Poppler".

  2. Agregue "C: \ Archivos de programa (x86) \ Poppler \ poppler-0.68.0 \ bin" a la variable de entorno SYSTEM PATH.

  3. Desde la línea cmd instale el módulo pdf2image -> "pip install pdf2image".

  4. O alternativamente, ejecute directamente pdftoppm.exe desde su código usando el módulo de subproceso de Python como lo explicó el usuario Basj.

@vishvAs vAsuki, este código debe generar los jpgs que desee a través del módulo de subproceso para todas las páginas de uno o más archivos PDF en una carpeta determinada:

import os, subprocess

pdf_dir = r"C:\yourPDFfolder"
os.chdir(pdf_dir)

pdftoppm_path = r"C:\Program Files (x86)\Poppler\poppler-0.68.0\bin\pdftoppm.exe"

for pdf_file in os.listdir(pdf_dir):

    if pdf_file.endswith(".pdf"):

        subprocess.Popen('"%s" -jpeg %s out' % (pdftoppm_path, pdf_file))

O usando el módulo pdf2image:

import os
from pdf2image import convert_from_path

pdf_dir = r"C:\yourPDFfolder"
os.chdir(pdf_dir)

    for pdf_file in os.listdir(pdf_dir):

        if pdf_file.endswith(".pdf"):

            pages = convert_from_path(pdf_file, 300)
            pdf_file = pdf_file[:-4]

            for page in pages:

               page.save("%s-page%d.jpg" % (pdf_file,pages.index(page)), "JPEG")
photek1944
fuente
Esto ayudó mucho. ¡Gracias!
Sreekiran
1
Esta debería ser la respuesta aceptada. Muestra qué hacer con los binarios instalados para Poppler
Kunj Mehta
3

Hay una utilidad llamada pdftojpg que se puede utilizar para convertir el pdf a img

Puede encontrar el código aquí https://github.com/pankajr141/pdf2jpg

from pdf2jpg import pdf2jpg
inputpath = r"D:\inputdir\pdf1.pdf"
outputpath = r"D:\outputdir"
# To convert single page
result = pdf2jpg.convert_pdf2jpg(inputpath, outputpath, pages="1")
print(result)

# To convert multiple pages
result = pdf2jpg.convert_pdf2jpg(inputpath, outputpath, pages="1,0,3")
print(result)

# to convert all pages
result = pdf2jpg.convert_pdf2jpg(inputpath, outputpath, pages="ALL")
print(result)
Pato
fuente
2
¿Esto de Java simplemente eliminó toda mi carpeta llena de pdf manipulando scripts de Python ...?
Ulf Gjerdingen
2

GhostScript funciona mucho más rápido que Poppler para un sistema basado en Linux.

A continuación se muestra el código para la conversión de PDF a imagen.

def get_image_page(pdf_file, out_file, page_num):
    page = str(page_num + 1)
    command = ["gs", "-q", "-dNOPAUSE", "-dBATCH", "-sDEVICE=png16m", "-r" + str(RESOLUTION), "-dPDFFitPage",
               "-sOutputFile=" + out_file, "-dFirstPage=" + page, "-dLastPage=" + page,
               pdf_file]
    f_null = open(os.devnull, 'w')
    subprocess.call(command, stdout=f_null, stderr=subprocess.STDOUT)

GhostScript se puede instalar en macOS usando brew install ghostscript

La información de instalación para otras plataformas se puede encontrar aquí . Si aún no está instalado en su sistema.

Keval Dave
fuente
0

Yo uso una opción (quizás) mucho más simple de pdf2image:

cd $dir
for f in *.pdf
do
  if [ -f "${f}" ]; then
    n=$(echo "$f" | cut -f1 -d'.')
    pdftoppm -scale-to 1440 -png $f $conv/$n
    rm $f
    mv  $conv/*.png $dir
  fi
done

Esta es una pequeña parte de un script bash en un bucle para el uso de un dispositivo de transmisión estrecho. Comprueba cada 5 segundos los archivos pdf agregados (todos) y los procesa. Esto es para un dispositivo de demostración, al final la conversión se realizará en un servidor remoto. Convertir a .PNG ahora, pero .JPG también es posible.

Esta conversión, junto con las transiciones en formato A4, la visualización de un video, dos textos de desplazamiento suave y un logotipo (con transición en tres versiones) configura el Pi3 a casi 4x 100% de carga de cpu ;-)

Robert
fuente
0
from pdf2image import convert_from_path
import glob

pdf_dir = glob.glob(r'G:\personal\pdf\*')  #your pdf folder path
img_dir = "G:\\personal\\img\\"           #your dest img path

for pdf_ in pdf_dir:
    pages = convert_from_path(pdf_, 500)
    for page in pages:
        page.save(img_dir+pdf_.split("\\")[-1][:-3]+"jpg", 'JPEG')
Saiprasad Bhatwadekar
fuente
Esta sería una mejor respuesta si explicara cómo el código que proporcionó responde a la pregunta.
pppery
1
@pppery Python es bastante legible, los comentarios indican la carpeta de origen y la carpeta de salida, el resto se lee como en inglés.
Ari
-1

Aquí hay una solución que no requiere bibliotecas adicionales y es muy rápida. Esto se encontró en: https://nedbatchelder.com/blog/200712/extracting_jpgs_from_pdfs.html# He agregado el código en una función para que sea más conveniente.

def convert(filepath):
    with open(filepath, "rb") as file:
        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
        jpg = pdf[istart:iend]
        newfile = "{}jpg".format(filepath[:-3])
        with open(newfile, "wb") as jpgfile:
            jpgfile.write(jpg)

        njpg += 1
        i = iend

        return newfile

Llame a convert con la ruta del pdf como argumento y la función creará un archivo .jpg en el mismo directorio

moo5e
fuente
1
Esta técnica parece que extrae imágenes que se han incrustado en el archivo, en lugar de rasterizar una página del archivo como una imagen, que es lo que quería el interrogador.
Josh Gallagher