最近工作的时候一直有PDF转图片和分割、图片转PDF的需求,用adobe和wps把图片转成pdf时图片会变糊,于是摸鱼的时候做了两个小工具。
为了方便使用,没有做gui,只能拖入文件到程序上或者命令行使用
基本上抄的pymupdf官方的用法,没有做任何报错的处理,用来合并电子发票的PDF时会报错,这种情况我一般用另一个工具都转成图片后再用图片合并PDF解决,所以懒得改了
1.图片和PDF相互转换
把文件/文件夹拖到程序上,如果拖入的是图片则合并成1个PDF,如果是PDF则导出为图片,如果既有图片又有PDF则不做处理
2.PDF合并和切割
把文件/文件夹拖到程序上,如果拖入的是单个PDF则切割,如果是多个PDF则合并
下载地址:
https://wwz.lanzout.com/b01g9e7yh
密码:1234
源码地址:
https://521github.com/PPJUST/simple-tools/blob/main/PDF%26%E5%9B%BE%E7%89%87%E4%BA%92%E8%BD%AC.py
https://521github.com/PPJUST/simple-tools/blob/main/PDF%E6%8B%86%E5%88%86%26%E5%90%88%E5%B9%B6.py
1.
[Python] 纯文本查看 复制代码 """
更新日期:
2024.03.27
功能:
PDF导出为图片,图片合并为一个PDF
"""
import os
import sys
import tkinter.messagebox
import filetype
import fitz
try:
drop_paths = sys.argv[1:]
except IndexError:
drop_paths = []
def pdf_to_image(pdf_path: str):
"""将pdf每页导出为图片"""
doc = fitz.open(pdf_path)
# 根据页数分别处理,如果是单页则直接导出图片,如果为多页则导出到一个文件夹中
pages_count = doc.page_count
filetitle = os.path.basename(os.path.splitext(pdf_path)[0])
dirpath = os.path.dirname(pdf_path)
if pages_count == 1:
pix = doc[0].get_pixmap(dpi=300)
# 使用官方的pix.save方法保存图片
pix.save(f'{dirpath}/{filetitle}.png')
# 使用PIL库保存图片
# image = Image.frombytes("RGB", (pix.width, pix.height), pix.samples)
# image.save(f'{dirpath}/{filetitle}.png')
elif pages_count > 1:
os.mkdir(f'{dirpath}/{filetitle}')
for index, page in enumerate(doc, start=1):
pix = page.get_pixmap(dpi=300)
# 使用官方的pix.save方法保存图片
pix.save(f'{dirpath}/{filetitle}/{index}.png')
# 使用PIL库保存图片
# image = Image.frombytes("RGB", (pix.width, pix.height), pix.samples)
# image.save(f'{dirpath}/{filetitle}/{index}.png')
def image_to_pdf(images: list, output: str = 'output.pdf'):
"""将图片合并为pdf"""
merged_pdf = fitz.open() # 最终合并的PDF
for image_file in images:
# 读取图片,转为PDF流
img = fitz.open(image_file)
# rect = img[0].rect # 读取图片尺寸
pdf_bytes = img.convert_to_pdf()
img.close()
# 读取PDF流,转为PDF对象
img_page = fitz.open("pdf", pdf_bytes)
# 插入
merged_pdf.insert_pdf(img_page)
dirpath = os.path.dirname(images[0])
merged_pdf.save(f'{dirpath}/{output}')
merged_pdf.close()
def is_image(file: str):
"""文件是否是图片"""
return filetype.is_image(file)
def is_pdf(file: str):
"""文件是否是pdf"""
kind = filetype.guess(file)
if kind is None:
return False
guess_type = kind.extension
if guess_type == 'pdf':
return True
else:
return False
def get_files(folder: str):
"""获取文件夹下所有文件路径"""
files = []
for dirpath, dirnames, filenames in os.walk(folder):
for j in filenames:
filepath_join = os.path.normpath(os.path.join(dirpath, j))
files.append(filepath_join)
return files
def show_info():
tkinter.Tk().withdraw()
tkinter.messagebox.showinfo(title='使用说明',
message='直接将文件/文件夹拖到程序上使用。\n拖入图片:合并为1个PDF\n拖入PDF:导出每页为图片')
def main():
# 收集全部文件
files = []
for path in drop_paths:
if os.path.isfile(path):
files.append(path)
else:
walks = get_files(path)
files += walks
# 按文件类型分类
images = [i for i in files if is_image(i)]
pdfs = [i for i in files if is_pdf(i)]
# 如果同时存在图片和pdf,则不做处理直接退出
if images and pdfs:
return
if images: # 图片转pdf
image_to_pdf(images)
elif pdfs: # pdf导出图片
for pdf in pdfs:
pdf_to_image(pdf)
if __name__ == '__main__':
if drop_paths:
main()
else:
show_info()
2.
[Python] 纯文本查看 复制代码 import os
import sys
import tkinter.messagebox
import filetype
import fitz
try:
drop_paths = sys.argv[1:]
except IndexError:
drop_paths = []
def merge_pdfs(pdfs_path: list, output: str = 'output.pdf'):
"""合并多个PDF"""
merged_pdf = fitz.open() # 最终合并的PDF
for child_pdf in pdfs_path:
pdf = fitz.open(child_pdf)
for page_num in range(pdf.page_count):
merged_pdf.insert_pdf(pdf, from_page=page_num, to_page=page_num, start_at=merged_pdf.page_count)
pdf.close()
dirpath = os.path.dirname(pdfs_path[0])
merged_pdf.save(f'{dirpath}/{output}')
merged_pdf.close()
def split_pdf(pdf_path: str):
"""拆分PDF的每页为单独的PDF"""
source_pdf = fitz.open(pdf_path)
page_count = source_pdf.page_count
if page_count == 1:
return
elif page_count > 1:
filetitle = os.path.basename(os.path.splitext(pdf_path)[0])
dirpath = os.path.dirname(pdf_path)
os.mkdir(f'{dirpath}/{filetitle}')
for page_num in range(source_pdf.page_count):
single_pdf = fitz.open()
single_pdf.insert_pdf(source_pdf, from_page=page_num, to_page=page_num)
single_pdf.save(f'{dirpath}/{filetitle}/{page_num + 1}.pdf')
single_pdf.close()
source_pdf.close()
def get_files(folder: str):
"""获取文件夹下所有文件路径"""
files = []
for dirpath, dirnames, filenames in os.walk(folder):
for j in filenames:
filepath_join = os.path.normpath(os.path.join(dirpath, j))
files.append(filepath_join)
return files
def is_pdf(file: str):
"""文件是否是pdf"""
kind = filetype.guess(file)
if kind is None:
return False
guess_type = kind.extension
if guess_type == 'pdf':
return True
else:
return False
def show_info():
tkinter.Tk().withdraw()
tkinter.messagebox.showinfo(title='使用说明',
message='直接将文件/文件夹拖到程序上使用。\n拖入多个PDF:合并为1个PDF\n拖入单个PDF:拆分每页为单独的PDF')
def main():
# 收集全部文件
files = []
for path in drop_paths:
if os.path.isfile(path):
files.append(path)
else:
walks = get_files(path)
files += walks
# 按文件类型分类
pdfs = [i for i in files if is_pdf(i)]
if len(pdfs) == 1: # 拆分PDF
split_pdf(pdfs[0])
elif len(pdfs) > 1: # 合并PDF
merge_pdfs(pdfs)
if __name__ == '__main__':
if drop_paths:
main()
else:
show_info() |