Витягніть сторінку з PDF у форматі jpeg


95

У коді python, як ефективно зберегти певну сторінку в pdf як jpeg-файл? (Варіант використання: я маю веб-сервер колби python, куди будуть завантажені pdf-файли, а jpeg-s, що відповідають кожній сторінці, зберігаються.)

Це рішення близьке, але проблема в тому, що воно не перетворює всю сторінку у jpeg.


1
Залежно від зображення, його може бути краще витягти у форматі PNG. Це застосовується, якщо сторінка містить переважно текст.
Пол Руні,

Відповіді:


125

Можна використовувати бібліотеку pdf2image.

Ви можете встановити його, просто використовуючи,

pip install pdf2image

Після встановлення ви можете використовувати наступний код для отримання зображень.

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

Збереження сторінок у форматі jpeg

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

Редагувати: Github repo pdf2image також згадує про те, що воно використовує pdftoppmта що вимагає інших установок:

pdftoppm - це програмне забезпечення, яке робить справжню магію. Він поширюється як частина більшого пакета, який називається poppler . Користувачам Windows доведеться встановити poppler для Windows . Користувачам Mac доведеться встановити poppler для Mac . Користувачам Linux буде попередньо встановлено pdftoppm з дистрибутивом (протестовано на Ubuntu та Archlinux), якщо це не так, запустіть sudo apt install poppler-utils.

Ви можете встановити останню версію під Windows за допомогою anaconda, виконавши:

conda install -c conda-forge poppler

Примітка: Версії Windows до 0.67 доступні за адресою http://blog.alivate.com.au/poppler-windows/, але зверніть увагу, що 0.68 вийшов у серпні 2018 року, тому ви не будете отримувати найновіші функції та виправлення помилок.


4
Привіт, poppler - це просто заархівований файл, він нічого не встановлює, що слід робити з файлами dll або bin?
gaurwraith

@gaurwraith: Скористайтеся наступним посиланням для poppler . Чомусь посилання в описі від Родріго не таке, як у репозиторії github.
Тобіас,

@Keval Dave Ви встановили poppler і пробували pdf2image на машині Windows? Який Windows, будь ласка?
SKR

1
@elPastor, ви можете додати first_page і last_page в аргумент функції convert_from_path, щоб перетворити лише вказану сторінку
Кеваль Дейв

1
@Jacob 500 - dpi. Це компроміс з необхідною роздільною здатністю та доступними обчисленнями. У моїх експериментах 500 працювали добре в більшості випадків, тоді як 300 отримували низькі зображення.
Keval Dave

36

Я знайшов це просте рішення, PyMuPDF , вихід у файл png. Зверніть увагу, що бібліотека імпортується як "fitz", історична назва механізму візуалізації, який вона використовує.

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
Будь ласка, додайте пояснення до своєї відповіді.
Shanteshwar Inde,

1
Хороша бібліотека, і вона встановлюється на Windows 10 без проблем (колеса не потрібні). github.com/pymupdf
Товариш Че

7
Це КРАЩА відповідь. Це був єдиний код, який не вимагав додаткової установки на мою ОС. Сценарії Python повинні бути зосереджені на роботі в системі Python. Мені не потрібно було встановлювати poppler, pdftoppm, imageMagick або ghostscript тощо (Python 3.6)
ZStoneDPM

1
Насправді для цього потрібна інша установка (бібліотека fitz, імпортована навіть без посилання та її залежностей), ця відповідь є неповною (як і всі відповіді на це питання)
Томмазо Герріні,

1
@JJPty Замість pdf-файлу, взятого із шляху, чи можемо ми взяти з pdfurl? Крім того, чи можливо, щоб файл png був потоковими даними, а не вихідним png-файлом?
Шубхем Агравал

18

Бібліотека Python pdf2image(використана в іншій відповіді) насправді робить не набагато більше, ніж просто запускати за pdttoppm допомогою subprocess.Popen, тому ось коротка версія, яка робить це безпосередньо:

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

Ось посилання для встановлення Windows для pdftoppm(що міститься в пакеті з іменем poppler): http://blog.alivate.com.au/poppler-windows/


4
Привіт, посилання для встановлення Windows для pdftoppm - це лише сукупність файлів, що заархівовані. Що ти маєш із ними робити, щоб вони працювали? Дякую!
gaurwraith

14

Немає необхідності встановлювати Poppler у вашій ОС. Це буде працювати:

pip встановити 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
Для роботи на паличці потрібно встановити бібліотеку ImageMagick .
Neeraj Gulia

2
Я спробував це, і мені також потрібно було встановити Ghostscript (за допомогою Windows 10 та Python 3.7). Зробив це, і це спрацювало чудово.
jcf

1
для чого f [: - 4]? на нього більше ніде не згадується
Арі

@Ari f [: - 4] виріже ".pdf" з імені файлу (нарізання рядків), щоб створити нове ім'я файлу з іншими ext.
Фабіан

9

@gaurwraith, встановіть poppler для Windows і використовуйте pdftoppm.exe наступним чином:

  1. Завантажте zip-файл із останніми двійковими файлами / dll Poppler з http://blog.alivate.com.au/poppler-windows/ та розпакуйте в нову папку у папці програмних файлів. Наприклад: "C: \ Program Files (x86) \ Poppler".

  2. Додайте "C: \ Program Files (x86) \ Poppler \ poppler-0.68.0 \ bin" до змінної середовища SYSTEM PATH.

  3. З рядка cmd встановіть pdf2image модуль -> "pip install pdf2image".

  4. Або ж безпосередньо запустіть pdftoppm.exe з вашого коду, використовуючи модуль підпроцесу Python, як пояснив користувач Basj.

@vishvAs vAsuki, цей код повинен генерувати jpgs, які ви хочете, через модуль підпроцесу для всіх сторінок одного або декількох pdfs у даній папці:

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

Або за допомогою модуля 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")

Це дуже допомогло. Дякую!
Срікіран

1
Це насправді має бути прийнятою відповіддю. Показує, що робити з встановленими двійковими
Kunj Mehta

3

Їх утиліта називається pdftojpg, яку можна використовувати для перетворення pdf в img

Ви можете знайти код тут 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
чи ця річ у Java просто видалила мою цілу папку, повну PDF, яка маніпулює сценаріями python ....?
Ульф Джердінген

2

GhostScript працює набагато швидше, ніж Poppler, для системи на базі Linux.

Нижче наведено код для перетворення PDF у зображення.

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 можна встановити на macOS за допомогою brew install ghostscript

Інформацію про встановлення інших платформ можна знайти тут . Якщо він ще не встановлений у вашій системі.


0

Я використовую (можливо) набагато простіший варіант 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

Це невелика частина сценарію bash у циклі для використання вузького пристрою для лиття. Кожні 5 секунд перевіряє додані файли PDF (усі) та обробляє їх. Це для демонстраційного пристрою, в кінці конвертація буде виконана на віддаленому сервері. Перетворення на .PNG зараз, але .JPG теж можливо.

Це перетворення, разом із переходами у форматі А4, відображенням відео, двома плавними текстами, що прокручуються, та логотипом (з переходом у трьох версіях) встановлює Pi3 на 4х 100% завантаження процесора ;-)


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

Це було б кращою відповіддю, якби ви пояснили, як наданий вами код відповідає на запитання.
пуппі

1
@pppery Python досить читабельний, коментарі вказують вихідну папку та вихідну папку, решта читається як англійська.
Арі

-1

Ось рішення, яке не вимагає додаткових бібліотек і є дуже швидким. Це було знайдено з: https://nedbatchelder.com/blog/200712/extracting_jpgs_from_pdfs.html# Я додав код у функцію, щоб зробити її зручнішою.

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

Виклик перетворення з використанням шляху pdf як аргументу, і функція створить файл .jpg у тому ж каталозі


1
Цей прийом виглядає так, ніби він витягує зображення, вбудовані у файл, а не растеризує сторінку файлу як зображення, що саме і хотів запитувач.
Джош Галлахер,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.