|
刚好前几天我也有这样的需求,用py支持库调用py解决。
- import os
- import re
- import sys
- import traceback
- from datetime import datetime
- import tkinter as tk
- from tkinter import filedialog, messagebox
- from PIL import Image, ImageOps
- IMAGE_EXTS = {".jpg", ".jpeg", ".png", ".bmp", ".webp", ".tif", ".tiff"}
- # --------------------------
- def is_image_file(path: str) -> bool:
- ext = os.path.splitext(path)[1].lower()
- return ext in IMAGE_EXTS
- def natural_key(s: str):
- return [int(t) if t.isdigit() else t for t in re.split(r'(\d+)', s.lower())]
- def load_image_as_rgb(path: str) -> Image.Image:
- im = Image.open(path)
- try:
- im = ImageOps.exif_transpose(im) # 遵循相机 EXIF 方向
- if im.mode in ("RGBA", "LA"):
- # 透明通道:铺白底
- bg = Image.new("RGB", im.size, (255, 255, 255))
- bg.paste(im, mask=im.split()[-1])
- im = bg
- elif im.mode != "RGB":
- im = im.convert("RGB")
- # 拷贝以便尽快关闭原文件句柄
- out = im.copy()
- finally:
- im.close()
- return out
- def merge_images_to_pdf(img_paths, output_pdf: str):
- if not img_paths:
- raise RuntimeError("未找到可用图片。")
- images = []
- first_image = None
- for i, p in enumerate(img_paths):
- rgb_img = load_image_as_rgb(p)
- if i == 0:
- first_image = rgb_img
- else:
- images.append(rgb_img)
- # 导出 PDF
- first_image.save(
- output_pdf,
- "PDF",
- resolution=100.0,
- save_all=True,
- append_images=images,
- )
- # 显式关闭(释放内存)
- first_image.close()
- for im in images:
- im.close()
- def choose_dir_and_run():
- root = tk.Tk()
- root.withdraw() # 隐藏主窗口,只弹出选择框
- folder = filedialog.askdirectory(title="选择包含图片的文件夹")
- if not folder:
- # 用户取消
- return
- try:
- # 收集图片
- all_files = [os.path.join(folder, f) for f in os.listdir(folder)]
- img_files = [p for p in all_files if os.path.isfile(p) and is_image_file(p)]
- img_files.sort(key=lambda p: natural_key(os.path.basename(p)))
- if not img_files:
- messagebox.showwarning("提示", "该文件夹下未找到可用的图片文件。")
- return
- # 输出路径
- ts = datetime.now().strftime("%Y%m%d_%H%M%S")
- out_pdf = os.path.join(folder, f"合并输出_{ts}.pdf")
- # 合并
- merge_images_to_pdf(img_files, out_pdf)
- messagebox.showinfo("完成", f"合并完成!\n共 {len(img_files)} 张图片\n已保存:\n{out_pdf}")
- except Exception as e:
- traceback.print_exc()
- messagebox.showerror("错误", f"合并失败:{e}")
- if __name__ == "__main__":
- choose_dir_and_run()
复制代码 |
|