更改说明:
临时图像文件:将 Pixmap 对象保存到临时文件中,然后将该图像插入到页面。这可以避免直接处理 Pixmap 对象可能带来的问题。
import os
import tkinter as tk
from tkinter import filedialog, ttk, messagebox
import fitz # PyMuPDF
# 压缩PDF文件
def compress_pdf(input_file, output_file, compression_ratio, progress_callback):
# 打开 PDF 文件
doc = fitz.open(input_file)
num_pages = len(doc)
# 压缩过程
for i in range(num_pages):
page = doc.load_page(i) # 加载页面
# 计算新图像尺寸
scale = compression_ratio / 100.0
mat = fitz.Matrix(scale, scale)
pix = page.get_pixmap(matrix=mat) # 使用缩放比例渲染页面
# 清除当前页面内容
page.clean_contents()
# 使用缩放后的图像插入到页面
rect = fitz.Rect(0, 0, pix.width, pix.height)
# 将图像保存到临时文件
temp_image_path = "temp_image.png"
pix.save(temp_image_path)
# 插入临时图像到页面
page.insert_image(rect, filename=temp_image_path)
# 删除临时图像文件
os.remove(temp_image_path)
progress_callback(i + 1, num_pages)
# 保存压缩后的文件
doc.save(output_file, garbage=4, deflate=True)
doc.close()
# 选择文件
def select_file():
file_path = filedialog.askopenfilename(
filetypes=[("PDF files", "*.pdf")])
file_entry.delete(0, tk.END)
file_entry.insert(0, file_path)
# 更新进度条
def update_progress(current, total):
progress_var.set(current / total * 100)
root.update_idletasks()
# 开始压缩
def start_compression():
input_file = file_entry.get()
compression_ratio = ratio_entry.get()
if not input_file:
messagebox.showerror("Error", "Please select a PDF file")
return
if not compression_ratio.isdigit() or not (0 < int(compression_ratio) <= 100):
messagebox.showerror("Error", "Please enter a valid compression ratio (1-100)")
return
compression_ratio = int(compression_ratio)
output_file = os.path.join(os.path.dirname(input_file), "compressed.pdf")
try:
compress_pdf(input_file, output_file, compression_ratio, update_progress)
messagebox.showinfo("Success", f"File compressed and saved as {output_file}")
except Exception as e:
messagebox.showerror("Error", f"An error occurred: {e}")
# 主窗口
root = tk.Tk()
root.title("PDF Compressor")
root.geometry("400x250")
# 文件选择部分
file_frame = tk.Frame(root)
file_frame.pack(pady=10)
file_label = tk.Label(file_frame, text="Select PDF File:")
file_label.pack(side=tk.LEFT)
file_entry = tk.Entry(file_frame, width=30)
file_entry.pack(side=tk.LEFT, padx=5)
file_button = tk.Button(file_frame, text="Browse", command=select_file)
file_button.pack(side=tk.LEFT)
# 压缩比例输入框
ratio_frame = tk.Frame(root)
ratio_frame.pack(pady=10)
ratio_label = tk.Label(ratio_frame, text="Compression Ratio (%):")
ratio_label.pack(side=tk.LEFT)
ratio_entry = tk.Entry(ratio_frame, width=10)
ratio_entry.pack(side=tk.LEFT, padx=5)
# 进度条
progress_var = tk.DoubleVar()
progress_bar = ttk.Progressbar(root, variable=progress_var, maximum=100)
progress_bar.pack(pady=20, fill=tk.X, padx=20)
# 开始压缩按钮
start_button = tk.Button(root, text="Start Compression", command=start_compression)
start_button.pack(pady=10)
# 运行主循环
root.mainloop()