Python编写的小工具-PDF拼接高清图片

来源:https://www.52pojie.cn/thread-2108169-1-1.html本人从事制药行业法规事务工作,业余时间运营着一个公众号,经常需要把国家药品监督管理局发布的PDF版法规转成图片通过公众号进行分享。直接使用Windows的截图工具,或者Adobe Acrobat Pro(专业版)虽然都可以成功转换,但是清晰度都不尽如人意,也无法自行指定导出的清晰度,也无法实现自行定义…

6效率工具52pojie吾爱破解

来源:https://www.52pojie.cn/thread-2108169-1-1.html

本人从事制药行业法规事务工作,业余时间运营着一个公众号,经常需要把国家药品监督管理局发布的PDF版法规转成图片通过公众号进行分享。直接使用Windows的截图工具,或者Adobe Acrobat Pro(专业版)虽然都可以成功转换,但是清晰度都不尽如人意,也无法自行指定导出的清晰度,也无法实现自行定义的拼接效果。今天用Python编写了一个小工具,可以指定清晰度(300dpi即可导出高清图片),图片接拼方式(如3行2列),欢迎大家下载试用:

通过百度网盘分享的文件:202605 PDF拼接高清图片
链接: https://pan.baidu.com/s/1SQxZJVahqP3sOaiGt0i-9A 提取码: 52pj

同时把源代码分享如下,请吾爱的大神们多多指点:
[Python] 纯文本查看 复制代码
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import fitz
from PIL import Image
import os
import threading
import math


def convert_pdf_thread():
    threading.Thread(target=convert_pdf, daemon=True).start()


def convert_pdf():
    pdf_path = pdf_entry.get()
    if not pdf_path:
        messagebox.showwarning("提示", "请选择 PDF 文件")
        return

    try:
        rows = int(row_var.get())
        cols = int(col_var.get())
        dpi = int(dpi_var.get())
    except ValueError:
        messagebox.showerror("错误", "请输入有效数字")
        return

    if rows <= 0 or cols <= 0:
        messagebox.showerror("错误", "行数和列数必须大于 0")
        return

    output_dir = filedialog.askdirectory(title="选择图片保存目录")
    if not output_dir:
        return

    doc = fitz.open(pdf_path)
    total_pages = len(doc)

    # 进度窗口
    progress_win = tk.Toplevel(root)
    progress_win.title("正在处理")
    progress_win.geometry("360x120")
    progress_win.resizable(False, False)

    tk.Label(progress_win, text="正在转换 PDF 页面...").pack(pady=10)

    progress_bar = ttk.Progressbar(
        progress_win, length=300, mode="determinate", maximum=total_pages
    )
    progress_bar.pack(pady=5)

    progress_label = tk.Label(progress_win, text="0 / {}".format(total_pages))
    progress_label.pack()

    zoom = dpi / 72
    mat = fitz.Matrix(zoom, zoom)

    images = []
    for i in range(total_pages):
        page = doc.load_page(i)
        pix = page.get_pixmap(matrix=mat)
        img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
        images.append(img)

        progress_bar["value"] = i + 1
        progress_label.config(text=f"{i + 1} / {total_pages}")
        progress_win.update_idletasks()

    doc.close()

    # 网格拼接
    pages_per_image = rows * cols
    output_images = []

    for i in range(0, len(images), pages_per_image):
        chunk = images[i:i + pages_per_image]

        while len(chunk) < pages_per_image:
            chunk.append(Image.new("RGB", chunk[0].size, (255, 255, 255)))

        widths, heights = zip(*(img.size for img in chunk))

        cell_width = max(widths)
        cell_height = max(heights)

        big_width = cell_width * cols
        big_height = cell_height * rows

        new_img = Image.new("RGB", (big_width, big_height), (255, 255, 255))

        for idx, img in enumerate(chunk):
            r = idx // cols
            c = idx % cols
            new_img.paste(img, (c * cell_width, r * cell_height))

        output_images.append(new_img)

    # 保存
    base_name = os.path.splitext(os.path.basename(pdf_path))[0]
    for idx, img in enumerate(output_images, start=1):
        out_path = os.path.join(output_dir, f"{base_name}_{idx}.png")
        img.save(out_path, "PNG")

    progress_win.destroy()
    messagebox.showinfo("完成", f"成功导出 {len(output_images)} 张图片")


# ===== GUI =====
root = tk.Tk()
root.title("PDF 转拼接图片工具 by xhlbudd@52pojie")
root.geometry("440x320")

# PDF
tk.Label(root, text="PDF 文件:").pack(anchor="w", padx=10, pady=(10, 0))
pdf_entry = tk.Entry(root, width=52)
pdf_entry.pack(padx=10)

tk.Button(
    root,
    text="浏览",
    command=lambda: pdf_entry.insert(
        0, filedialog.askopenfilename(filetypes=[("PDF Files", "*.pdf")])
    ),
).pack(pady=5)

# 拼接布局
frame_layout = tk.Frame(root)
frame_layout.pack(pady=10)

tk.Label(frame_layout, text="拼接布局(行 × 列):").grid(row=0, column=0, padx=5)

row_var = tk.StringVar(value="3")
col_var = tk.StringVar(value="1")

tk.Entry(frame_layout, textvariable=row_var, width=5).grid(row=0, column=1)
tk.Label(frame_layout, text="×").grid(row=0, column=2)
tk.Entry(frame_layout, textvariable=col_var, width=5).grid(row=0, column=3)

# DPI
tk.Label(root, text="导出清晰度(DPI):").pack(anchor="w", padx=10)
dpi_var = tk.StringVar(value="300")
tk.Entry(root, textvariable=dpi_var, width=10).pack(anchor="w", padx=10)

# 开始按钮
tk.Button(
    root,
    text="开始转换",
    bg="#4CAF50",
    fg="white",
    height=2,
    command=convert_pdf_thread,
).pack(pady=15)

root.mainloop()

下载地址