今天需要把图片转pdf,发现迅捷pdf转换开始默认带水印了,收费版那算了😂😂,那就用Python吧,可单转,可批量转。
参考: https://blog.csdn.net/qq_53706090/article/details/128261862
pip install img2pdf
pip install pypdf2
这篇博客将介绍 照片转pdf,多图转多个pdf,多图转单个pdf,pdf合并。
wb覆盖,ab+是以二进制格式写入图片到文件,即使设置ab+ 追加文件生成的pdf依然有问题,只有一张图片,需要生成多个pdf再合并。
用pic_to_pdf 可以 生成单图生成单个pdf,多图生成多个pdf后在用 pypdf2 合并生成;
或者用img2pdf 传递单图生成单个pdf,传递多个图片生成单个pdf, 一次性生成一个pdf;
1. 效果图
发现可以成功转换:
2. 源码
# 照片转pdf,多图转多个pdf,多图转单个pdf,pdf合并
# imgToPdf.py
# coding = UTF-8
# 导入Python标准库
import os
from io import BytesIO
import img2pdf
# 导入第三方库
from PIL import Image
# 防止中文乱码
from PyPDF2 import PdfMerger
os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.UTF8'
# 支持的图片文件格式
SUPPORT_SUFFIX = ["jpg", "jpeg", "png"]
def pic_to_pdf(image_bytes: bytes) -> bytes:
"""将单个图片转换为单张PDF
:param image_bytes: 图片的bytes对象
:return: PDF的bytes对象
"""
# 将bytes对象转换为BytesIO对象
image_bytes_io = BytesIO(image_bytes)
# 从内存中读取图片
image_object = Image.open(image_bytes_io)
# 打开内存中的文件用于保存PDF
with BytesIO() as result_bytes_io:
# 将图片保存为单张PDF
image_object.save(result_bytes_io, "PDF", resolution=100.0)
# 获取内存中的文件
data = result_bytes_io.getvalue()
# 返回PDF的bytes对象
return data
def batch_convert(image_path: str, pdf_path: str) -> None:
"""批量将图片转换为单张PDF
:param image_path: 图片的文件夹
:param pdf_path: PDF文件保存的文件夹
"""
# 遍历文件夹下所有文件
for root, dirs, files in os.walk(image_path, topdown=False):
if (root.__contains__("ch/ch102")): break
for name in files:
# 提取文件的后缀名
file_suffix = os.path.splitext(name)[-1].lstrip(".").lower()
# 检测该文件格式是否受到支持
if file_suffix not in SUPPORT_SUFFIX:
continue
# 拼接出图片文件的绝对路径
source_file_path = os.path.join(root, name)
# 拼接出PDF文件的绝对路径
# target_file_path = os.path.join(pdf_path, f"{os.path.splitext(name)[0]}.pdf")
target_file_path = pdf_path
# 将图片文件转换为PDF文件
with open(source_file_path, "rb") as source:
try:
# r:以只读方式打开文件,从头开始读。
# rb:以二进制格式打开一个文件用于只读。
# 关于写入:
# w:打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件
# wb:以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等
# a+:打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式,不会覆盖原有的内容。如果该文件不存在,创建新文件用于读写
# ab+:以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。不会覆盖原有的内容。如果该文件不存在,创建新文件用于读写。
# 即使设置ab+生成的pdf依然有问题,只有一张图片,需要生成多个pdf再合并
with open(target_file_path, "ab+") as target:
target.write(pic_to_pdf(source.read()))
print(source_file_path)
except Exception as e:
print(e)
with open('error.txt', 'a+') as f:
f.writelines('\'' + source_file_path + "\',")
finally:
print('---------------')
# 照片转pdf
# image_path: 图片绝对路径
# pdf_path: pdf路径
def pic_convert(image_path, pdf_path):
# 提取文件的后缀名
file_suffix = os.path.splitext(image_path)[-1].lstrip(".").lower()
# 检测该文件格式是否受到支持
if file_suffix not in SUPPORT_SUFFIX:
return
# 将图片文件转换为PDF文件
with open(image_path, "rb") as source:
with open(pdf_path, "wb") as target:
target.write(pic_to_pdf(source.read()))
def pic_convert2(image_path, pdf_path):
imagePaths = []
for root, dirs, files in os.walk(image_path, topdown=False):
if (root.__contains__("ch/ch102")): break
for name in files:
# 提取文件的后缀名
file_suffix = os.path.splitext(name)[-1].lstrip(".").lower()
# 检测该文件格式是否受到支持
if file_suffix not in SUPPORT_SUFFIX:
continue
# 拼接出图片文件的绝对路径
source_file_path = os.path.join(root, name)
with open(source_file_path, "rb") as source:
try:
pic_to_pdf(source.read())
imagePaths.append(source_file_path)
except Exception as e:
# 过滤掉坏图
print('error:', e)
finally:
print('---------------')
with open(pdf_path, "ab") as f:
f.write(img2pdf.convert(imagePaths))
f.close()
# 合并pdf
def mergePdf(i, pdf_list):
print(str(i), pdf_list[0], pdf_list[-1])
# 将所有 PDF 合并成一个文件
merger = PdfMerger()
for file_path in pdf_list:
print(file_path)
merger.append(str(file_path))
merger.write("ch/output%s.pdf" % i)
image_path = 'D:/study/dataset/val/daisy/cj.jpg'
image_path = 'ch/ch1_209/167689.jpg'
pdf_path = os.path.splitext(image_path)[0].lstrip(".") + ".pdf"
pic_convert(image_path, pdf_path)
img_dir = 'D:/study/python-scripts/p20231031/ch/'
# 绝对路径,相对路径没有影响,pic_to_pdf 只能转一张 img2pdf传多个路径可以转多张图
batch_convert(img_dir, 'ch/chAll.pdf') # 错误 无法生成全量图片的pdf,只有一张图片
pic_convert2(img_dir, 'ch/chAll2.pdf')
img_dir = 'ch/'
batch_convert(img_dir, 'ch/chAll_relativepath.pdf') # 错误 无法生成全量图片的pdf,只有一张图片
pic_convert2(img_dir, 'ch/chAll2_relativepath.pdf')
pdf_list = []
pdf_list.append(pdf_path)
pdf_list.append('ch/chAll.pdf')
pdf_list.append('ch/chAll2.pdf')
# pdf_list.append('ch/chAll_relativepath.pdf') # 而且pdf指针有问题 合并会报错
pdf_list.append('ch/chAll2_relativepath.pdf')
mergePdf('_all', pdf_list)