在Python中从PDF中提取图像而不重新取样?
怎样从一个PDF文档中提取出所有的图片,并保持它们的原始分辨率和格式呢?也就是说,提取出来的TIFF格式的图片要保持TIFF格式,JPEG格式的图片要保持JPEG格式,等等,而且不进行重新采样。图片在页面上的位置我不太在意。
24 个回答
32
在PDF文件中,图片通常是直接存储的。比如说,如果一个PDF里插入了一个jpg图片,那么在这个PDF的某个地方会有一段字节数据,这段数据提取出来后就是一个有效的jpg文件。你可以利用这个特性很简单地从PDF中提取字节范围。我之前写过一篇文章,里面有示例代码,讲解了如何提取PDF中的jpg图片:从PDF中提取JPG图片。
64
在Python中,使用
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!")