在Python中从PDF中提取图像而不重新取样?

118 投票
24 回答
197356 浏览
提问于 2025-04-15 21:55

怎样从一个PDF文档中提取出所有的图片,并保持它们的原始分辨率和格式呢?也就是说,提取出来的TIFF格式的图片要保持TIFF格式,JPEG格式的图片要保持JPEG格式,等等,而且不进行重新采样。图片在页面上的位置我不太在意。

24 个回答

32

在PDF文件中,图片通常是直接存储的。比如说,如果一个PDF里插入了一个jpg图片,那么在这个PDF的某个地方会有一段字节数据,这段数据提取出来后就是一个有效的jpg文件。你可以利用这个特性很简单地从PDF中提取字节范围。我之前写过一篇文章,里面有示例代码,讲解了如何提取PDF中的jpg图片:从PDF中提取JPG图片

64

在Python中,使用和Pillow这两个库来处理PDF文件非常简单:

from pypdf import PdfReader

reader = PdfReader("example.pdf")
for page in reader.pages:
    for image in page.images:
        with open(image.name, "wb") as fp:
            fp.write(image.data)

请注意:PyPDF2已经不再维护了,建议使用pypdf。

98

你可以使用一个叫做PyMuPDF的模块。这个模块可以把所有的图片输出为.png格式的文件,而且使用起来非常简单,速度也很快。

import fitz
doc = fitz.open("file.pdf")
for i in range(len(doc)):
    for img in doc.getPageImageList(i):
        xref = img[0]
        pix = fitz.Pixmap(doc, xref)
        if pix.n < 5:       # this is GRAY or RGB
            pix.writePNG("p%s-%s.png" % (i, xref))
        else:               # CMYK: convert to RGB first
            pix1 = fitz.Pixmap(fitz.csRGB, pix)
            pix1.writePNG("p%s-%s.png" % (i, xref))
            pix1 = None
        pix = None

这里有更多资源可以参考

下面是一个适用于fitz 1.19.6的修改版本:

import os
import fitz  # pip install --upgrade pip; pip install --upgrade pymupdf
from tqdm import tqdm # pip install tqdm

workdir = "your_folder"

for each_path in os.listdir(workdir):
    if ".pdf" in each_path:
        doc = fitz.Document((os.path.join(workdir, each_path)))

        for i in tqdm(range(len(doc)), desc="pages"):
            for img in tqdm(doc.get_page_images(i), desc="page_images"):
                xref = img[0]
                image = doc.extract_image(xref)
                pix = fitz.Pixmap(doc, xref)
                pix.save(os.path.join(workdir, "%s_p%s-%s.png" % (each_path[:-4], i, xref)))
                
print("Done!")

撰写回答