图片与PDF文件相互转换
一、概述
本文实现了提取PDF文件中包含的图片,和将多个图片合并转换为PDF文件,并给出了相应的python代码,说明了其中的几处注意要点。
二、提取PDF文件中的图片
2.1代码实现
python代码如下:
python
import fitz
import io
from PIL import Image
import os
def extract_images_from_pdf(pdf_path, outputImg_folder):
if not os.path.exists(outputImg_folder):
os.makedirs(outputImg_folder)
# 打开PDF文件
pdf_document = fitz.open(pdf_path)
# 遍历PDF中的每一页
for page_number in range(len(pdf_document)):
page = pdf_document.load_page(page_number)
image_list = page.get_images(full=True)
# 遍历每个页面中的每张图片
for image_index, img in enumerate(image_list):
xref = img[0]
base_image = pdf_document.extract_image(xref)
image_bytes = base_image["image"]
# 将图像字节转换为PIL图像
image = Image.open(io.BytesIO(image_bytes))
# 生成输出文件名
output_file = f"{outputImg_folder}/image_page_{page_number + 1:0=3d}_{image_index + 1:0=3d}.{image.format.lower()}"
# 保存图像
image.save(output_file)
print(f"保存图像: {output_file}")
2.2注意要点
2.2.1代码使用
需要注意的是,上述代码只能提取非扫描的PDF文档,如果是扫描的PDF文档,那么会将文档每一页当作图片提取出来。
2.2.2依赖包
上述代码主要是使用fitz软件包实现的PDF文件中图片提取,fitz也叫PyMuPDF,安装命令如下:
powershell
pip install pymupdf
2.2.3图片序号设置
代码在给提取的图片命名时,将图片序号设置为3位数字,不足3位则自动补零,保证了在后续处理中能够获得排序正确的图片列表。
三、图片转换为PDF文件
3.1代码实现
python代码如下:
python
def convert_images_to_pdf(img_path, output_pdf_path, adjust=True):
# 创建PDF文件
c = canvas.Canvas(output_pdf_path, pagesize=letter)
width, height = letter
page_width = width
page_height = height
renderDPI = 96
image_paths = []
if os.path.isfile(img_path):
image_paths.append(img_path)
elif os.path.isdir(img_path):
image_extensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'tif', 'tiff']
for filename in os.listdir(img_path):
image_paths.append(os.path.join(img_path, filename))
else:
print('图片路径输入错误')
return
for image_path in image_paths:
# 打开图片
image = Image.open(image_path)
image_width, image_height = image.size
if adjust:
# 调整图片尺寸以适应页面,居中显示,保持图片长宽比例
aspect = image_width / image_height
if image_width > image_height:
canvas_width = page_width
canvas_height = page_width / aspect
else:
canvas_height = page_height
canvas_width = page_height * aspect
if canvas_width > page_width:
canvas_width = page_width
canvas_height = page_width / aspect
if canvas_height > page_height:
canvas_height = page_height
canvas_width = page_height * aspect
# 计算图片的居中位置
x = (page_width - canvas_width) / 2
y = (page_height - canvas_height) / 2
else:
canvas_width = image_width / renderDPI * 72
canvas_height = image_height / renderDPI * 72
# 设置页面大小与图片尺寸匹配
c.setPageSize((canvas_width, canvas_height))
x = 0
y = 0
# 添加图片到PDF页面
c.drawImage(image_path, x, y, canvas_width, canvas_height)
c.showPage() # 创建新的一页
print(image_path)
c.save() # 保存PDF文件
3.2注意要点
3.2.1代码使用
上述代码根据传入参数自动判断图片数量为单张或多张,实现了单张或多张图片转换为PDF文件,每张图片占一页PDF。
转换后的PDF文件尺寸有两种选项,通过adjust参数控制,一种是统一设定PDF文件所有页面尺寸,为适应尺寸图片会被缩放,但保留长宽比,另一种是不对图片进行缩放,每一页文档的尺寸随图片的尺寸不同而变化。
3.2.2PDF文件尺寸设置
当adjust为True时,PDF文件所有页面尺寸会被统一设置,代码中设置为letter信纸尺寸:8.5 x 11 英寸,此时图片将被缩放,只保留长宽比,缩放后的图片居中显示,此时不需要计算图片尺寸,只需计算图片的长宽比。
需要注意的是,图片虽然被缩放,但图片的质量并没有被改变。在PDF查看器的缩放比例为100%时,缩放后的图片可能会显得模糊,但只要调整缩放比例就能够清晰显示。
关于PDF文件尺寸更多详细信息,可参照本博客的另一篇文章:DPI简析。
3.2.3PDF文件中图片尺寸计算
当adjust为False时,不对图片进行缩放,每一页文档的尺寸随图片的尺寸不同而变化,那么此时需要计算出PDF文件中图片的尺寸大小。
尺寸属性并不是图片的固有属性,只有在打印或显示图片时,图片才具有尺寸属性,而PDF文件布局是以尺寸为量化标准的,PDF中尺寸的单位为点(points),1点等于1/72英寸,所以需要计算出图片在PDF中的尺寸。
PDF文件在显示时会首先被渲染,将尺寸转换为像素,像素数=尺寸×渲染DPI,根据这个公式可以反推出图片在PDF文件中的尺寸,即=图片像素数÷渲染DPI,此时单位为英寸,还应转换为点,所以完整的计算公式如下:
图片在PDF文件中的尺寸=图片像素数÷渲染DPI×72
此处的图片在PDF文件中的尺寸与图片的显示尺寸两个概念可能会让读者混淆,二者的关系其实是PDF的实际物理尺寸与显示尺寸的关系,更多信息可见DPI简析。