前段时间,因工作需要,要将一堆照片弄成PDF,还要保证照片的顺序,一张张的选择正确顺序的照片插入,这效率,不能忍。于是准备写一个程序,把图片按照顺序合成PDF。
需求分析:
- 要保证图片的顺序,只能从文件命名上下手,所以可以把图片命名成数字,数字小的排前面,数字大的排后面,类似这样:
- 这样命名完后,全是数字,又不好分辨,需要给文件加个备注,可以用一个特殊符号来分割数字和备注,类似这样:
- 如果顺序整理好过后,发现有点问题,需要在某处插入一张照片怎么办?可以用小数来解决,类似这样:
大体需求就这样了,现在开始写代码实现。
网上查了一下,python的PDF库 FPDF 可以实现图片插入的功能,先pip install FPDF 一波。
先把图片排好序:
def get_ordered_file_list():
tmp_file_list = []
for file in os.listdir(dir):
file_name, suffix = os.path.splitext(file)
if suffix[1:].lower() in ['jpg', 'jpeg', 'png', 'bmp']:
try:
num = float(file_name.split('-')[0])
tmp_file_list.append((num, os.path.join(dir, file)))
except:
print(file, '提取顺序失败,未加入PDF,可重新将图片命名,重新运行程序')
return [a[1] for a in sorted(tmp_file_list, key=lambda x: x[0])]
制作PDF的操作也很简单:
pdf = FPDF(unit="pt") # 第一步,创建PDF对象
pdf.add_page() # 第二步,增加一页
pdf.image(img_path) # 第三步,加照片
pdf.output('XXX.pdf', 'F') # 第四步,保存
期间参照源码,做了些许改动:对图片进行缩放,对页面的横板竖版进行调整,增加了页码。
完整代码如下:
from fpdf import FPDF
from PIL import Image
import os
import sys
class PDFTool():
def __init__(self, dir_path):
self.pdf = FPDF(unit="pt")
self.pdf.set_font('arial',size=16)
self.dir = dir_path
self.img_type = ['jpg', 'jpeg', 'png', 'bmp']
self.file_list = self.get_ordered_file_list()
def get_ordered_file_list(self):
tmp_file_list = []
for file in os.listdir(self.dir):
file_name, suffix = os.path.splitext(file)
if suffix[1:].lower() in self.img_type:
try:
num = float(file_name.split('-')[0])
tmp_file_list.append((num, os.path.join(self.dir, file)))
except:
print(file, '提取顺序失败,未加入PDF,可重新将图片命名,重新运行程序')
return [a[1] for a in sorted(tmp_file_list, key=lambda x: x[0])]
def makePdf(self):
if not self.file_list:
print('没有满足条件的照片')
return
for file in self.file_list:
img = Image.open(file)
img_width, img_height = img.size
# 595.28,841.89
rate = 0.95
if img_width > img_height:
self.pdf.add_page('L')
if (img_width / img_height) > (841.89 / 595.28):
rate *= 841.89 / img_width
else:
rate *= 595.28 / img_height
self.pdf.image(file, 20, 20, int(img_width * rate), int(img_height * rate))
self.pdf.text(841//2-10,595-10,str(self.pdf.page_no()))
else:
self.pdf.add_page('P')
if (img_width / img_height) > (595.28 / 841.89):
rate *= 595.28 / img_width
else:
rate *= 841.89 / img_height
self.pdf.image(file, 20, 20, int(img_width * rate), int(img_height * rate))
self.pdf.text(595 // 2 - 10, 841 - 10, str(self.pdf.page_no()))
self.pdf.output(os.path.join(self.dir, os.path.split(self.dir)[-1]) + '.pdf', "F")
print(self.dir, '下面有个和文件夹同名的PDF 打开看看')
if __name__ == '__main__':
tool = PDFTool(sys.argv[1])
tool.makePdf()
最终效果图: