Trích xuất trang từ pdf dưới dạng jpeg


95

Trong mã python, làm cách nào để lưu hiệu quả một trang nhất định trong pdf dưới dạng tệp jpeg? (Trường hợp sử dụng: Tôi có một máy chủ web bình trăn, nơi pdf-s sẽ được tải lên và jpeg-s tương ứng với mỗi trang là các cửa hàng.)

Giải pháp này là gần đúng, nhưng vấn đề là nó không chuyển đổi toàn bộ trang thành jpeg.


1
Tùy thuộc vào hình ảnh, có thể tốt hơn nếu trích xuất dưới dạng png. Điều này sẽ áp dụng nếu trang chứa chủ yếu là văn bản.
Paul Rooney

Câu trả lời:


125

Thư viện pdf2image có thể được sử dụng.

Bạn có thể cài đặt nó một cách đơn giản bằng cách sử dụng,

pip install pdf2image

Sau khi cài đặt, bạn có thể sử dụng mã sau để lấy hình ảnh.

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

Lưu trang ở định dạng jpeg

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

Chỉnh sửa: pdf2image repo Github cũng đề cập rằng nó sử dụng pdftoppmvà nó yêu cầu các cài đặt khác:

pdftoppm là phần mềm thực hiện điều kỳ diệu. Nó được phân phối như một phần của gói lớn hơn được gọi là poppler . Người dùng Windows sẽ phải cài đặt poppler cho Windows . Người dùng Mac sẽ phải cài đặt poppler cho Mac . Người dùng Linux sẽ được cài đặt sẵn pdftoppm với bản phân phối (Đã thử nghiệm trên Ubuntu và Archlinux), nếu không, hãy chạy sudo apt install poppler-utils.

Bạn có thể cài đặt phiên bản mới nhất trong Windows bằng anaconda bằng cách thực hiện:

conda install -c conda-forge poppler

lưu ý: Phiên bản Windows tối đa 0.67 có sẵn tại http://blog.alivate.com.au/poppler-windows/ nhưng lưu ý rằng 0.68 đã được phát hành vào tháng 8 năm 2018 nên bạn sẽ không nhận được các tính năng hoặc bản sửa lỗi mới nhất.


4
Xin chào, poppler chỉ là một tệp nén, không cài đặt bất cứ thứ gì, người ta phải làm gì với tệp dll hoặc tệp bin?
bò tót

@gaurwraith: Sử dụng liên kết sau đến poppler . Vì một số lý do, liên kết trong mô tả từ Rodrigo không giống như trong repo github.
Tobias

@Keval Dave Bạn đã cài đặt poppler và thử pdf2image trên máy Windows chưa? Làm ơn cho Windows nào?
SKR

1
@elPastor, bạn có thể thêm first_page và last_page vào đối số của hàm convert_from_path để chỉ chuyển đổi trang được chỉ định
Keval Dave

1
@Jacob 500 là dpi. Nó đánh đổi độ phân giải cần thiết và khả năng tính toán. Trong các thử nghiệm của tôi, 500 hoạt động tốt trong hầu hết các trường hợp trong khi 300 cho tôi hình ảnh rez thấp.
Keval Dave

36

Tôi tìm thấy giải pháp đơn giản này, PyMuPDF , xuất ra tệp png. Lưu ý rằng thư viện được nhập dưới dạng "fitz", một tên lịch sử cho công cụ kết xuất mà nó sử dụng.

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
Vui lòng thêm giải thích cho câu trả lời của bạn.
Shanteshwar Inde

1
Một thư viện tốt và nó cài đặt trên Windows 10 mà không gặp vấn đề gì (không cần bánh xe). github.com/pymupdf
Đồng chí Che

7
Đây là câu trả lời TỐT NHẤT. Đây là mã duy nhất không yêu cầu cài đặt thêm vào hệ điều hành của tôi. Các tập lệnh Python nên tập trung vào hoạt động trong hệ thống Python. Tôi không cần cài đặt poppler, pdftoppm, imageMagick hoặc ghostcript, v.v. (Python 3.6)
ZStoneDPM

1
Trên thực tế, nó yêu cầu một cài đặt khác (thư viện fitz, được nhập mà thậm chí không được tham chiếu và các phụ thuộc của nó), câu trả lời này không đầy đủ (giống như tất cả các câu trả lời ở câu hỏi này)
Tommaso Guerrini

1
@JJPty Thay vì lấy tệp pdf từ đường dẫn, chúng ta có thể lấy từ pdfurl không? Ngoài ra, có thể tệp png là dữ liệu trong luồng chứ không phải tệp png đầu ra?
Shubham Agrawal

18

Thư viện Python pdf2image(được sử dụng trong câu trả lời khác) trên thực tế không làm được gì nhiều hơn là chỉ khởi chạy pdttoppm với subprocess.Popen, vì vậy đây là một phiên bản ngắn thực hiện trực tiếp:

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

Đây là liên kết cài đặt Windows cho pdftoppm(có trong một gói có tên poppler): http://blog.alivate.com.au/poppler-windows/


4
Xin chào, liên kết cài đặt Windows cho pdftoppm chỉ là một nhóm các tệp nén, bạn phải làm gì với chúng để chúng hoạt động? Cảm ơn!
bò tót

14

Không cần cài đặt Poppler trên hệ điều hành của bạn. Điều này sẽ hoạt động:

pip cài đặt 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
Thư viện ImageMagick cần được cài đặt để hoạt động trên cây đũa phép.
Neeraj Gulia

2
Tôi đã thử điều này và cũng cần cài đặt Ghostscript (sử dụng Windows 10 và Python 3.7). Đã làm và nó hoạt động hoàn hảo.
jcf

1
f [: - 4] để làm gì? nó không được tham chiếu ở bất kỳ nơi nào khác
Ari

@Ari f [: - 4] sẽ cắt ".pdf" khỏi tên tệp (cắt chuỗi) để tạo tên tệp mới với máy lẻ khác.
Fabian

9

@gaurwraith, cài đặt poppler cho Windows và sử dụng pdftoppm.exe như sau:

  1. Tải xuống tệp zip với tệp nhị phân / dlls mới nhất của Poppler từ http://blog.alivate.com.au/poppler-windows/ và giải nén vào một thư mục mới trong thư mục tệp chương trình của bạn. Ví dụ: "C: \ Program Files (x86) \ Poppler".

  2. Thêm "C: \ Program Files (x86) \ Poppler \ poppler-0.68.0 \ bin" vào biến môi trường SYSTEM PATH của bạn.

  3. Từ dòng cmd install pdf2image module -> "pip install pdf2image".

  4. Hoặc cách khác, trực tiếp thực thi pdftoppm.exe từ mã của bạn bằng mô-đun quy trình con của Python như người dùng Basj giải thích.

@vishvAs vAsuki, mã này sẽ tạo jpgs bạn muốn thông qua mô-đun quy trình con cho tất cả các trang của một hoặc nhiều pdf trong một thư mục nhất định:

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

Hoặc sử dụng mô-đun 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")

Điều này đã giúp rất nhiều. Cảm ơn!
Sreekiran

1
Đây thực sự phải là câu trả lời được chấp nhận. Hiển thị những việc cần làm với các tệp nhị phân đã cài đặt cho Poppler
Kunj Mehta

3

Họ là một tiện ích có tên là pdftojpg có thể được sử dụng để chuyển đổi pdf sang img

Bạn có thể tìm thấy mã ở đây 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
Có phải cái java này chỉ xóa toàn bộ thư mục đầy pdf của tôi với các tập lệnh python thao tác ....?
Ulf Gjerdingen

2

GhostScript hoạt động nhanh hơn nhiều so với Poppler dành cho hệ thống dựa trên Linux.

Sau đây là mã để chuyển đổi pdf sang hình ảnh.

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 có thể được cài đặt trên macOS bằng brew install ghostscript

Thông tin cài đặt cho các nền tảng khác có thể được tìm thấy tại đây . Nếu nó chưa được cài đặt trên hệ thống của bạn.


0

Tôi sử dụng một (có thể) tùy chọn đơn giản hơn nhiều của 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

Đây là một phần nhỏ của tập lệnh bash trong một vòng lặp để sử dụng thiết bị truyền hẹp. Kiểm tra 5 giây một lần trên các tệp pdf đã thêm (tất cả) và xử lý chúng. Đây là thiết bị dùng thử, việc chuyển đổi cuối cùng sẽ được thực hiện tại một máy chủ từ xa. Hiện đang chuyển đổi thành .PNG nhưng .JPG cũng có thể thực hiện được.

Việc chuyển đổi này, cùng với quá trình chuyển đổi trên định dạng A4, hiển thị một video, hai văn bản cuộn mượt mà và một biểu trưng (với quá trình chuyển đổi trong ba phiên bản) đặt Pi3 ở mức tối đa 4x 100% tải 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')

Đây sẽ là câu trả lời tốt hơn nếu bạn giải thích cách mã bạn cung cấp trả lời câu hỏi.
pppery

1
@pppery Python khá dễ đọc, các nhận xét cho biết thư mục nguồn và thư mục đầu ra, phần còn lại đọc như tiếng Anh.
Ari

-1

Đây là một giải pháp không yêu cầu thư viện bổ sung và rất nhanh. Điều này được tìm thấy từ: https://nedbatchelder.com/blog/200712/extract_jpgs_from_pdfs.html# Tôi đã thêm mã vào một hàm để thuận tiện hơn.

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

Gọi convert với đường dẫn pdf làm đối số và hàm sẽ tạo tệp .jpg trong cùng thư mục


1
Kỹ thuật này trông giống như nó trích xuất các hình ảnh đã được nhúng trong tệp, thay vì sắp xếp một trang của tệp dưới dạng hình ảnh mà người hỏi mong muốn.
Josh Gallagher
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.