以 jpeg 格式从 pdf 文件中提取页面

在 python 代码中,如何有效地将 pdf 中的某个页面保存为 jpeg 文件?(用例: 我有一个 python flask web 服务器,其中将上传 pdf-s,对应于每个页面的 jpeg-s 是存储。)

这个解决方案 很接近,但问题是它没有将整个页面转换为 jpeg。

288225 次浏览

可以使用 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 Pdf 图片还提到它使用 pdftoppm,并且需要其他安装:

Pdftoppm 是一个实现真正魔力的软件。它是作为称为 Poppler的更大包的一部分分发的。 Windows 用户必须安装 窗用爆破器。 Mac 用户必须安装 给 Mac 的 Poppler。 Linux 用户将在发行版中预先安装 pdftoppm (在 Ubuntu 和 Archlinux 上测试) ,如果没有,运行 sudo apt install poppler-utils

你可以使用水蟒在 Windows 下安装最新版本,方法是:

conda install -c conda-forge poppler

注意: 0.67以下的 Windows 版本可以在 http://blog.alivate.com.au/poppler-windows/上找到,但是请注意,0.68是 于2018年8月公布,所以您不会得到最新的特性或 bug 修复。

Python 库 pdf2image(在另一个答案中使用)实际上并不使用 subprocess.Popen来处理 不仅仅是发射 pdttoppm,因此下面是一个直接处理 不仅仅是发射 pdttoppm的简短版本:

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

下面是 pdftoppm的 Windows 安装链接(包含在一个名为 poppler 的包中) : http://blog.alivate.com.au/poppler-windows/

它们是一个名为 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)

@ gaurwraith,为 Windows 安装 poppler 并使用 pdftoppm.exe 如下:

  1. http://blog.alivate.com.au/poppler-windows/下载带有 Poppler 最新二进制文件/dlls 的 zip 文件,并将其解压到程序文件文件夹中的一个新文件夹中。例如: “ C: Program Files (x86) Poppler”。

  2. 添加“ C: Program Files (x86) Poppler Poppler-0.68.0 bin”到你的系统路径环境变量。

  3. 从 cmd 行安装 pdf2image 模块-> “ pip install pdf2image”。

  4. 或者,也可以使用 Python 的子进程模块直接从代码中执行 pdftoppm.exe,用户 Basj 对此进行了解释。

@ vishvAs vAsuki,这段代码应该通过子进程模块为给定文件夹中一个或多个 pdf 的所有页面生成所需的 jpgs:

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

没有必要在你的操作系统上安装 Poppler:

安装魔杖

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)

我找到了这个简单的解决方案,PyMuPDF,输出为 png 文件。注意,这个库被导入为“ fitz”,这是它所使用的呈现引擎的历史名称。

import fitz


pdffile = "infile.pdf"
doc = fitz.open(pdffile)
page = doc.load_page(0)  # number of page
pix = page.get_pixmap()
output = "outfile.png"
pix.save(output)

注意: 库从使用“ camelCase”改为使用“ Snake _ case”。如果遇到函数不存在的错误,请查看 不推崇的名称。上面示例中的函数已相应更新。

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

我使用了一个(也许)更简单的 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 文件(所有)并处理它们。 这是一个演示设备,最后转换将在远程服务器上完成。转换到。巴布亚新几内亚,但是。JPG 也是可能的。

这种转换,连同 A4格式的转换,显示一个视频,两个平滑的滚动文本和一个徽标(有三个版本的转换)设置 Pi3几乎4x100% CPU 负载; -)

对于基于 Linux 的系统,GhostScript 的性能比 Poppler 快得多。

下面是 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)

可以使用 brew install ghostscript在 macOS 上安装 GhostScript

其他平台的安装信息可以找到 给你。如果它还没有安装在您的系统上。

下面是一个不需要额外库且速度非常快的解决方案。这可以从以下 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 路径作为参数调用 Convert,函数将创建一个。同一目录下的 jpg 文件

一个问题,每个人都将面临的是 安装波普勒。我的方法是一个棘手的方法,但将有效地工作。首先下载 波普勒 给你。然后解压缩它添加在代码部分只添加 Poppler _ path = r‘ C: Program Files poppler-0.68.0 bin’(例如)如下

from pdf2image import convert_from_path
images = convert_from_path("mypdf.pdf", 500,poppler_path=r'C:\Program Files\poppler-0.68.0\bin')
for i, image in enumerate(images):
fname = 'image'+str(i)+'.png'
image.save(fname, "PNG")

下面是一个函数,它将 PDF 档案一页或多页转换为 单合并 JPEG 图像

import os
import tempfile
from pdf2image import convert_from_path
from PIL import Image


def convert_pdf_to_image(file_path, output_path):
# save temp image files in temp dir, delete them after we are finished
with tempfile.TemporaryDirectory() as temp_dir:
# convert pdf to multiple image
images = convert_from_path(file_path, output_folder=temp_dir)
# save images to temporary directory
temp_images = []
for i in range(len(images)):
image_path = f'{temp_dir}/{i}.jpg'
images[i].save(image_path, 'JPEG')
temp_images.append(image_path)
# read images into pillow.Image
imgs = list(map(Image.open, temp_images))
# find minimum width of images
min_img_width = min(i.width for i in imgs)
# find total height of all images
total_height = 0
for i, img in enumerate(imgs):
total_height += imgs[i].height
# create new image object with width and total height
merged_image = Image.new(imgs[0].mode, (min_img_width, total_height))
# paste images together one by one
y = 0
for img in imgs:
merged_image.paste(img, (0, y))
y += img.height
# save merged image
merged_image.save(output_path)
return output_path

示例用法:-

convert_pdf_to_image("path_to_Pdf/1.pdf", "output_path/output.jpeg")

对于一个多页的 pdf 文件,以下是最好和最简单的(我使用 pdf2image-1.14.0) :

from pdf2image import convert_from_path
from pdf2image.exceptions import (
PDFInfoNotInstalledError,
PDFPageCountError,
PDFSyntaxError
)
        

images = convert_from_path(r"path/to/input/pdf/file", output_folder=r"path/to/output/folder", fmt="jpg",) #dpi=200, grayscale=True, size=(300,400), first_page=0, last_page=3)
        

images.clear()

注:

  1. “图像”是 PIL 图像的列表。
  2. 在输出文件夹中保存的映像将具有系统生成的名称; 以后可以根据需要更改它们。
from pdf2image import convert_from_path


PDF_file = 'Statement.pdf'
pages = convert_from_path(PDF_file, 500,userpw='XXX')


image_counter = 1


for page in pages:


filename = "foldername/page_" + str(image_counter) + ".jpg"
page.save(filename, 'JPEG')
image_counter = image_counter + 1

我编写这个脚本是为了很容易地将包含 PDF (单页)的文件夹目录转换为 PNG。

import os
from pathlib import PurePath
import glob
# from PIL import Image
from pdf2image import convert_from_path
import pdb


# In[file list]


wd = os.getcwd()


# filter images
fileListpdf = glob.glob(f'{wd}//*.pdf')


# In[Convert pdf to images]


for i in fileListpdf:
    

images = convert_from_path(i, dpi=300)
    

path_split = PurePath(i).parts
fileName, ext = os.path.splitext(path_split[-1])
    

images[0].save(f'{fileName}.png', 'PNG')

如果您需要将 PDF 文件转换为 PNG 文件,希望这会有所帮助!

使用 pypdfium2:

python3 -m pip install pypdfium2
import pypdfium2 as pdfium


# Load a document
filepath = "tests/resources/multipage.pdf"
pdf = pdfium.PdfDocument(filepath)


# render a single page (in this case: the first one)
page = pdf.get_page(0)
pil_image = page.render_to(
pdfium.BitmapConv.pil_image,
)
pil_image.save("output.jpg")


# render multiple pages concurrently (in this case: all)
page_indices = [i for i in range(len(pdf))]
renderer = pdf.render_to(
pdfium.BitmapConv.pil_image,
page_indices = page_indices,
)
for image, index in zip(renderer, page_indices):
image.save("output_%02d.jpg" % index)

优点:

  • PDFium 是自由许可的(BSD3-子句或 Apache 2.0,由您选择)
  • 在速度方面,pypdfium2几乎可以达到 PyMuPDF
  • 根据需要返回 PIL.Image.Imagenumpy.ndarray、字节或 ctype 数组
  • 能够处理加密的(密码保护的) PDF 文件
  • 没有强制运行时依赖项
  • 支持 Python > = 3.6
  • 安装基础设施符合 PEP 517/518,而遗留安装仍然可以工作

车轮目前可用于

  • Windows AMD64,win32,arm64
  • macOS x86 _ 64,arm64
  • Linux (glibc) x86 _ 64,i686,aarch64,armv7l
  • Linux (musl) x86 _ 64,i686

还有一个要从源代码构建的脚本。

(免责声明: 我是作者)

这个简单的脚本可以将包含 PDF (单页/多页)的文件夹目录转换为 jpeg。

from PIL import Image
import pytesseract
import sys
from pdf2image import convert_from_path
import os
from os import listdir
from os import system
from os.path import isfile, join, basename, dirname
import shutil


def move_processed_file(file, doc_path, download_processed):
try:
shutil.move(doc_path + '/' + file, download_processed + '/' + file)
pass
except Exception as e:
print(e.errno)
raise
else:
pass
finally:
pass
pass




def run_conversion():
root_dir = os.path.abspath(os.curdir)


doc_path = root_dir + r"\data\download"
pdf_processed = root_dir + r"\data\download\pdf_processed"
results_folder = doc_path


files = [f for f in listdir(doc_path) if isfile(join(doc_path, f))]


pdf_files = [f for f in listdir(doc_path) if isfile(join(doc_path, f)) and f.lower().endswith('.pdf')]


# check OS type
if os.name == 'nt':
# if is windows or a graphical OS, change this poppler path with your own path
poppler_path = r"C:\poppler-0.68.0\bin"
else:
poppler_path = root_dir + r"\usr\bin"


for file in pdf_files:


'''
# Converting PDF to images
'''


# Store all the pages of the PDF in a variable
pages = convert_from_path(doc_path + '/' + file, 500, poppler_path=poppler_path)


# Counter to store images of each page of PDF to image
image_counter = 1


filename, file_extension = os.path.splitext(file)


# Iterate through all the pages stored above
for page in pages:
# Declaring filename for each page of PDF as JPG
# PDF page n -> page_n.jpg
filename = filename + '_' + str(image_counter) + ".jpg"


# Save the image of the page in system
page.save(results_folder + '/' + filename, 'JPEG')


# Increment the counter to update filename
image_counter += 1


move_processed_file(file, doc_path, pdf_processed)