赞
踩
老大最近一直需要将一个好几兆的pdf文件压缩到2mb甚至1mb以内。通常的做法可能会是打印pdf文件,然后用打印机设置生产很小的pdf文件,或者就是截图保存等等。但都有点太傻瓜了,这时候还是python大法好,网上摘取了一部分别人的代码,稍作修改,就变成了一个能用的小工具。在此感谢各位大佬的资源。目前差不多能用,功能如下:
先安装库 fitz,再安装库pymupdf,地址:https://github.com/pymupdf/PyMuPDF/
pip install fitz
pip install pymupdf
第一个pdf2pic从pdf中提取jpg文件的部分引用了别人的代码
以下两行doc.引用的注意了,不然会报错
lenXREF = doc.xref_length()
text = doc.xref_object(i) # 定义对象字符串
另外加入了重新调整过大的照片尺寸,和保存照片的质量,这里有个变量comp_ratio
im = im.resize((1376, y_s), Image.ANTIALIAS)
im.save(pic_path_d, quality=comp_ratio)
import fitz import re import os from PIL import Image from tkinter import filedialog def pdf2pic(path, pic_path, comp_ratio): checkXO = r"/Type(?= */XObject)" # 使用正则表达式来查找图片 checkIM = r"/Subtype(?= */Image)" doc = fitz.open(path) # 打开pdf文件 imgcount = 0 # 图片计数 lenXREF = doc.xref_length() # 获取对象数量长度 # 打印PDF的信息 print("文件名:{}, 页数: {}, 对象: {}".format(path, len(doc), lenXREF - 1)) # 遍历每一个对象 for i in range(1, lenXREF): text = doc.xref_object(i) # 定义对象字符串 isXObject = re.search(checkXO, text) # 使用正则表达式查看是否是对象 isImage = re.search(checkIM, text) # 使用正则表达式查看是否是图片 if not isXObject or not isImage: # 如果不是对象也不是图片,则continue continue imgcount += 1 pix = fitz.Pixmap(doc, i) # 生成图像对象 new_name = "pic{}.jpg".format(imgcount) # 生成图片的名称 print(new_name) if pix.n < 5: # 如果pix.n<5,可以直接存为PNG pic_path_d = os.path.join(pic_path, new_name) pix.writeImage(os.path.join(pic_path, new_name)) im = Image.open(pic_path_d) x, y = im.size if x > 1376: y_s = int(y * 1376 / x) im = im.resize((1376, y_s), Image.ANTIALIAS) im.save(pic_path_d, quality=comp_ratio) else: # 否则先转换CMYK pix0 = fitz.Pixmap(fitz.csRGB, pix) pix0.writeImage(os.path.join(pic_path, new_name)) pix0 = None pix = None # 释放资源 print("提取了{}张图片".format(imgcount)) os.startfile(pic_path)
下面这个rea是用来将文件夹内的照片重新组合为pdf文件
def rea(path, pdf_name): file_list = os.listdir(path) pic_name = [] im_list = [] for x in file_list: if "jpg" in x or 'png' in x or 'jpeg' in x: pic_name.append(x) pic_name.sort() new_pic = [] for x in pic_name: if "jpg" in x: new_pic.append(x) for x in pic_name: if "png" in x: new_pic.append(x) print("hec", new_pic) im1 = Image.open(os.path.join(path, new_pic[0])) new_pic.pop(0) for i in new_pic: img = Image.open(os.path.join(path, i)) # im_list.append(Image.open(i)) if img.mode == "RGBA": img = img.convert('RGB') im_list.append(img) else: im_list.append(img) im1.save(pdf_name, "PDF", resolution=100.0, save_all=True, append_images=im_list) print("输出文件名称:", pdf_name) def pdf_out(): print('功能完善中')
主程序中随意加了一些判断,如压缩等级1、2、3等。
if __name__ == '__main__': print("Hello world!请先输入压缩等级1~3,然后在弹出的对话框中选择需要压缩的文件") comp_level = input("压缩等级(1=高画质,2=中画质,3=低画质):(输入数字并按回车键)") ratio = 10 if comp_level == "1": ratio = 20 elif comp_level == "2": ratio = 10 elif comp_level == "3": ratio = 5 '''打开选择文件夹对话框''' filepath = filedialog.askopenfilename() # 获得选择好的文件 print('选择的PDF地址:', filepath) if os.path.exists("./pdf_output"): pass else: os.mkdir("./pdf_output") pic_path = str(os.getcwd()) + "\pdf_output" print('提取图片的输出地址:', pic_path ) pdf2pic(filepath, pic_path, comp_ratio=ratio) pdf_name = 'Compressed.pdf' if ".pdf" in pdf_name: rea(pic_path, pdf_name=pdf_name) else: rea(pic_path, pdf_name="{}.pdf".format(pdf_name)) print("压缩完成,请关闭窗口。若压缩等级不合适,请先删除图片和文件并重新打开程序。")
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。