Estrai una pagina da un pdf come jpeg


96

Nel codice Python, come salvare in modo efficiente una determinata pagina in un pdf come file jpeg? (Caso d'uso: ho un server web flask Python in cui verranno caricati pdf-s e jpeg-s corrispondenti a ciascuna pagina vengono archiviati.)

Questa soluzione è vicina, ma il problema è che non converte l'intera pagina in jpeg.


1
A seconda dell'immagine, potrebbe essere meglio estrarre come png. Ciò si applicherebbe se la pagina contenga principalmente testo.
Paul Rooney,

Risposte:


126

È possibile utilizzare la libreria pdf2image.

Puoi installarlo semplicemente usando,

pip install pdf2image

Una volta installato, puoi utilizzare il seguente codice per ottenere le immagini.

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

Salvataggio di pagine in formato jpeg

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

Modifica: il repository Github pdf2image menziona anche che utilizza pdftoppme che richiede altre installazioni:

pdftoppm è il software che fa la vera magia. È distribuito come parte di un pacchetto più grande chiamato poppler . Gli utenti Windows dovranno installare poppler per Windows . Gli utenti Mac dovranno installare poppler per Mac . Gli utenti Linux avranno pdftoppm preinstallato con la distro (testato su Ubuntu e Archlinux) se non lo è, esegui sudo apt install poppler-utils.

Puoi installare l'ultima versione sotto Windows usando anaconda facendo:

conda install -c conda-forge poppler

nota: le versioni di Windows fino alla 0.67 sono disponibili su http://blog.alivate.com.au/poppler-windows/ ma nota che la 0.68 è stata rilasciata nell'agosto 2018, quindi non riceverai le ultime funzionalità o correzioni di bug.


4
Ciao, il poppler è solo un file zippato, non installa nulla, cosa si dovrebbe fare con i file dll o bin?
gaurwraith

@gaurwraith: usa il seguente link per poppler . Per qualche motivo il collegamento nella descrizione di Rodrigo non è lo stesso del repository github.
Tobias

@Keval Dave Hai installato poppler e provato pdf2image su macchina Windows? Quale Windows per favore?
SKR

1
@elPastor puoi aggiungere first_page e last_page nell'argomento della funzione conver_from_path per convertire solo la pagina specificata
Keval Dave

1
@Jacob 500 è il dpi. Compensa la risoluzione richiesta e il calcolo disponibile. Nei miei esperimenti, 500 hanno funzionato bene nella maggior parte dei casi, mentre 300 mi hanno ottenuto immagini a bassa risoluzione.
Keval Dave

36

Ho trovato questa semplice soluzione, PyMuPDF , l'output in un file png. Nota la libreria viene importata come "fitz", un nome storico per il motore di rendering che utilizza.

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)

1
Per favore aggiungi una spiegazione alla tua risposta.
Shanteshwar Inde

1
Una buona libreria e si installa su Windows 10 senza problemi (non sono necessarie ruote). github.com/pymupdf
Compagno Che

7
Questa è la migliore risposta. Questo era l'unico codice che non richiedeva un'installazione aggiuntiva sul mio sistema operativo. Gli script Python dovrebbero concentrarsi sul lavoro all'interno del sistema Python. Non avevo bisogno di installare poppler, pdftoppm, imageMagick o ghostscript, ecc. (Python 3.6)
ZStoneDPM

1
In realtà richiede un'altra installazione (libreria fitz, importata senza nemmeno essere riferita e le sue dipendenze), questa risposta è incompleta (come tutte le risposte a questa domanda)
Tommaso Guerrini

1
@JJPty Invece del file pdf preso dal percorso, possiamo prendere da pdfurl? Inoltre, è possibile che il file png sia dati in-stream anziché file png di output?
Shubham Agrawal

18

La libreria Python pdf2image(usata nell'altra risposta) infatti non fa molto di più che lanciarla semplicemente pdttoppm con subprocess.Popen, quindi ecco una versione breve che la fa direttamente:

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

Ecco il collegamento all'installazione di Windows per pdftoppm(contenuto in un pacchetto chiamato poppler): http://blog.alivate.com.au/poppler-windows/


4
Ciao, il collegamento di installazione di Windows per pdftoppm è solo un mucchio di file zippati, cosa devi fare con loro per farli funzionare? Grazie!
gaurwraith

14

Non è necessario installare Poppler sul tuo sistema operativo. Questo funzionerà:

pip install Wand

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)

10
La libreria ImageMagick deve essere installata per funzionare sulla bacchetta.
Neeraj Gulia

2
Ho provato questo e avevo bisogno di installare anche Ghostscript (usando Windows 10 e Python 3.7). Lo ha fatto e ha funzionato perfettamente.
jcf

1
a cosa serve la f [: - 4]? non si fa riferimento da nessun'altra parte
Ari

@Ari f [: - 4] taglierà ".pdf" da filename (string slicing) per creare un nuovo nome file con altri ext.
Fabian

9

@gaurwraith, installa poppler per Windows e usa pdftoppm.exe come segue:

  1. Scarica il file zip con gli ultimi binari / dll di Poppler da http://blog.alivate.com.au/poppler-windows/ e decomprimilo in una nuova cartella nella cartella dei file di programma. Ad esempio: "C: \ Programmi (x86) \ Poppler".

  2. Aggiungi "C: \ Program Files (x86) \ Poppler \ poppler-0.68.0 \ bin" alla variabile d'ambiente SYSTEM PATH.

  3. Dalla riga cmd installa il modulo pdf2image -> "pip install pdf2image".

  4. O in alternativa, esegui direttamente pdftoppm.exe dal tuo codice usando il modulo sottoprocesso di Python come spiegato dall'utente Basj.

@vishvAs vAsuki, questo codice dovrebbe generare i jpg che desideri attraverso il modulo di sottoprocesso per tutte le pagine di uno o più pdf in una determinata cartella:

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

Oppure utilizzando il modulo 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")

Questo ha aiutato molto. Grazie!
Sreekiran

1
Questa dovrebbe essere effettivamente la risposta accettata. Mostra cosa fare con i binari installati per Poppler
Kunj Mehta

3

La loro è un'utilità chiamata pdftojpg che può essere utilizzata per convertire il pdf in img

Puoi trovare il codice qui 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)

2
questa cosa di Java ha appena cancellato la mia intera cartella piena di pdf che manipolano gli script Python ....?
Ulf Gjerdingen

2

GhostScript è molto più veloce di Poppler per un sistema basato su Linux.

Di seguito è riportato il codice per la conversione da PDF a immagine.

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 può essere installato su macOS utilizzando brew install ghostscript

Le informazioni di installazione per altre piattaforme possono essere trovate qui . Se non è già installato sul tuo sistema.


0

Uso un'opzione (forse) molto più semplice di 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

Questa è una piccola parte di uno script bash in un ciclo per l'uso di un dispositivo di casting stretto. Controlla ogni 5 secondi i file pdf aggiunti (tutti) e li elabora. Questo è per un dispositivo demo, alla fine la conversione verrà eseguita su un server remoto. Conversione in .PNG ora, ma è possibile anche .JPG.

Questa conversione, insieme alle transizioni in formato A4, alla visualizzazione di un video, due testi a scorrimento fluido e un logo (con transizione in tre versioni) imposta il Pi3 al massimo 4x 100% di carico della CPU ;-)


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')

Questa sarebbe una risposta migliore se spiegassi come il codice che hai fornito risponde alla domanda.
pppery

1
@pppery Python è abbastanza leggibile, i commenti indicano la cartella di origine e la cartella di output, il resto si legge come l'inglese.
Ari

-1

Ecco una soluzione che non richiede librerie aggiuntive ed è molto veloce. Questo è stato trovato da: https://nedbatchelder.com/blog/200712/extracting_jpgs_from_pdfs.html# Ho aggiunto il codice in una funzione per renderlo più 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

Chiama convert con il percorso pdf come argomento e la funzione creerà un file .jpg nella stessa directory


1
Questa tecnica sembra estrarre le immagini che sono state incorporate nel file, piuttosto che rasterizzare una pagina del file come un'immagine che è ciò che l'interrogante voleva.
Josh Gallagher,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.