Wyodrębnij stronę z pliku PDF jako jpeg

100

W kodzie Pythona, jak efektywnie zapisać określoną stronę w pliku PDF jako plik jpeg? (Przykład zastosowania: mam serwer sieciowy python flask, na którym zostaną przesłane pliki PDF, a pliki jpeg odpowiadające każdej stronie są przechowywane).

To rozwiązanie jest bliskie, ale problem polega na tym, że nie konwertuje ono całej strony do formatu jpeg.

vishvAs vAsuki
źródło
1
W zależności od obrazu może być lepiej wyodrębnić jako plik png. Miałoby to zastosowanie, gdyby strona zawierała głównie tekst.
Paul Rooney

Odpowiedzi:

134

Można użyć biblioteki pdf2image.

Możesz go zainstalować po prostu za pomocą,

pip install pdf2image

Po zainstalowaniu możesz użyć następującego kodu, aby pobrać obrazy.

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

Zapisywanie stron w formacie jpeg

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

Edycja: repozytorium Github pdf2image wspomina również, że używa pdftoppmi wymaga innych instalacji:

pdftoppm to oprogramowanie, które robi prawdziwą magię. Jest dystrybuowany jako część większego pakietu zwanego poppler . Użytkownicy systemu Windows będą musieli zainstalować poppler dla systemu Windows . Użytkownicy komputerów Mac będą musieli zainstalować poppler dla komputerów Mac . Użytkownicy Linuksa będą mieli preinstalowany program pdftoppm z dystrybucją (testowany na Ubuntu i Archlinux), jeśli tak nie jest, uruchom sudo apt install poppler-utils.

Możesz zainstalować najnowszą wersję w systemie Windows za pomocą programu anaconda, wykonując:

conda install -c conda-forge poppler

Uwaga: wersje Windows do 0.67 są dostępne na http://blog.alivate.com.au/poppler-windows/, ale pamiętaj, że 0.68 został wydany w sierpniu 2018, więc nie będziesz otrzymywać najnowszych funkcji ani poprawek błędów.

Keval Dave
źródło
4
Cześć, poppler to po prostu spakowany plik, nic nie instaluje, co należy zrobić z plikami dll lub bin?
gaurwraith
@gaurwraith: Użyj poniższego linku, aby poppler . Z jakiegoś powodu link w opisie z Rodrigo nie jest tym samym, co w repozytorium github.
Tobias,
1
@elPastor możesz dodać first_page i last_page w argumencie funkcji conver_from_path, aby przekonwertować tylko określoną stronę
Keval Dave
1
@Jacob 500 to dpi. Wiąże się to z wymaganą rozdzielczością i dostępnymi obliczeniami. W moich eksperymentach 500 działało dobrze w większości przypadków, a 300 dało mi obrazy w niskiej rozdzielczości.
Keval Dave,
1
Aby przekonwertować pierwszą stronę pliku PDF i nic więcej, działa to:from pdf2image import convert_from_path pages = convert_from_path('file.pdf', 500) pages = convert_from_path('file.pdf', 500, single_file=True) pages[0].save('file.jpg', 'JPEG')
helgis
38

Znalazłem to proste rozwiązanie, PyMuPDF , wyjście do pliku png. Zauważ, że biblioteka jest importowana jako „fitz”, historyczna nazwa używanego przez nią silnika renderującego.

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
źródło
1
Proszę dodać wyjaśnienie do swojej odpowiedzi.
Shanteshwar Inde
1
Dobra biblioteka i instaluje się na Windows 10 bez problemów (bez kółek). github.com/pymupdf
Comrade Che
7
To jest NAJLEPSZA odpowiedź. To był jedyny kod, który nie wymagał dodatkowej instalacji w moim systemie operacyjnym. Skrypty Pythona powinny skupiać się na pracy w systemie Python. Nie musiałem instalować poppler, pdftoppm, imageMagick lub ghostscript itp. (Python 3.6)
ZStoneDPM
1
Właściwie wymaga innej instalacji (biblioteka fitz, zaimportowana bez odniesienia do niej i jej zależności), ta odpowiedź jest niekompletna (jak wszystkie odpowiedzi na to pytanie)
Tommaso Guerrini
1
@JJPty Czy zamiast pliku pdf pobranego ze ścieżki możemy pobrać plik z pdfurl? Czy plik png może być danymi typu In-Stream, a nie wyjściowym plikiem png?
Shubham Agrawal
19

Biblioteka Pythona pdf2image(stosowany w innych odpowiedzi) w rzeczywistości nie robi znacznie więcej niż tylko rozpoczyna pdttoppm się subprocess.Popen, więc tutaj jest krótka wersja robi to bezpośrednio:

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

Oto łącze instalacyjne systemu Windows dla pdftoppm(zawarte w pakiecie o nazwie poppler): http://blog.alivate.com.au/poppler-windows/

Basj
źródło
4
Cześć, łącze instalacyjne systemu Windows dla pdftoppm to po prostu kilka spakowanych plików, co musisz z nimi zrobić, aby działały? Dzięki!
gaurwraith
14

Nie ma potrzeby instalowania Popplera w twoim systemie operacyjnym. To zadziała:

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)
DevB2F
źródło
12
Biblioteka ImageMagick musi być zainstalowana, aby działać na różdżce.
Neeraj Gulia
3
Próbowałem tego i musiałem również zainstalować Ghostscript (używając Windows 10 i Python 3.7). Zrobiłem to i zadziałało idealnie.
jcf
1
po co to f [: - 4]? nie ma odniesienia nigdzie indziej
Ari
@Ari f [: - 4] wycina „.pdf” z nazwy pliku (cięcie ciągów znaków), aby utworzyć nową nazwę pliku z innym rozszerzeniem.
Fabian
11

@gaurwraith, zainstaluj poppler dla Windows i użyj pdftoppm.exe w następujący sposób:

  1. Pobierz plik zip z najnowszymi plikami binarnymi / dllami Popplera ze strony http://blog.alivate.com.au/poppler-windows/ i rozpakuj do nowego folderu w folderze plików programu. Na przykład: „C: \ Program Files (x86) \ Poppler”.

  2. Dodaj „C: \ Program Files (x86) \ Poppler \ poppler-0.68.0 \ bin” do zmiennej środowiskowej SYSTEM PATH.

  3. Z linii cmd zainstaluj moduł pdf2image -> "pip install pdf2image".

  4. Lub alternatywnie, wykonaj bezpośrednio pdftoppm.exe z kodu za pomocą modułu podprocesu Pythona, jak wyjaśniono przez użytkownika Basj.

@vishvAs vAsuki, ten kod powinien generować pliki jpg, które chcesz za pośrednictwem modułu podprocesu dla wszystkich stron jednego lub więcej plików PDF w danym folderze:

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

Lub korzystając z modułu 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
źródło
To bardzo pomogło. Dzięki!
Sreekiran
1
Właściwie to powinna być akceptowana odpowiedź. Pokazuje, co zrobić z zainstalowanymi plikami binarnymi dla Popplera
Kunj Mehta,
3

Jest to narzędzie o nazwie pdftojpg, które można wykorzystać do konwersji pliku PDF na img

Możesz znaleźć kod tutaj 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)
kaczka
źródło
2
czy ta rzecz java po prostu usunęła cały mój folder pełen PDF manipulujących skryptami Pythona ....?
Ulf Gjerdingen
2

GhostScript działa znacznie szybciej niż Poppler w systemie opartym na systemie Linux.

Poniżej znajduje się kod konwersji PDF do obrazu.

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 można zainstalować na macOS przy użyciu brew install ghostscript

Informacje dotyczące instalacji dla innych platform można znaleźć tutaj . Jeśli nie jest jeszcze zainstalowany w twoim systemie.

Keval Dave
źródło
0

Używam (być może) znacznie prostszej opcji 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

Jest to niewielka część skryptu basha w pętli do korzystania z wąskiego urządzenia rzutującego. Sprawdza co 5 sekund dodane pliki pdf (wszystkie) i przetwarza je. To jest dla urządzenia demonstracyjnego, na końcu konwersja zostanie wykonana na zdalnym serwerze. Konwersja do .PNG teraz, ale .JPG też jest możliwa.

Ta konwersja, wraz z przejściami na format A4, wyświetlaniem wideo, dwoma płynnie przewijanymi tekstami i logo (z przejściem w trzech wersjach) ustawia Pi3 na prawie 4x 100% obciążenia procesora ;-)

Robert
źródło
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
źródło
To byłaby lepsza odpowiedź, gdybyś wyjaśnił, w jaki sposób podany kod odpowiada na pytanie.
pppery
2
@pppery Python jest dość czytelny, komentarze wskazują folder źródłowy i folder wyjściowy, reszta brzmi jak angielski.
Ari
-1

Oto rozwiązanie, które nie wymaga dodatkowych bibliotek i jest bardzo szybkie. Zostało to znalezione z: https://nedbatchelder.com/blog/200712/extracting_jpgs_from_pdfs.html# Dodałem kod w funkcji, aby była wygodniejsza.

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

Wywołaj funkcję convert ze ścieżką pdf jako argumentem, a funkcja utworzy plik .jpg w tym samym katalogu

moo5e
źródło
1
Ta technika wygląda tak, jakby wyodrębniała obrazy, które zostały osadzone w pliku, zamiast rasteryzacji strony pliku jako obrazu, czego chciał pytający.
Josh Gallagher