1.缘起
最近需要将记的笔记整理成一个 pdf 进行保存,所以就研究了一下如何利用 Python 代码将拍下来的照片整个合并成一个 pdf。
2.过程
拿到一个需求最重要的就是将大块任务拆分成一个个小模块,逐个击破。
2.1拍照
这一步首先是将所有的书页拍好,需要注意的是要按照书的页码来拍,因为后面的排序是按照文件名进行排序的,拍照的文件名基本上是按照时间生成的,如果拍的时候乱了,到时候生成的 pdf 里面的页码也会乱掉。
2.2 Python 操作库
Python 最好的地方就是有大量的第三方库能帮我们快速实现我们想要的方法,搜索到了两个库,
PyFPDF 和img2pdf,我们这里选择img2pdf来完成我们的需求
pip install img2pdf
2.3 Python遍历文件夹获取图片
dirname = "f:/wlzcool" imgs = [] for fname in os.listdir(dirname): if not fname.endswith(".jpg"): continue path = os.path.join(dirname, fname) if os.path.isdir(path): continue imgs.append(path)
需要注意图片的文件名如果是纯数字且位数不一样,排序会为1之后是10而不是2,需要对数字进行一个额外的排序,如果是手机拍的文件就没有这个问题。
files.sort(key=lambda x: int(x[:-4]))
2.4 旋转图片展示方向并压缩像素
有的时候手机拍出来的图片是水平的,需要将其改为竖直的
用rotate旋转方向的时候需要注意加上expand=True 这个参数,否则会有黑边出现。
手机的照片像素太高,有的需要进行压缩以保证最后生成的pdf的大小适中。
img = Image.open(path) if img.size[0] > img.size[1]: im_rotate = img.rotate(90, expand=True) size = (int(im_rotate.size[0] / 3), int(im_rotate.size[1] / 3)) im_rotate = im_rotate.resize(size) im_rotate.save(savepath, quality=95) else: size = (int(img.size[0] / 3), int(img.size[1] / 3)) img = img.resize(size) img.save(savepath, quality=95)
2.5 整体代码
写成脚本需要考虑的有很多,为了方便使用,需要将各种参数改为允许用户输入的。比如图片文件夹所在的路径,压缩比之类的
from PIL import Image import os import img2pdf flag = False while not flag: dirname = input("请输入图片文件夹所在路径(例如d:/wlzcool):") flag = os.path.exists(dirname) if not flag: print("图片文件夹所在路径不存在!") saveflag = False while not saveflag: savedirname = input("请输入目标图片文件夹所在路径(例如d:/wlzcool2):") saveflag = os.path.exists(savedirname) if not saveflag: print("图片文件夹所在路径不存在!") automakedir = input("是否自动创建对应文件夹?(是Y/否N):") if automakedir.strip().upper() == "Y": os.makedirs(savedirname) saveflag = True files = os.listdir(dirname) reductionFactor = int(input("请输入长宽压缩比(例如3):")) if reductionFactor <= 0: reductionFactor = 3 isConvertBlack = input("是否输出黑白版本?(是Y/否N):").strip().upper() == "Y" for fname in files: if not fname.endswith(".jpg"): continue path = os.path.join(dirname, fname) savePath = os.path.join(savedirname, fname) if os.path.isdir(path): continue img = Image.open(path) if img.size[0] > img.size[1]: im_rotate = img.rotate(90, expand=True) size = (int(im_rotate.size[0] / reductionFactor), int(im_rotate.size[1] / reductionFactor)) im_rotate = im_rotate.resize(size) if isConvertBlack: im_rotate = im_rotate.convert("L") im_rotate.save(savePath, quality=95) else: size = (int(img.size[0] / reductionFactor), int(img.size[1] / reductionFactor)) img = img.resize(size) if isConvertBlack: img = img.convert("L") img.save(savePath, quality=95) filename = input("请输入输出文件名(例如:第一章):") with open(filename + ".pdf", "wb") as f: imgs = [] files = os.listdir(savedirname) for fname in files: if not fname.endswith(".jpg"): continue path = os.path.join(savedirname, fname) if os.path.isdir(path): continue imgs.append(path) f.write(img2pdf.convert(imgs))
2.6将脚本打包成exe
不是所有的电脑都有Python环境,我们需要将脚本打包成exe方便在任意一台电脑上使用。
使用 PyInstaller 来进行脚本的打包
2.6.1 安装 PyInstaller
pip install pyinstaller
2.6.2 打包脚本
在脚本所在的路径的cmd中执行以下命令即可
pyinstaller -F yourprogram.py
人生苦短,我用 Python,强大的第三方库可以令我们省掉不少时间开发一个很有意思的 Python图片合并 pdf 的小应用,Python 就是很酷!