Python × ChatGPTでPDFと画像を一括結合!GUIツールの作り方【Tkinter + PyMuPDF】
「複数のPDFや画像をまとめて1つのファイルにしたい」──そう思ったことはありませんか?
市販ソフトでも可能ですが、無料で使えるPythonを活用すれば、用途にぴったりのツールを自作できます。
この記事では、ChatGPTでコードを生成・改良しながら、PDF+画像をまとめて結合できるGUIツールを作った手順を紹介します。
- 画像(PNG/JPG等)+PDFを混在して1つのPDFへ結合
- ドラッグ&ドロップで追加 → 順番を入れ替えて変換
- 配布用にEXE化(PyInstaller)も可能
実際に私もブログ記事や業務資料の整理で使っており、ドラッグ&ドロップで結合できるので作業効率がかなり上がりました。
必要なライブラリ
- Tkinter(標準ライブラリ:GUI構築)
- Pillow(画像処理用)
- PyMuPDF(PDF操作用:
fitzとして利用) - os(ファイル操作)
- tkinterdnd2(ドラッグ&ドロップ対応)
💡 補足:以下で一括インストールできます。
pip install pillow pymupdf tkinterdnd2
TkinterはPython標準に含まれているため、追加インストールは不要です。
PyMuPDFはPDFと画像を統合的に扱える高速ライブラリで、結合系の用途でも安定しやすいのが強みです。
完成イメージ(できること)
- 画像/PDFをリストに追加(ドラッグ&ドロップ対応)
- ↑↓で順番を変更
- 「PDFに変換」で一括結合して1つのPDFを出力
Pythonコード(完成版)
以下が完成版のコードです。ChatGPTで生成→改良しながら、実用レベルのGUIアプリとして仕上げました。
※重要:元コードにあった os.path.splitext(path)[1] の「1」が全角だとエラーになるので、[1](半角)に直しています。
import tkinter as tk
from tkinter import filedialog, messagebox
from PIL import Image
import os
import fitz # PyMuPDF
import tempfile
from tkinterdnd2 import DND_FILES, TkinterDnD
def select_files():
file_paths = filedialog.askopenfilenames(
title="画像またはPDFファイルを選択",
filetypes=[("Image or PDF Files", "*.png *.jpg *.jpeg *.bmp *.tiff *.pdf")]
)
for path in file_paths:
file_list.insert(tk.END, path)
def select_output_path():
output_path = filedialog.asksaveasfilename(
defaultextension=".pdf",
filetypes=[("PDF files", "*.pdf")],
title="保存先を選択"
)
output_entry.delete(0, tk.END)
output_entry.insert(0, output_path)
def convert_to_pdf():
file_paths = file_list.get(0, tk.END)
output_path = output_entry.get()
if not file_paths:
messagebox.showerror("エラー", "ファイルを選択してください。")
return
if not output_path:
messagebox.showerror("エラー", "保存先を指定してください。")
return
try:
doc = fitz.open()
for path in file_paths:
ext = os.path.splitext(path)[1].lower()
if ext in [".png", ".jpg", ".jpeg", ".bmp", ".tiff"]:
img = Image.open(path)
if img.mode != "RGB":
img = img.convert("RGB")
# tempファイル名の衝突を避ける
with tempfile.NamedTemporaryFile(suffix=".pdf", delete=False) as tmp:
temp_path = tmp.name
img.save(temp_path)
temp_pdf = fitz.open(temp_path)
doc.insert_pdf(temp_pdf)
temp_pdf.close()
os.remove(temp_path)
elif ext == ".pdf":
pdf = fitz.open(path)
doc.insert_pdf(pdf)
pdf.close()
doc.save(output_path)
doc.close()
messagebox.showinfo("成功", f"PDFファイルが保存されました:\n{output_path}")
except Exception as e:
messagebox.showerror("変換エラー", str(e))
def drop(event):
files = root.tk.splitlist(event.data)
for file in files:
if os.path.isfile(file) and file.lower().endswith((".png", ".jpg", ".jpeg", ".bmp", ".tiff", ".pdf")):
file_list.insert(tk.END, file)
def move_up():
selected = file_list.curselection()
if not selected or selected[0] == 0:
return
index = selected[0]
item = file_list.get(index)
file_list.delete(index)
file_list.insert(index - 1, item)
file_list.select_set(index - 1)
def move_down():
selected = file_list.curselection()
if not selected or selected[0] == file_list.size() - 1:
return
index = selected[0]
item = file_list.get(index)
file_list.delete(index)
file_list.insert(index + 1, item)
file_list.select_set(index + 1)
def delete_selected():
selected = file_list.curselection()
for index in reversed(selected):
file_list.delete(index)
# GUI構築
root = TkinterDnD.Tk()
root.title("PDF一括変換ツール(画像+PDF結合対応)")
root.geometry("540x550")
tk.Button(root, text="ファイルを選択(画像またはPDF)", command=select_files).pack(pady=5)
file_list = tk.Listbox(root, width=60, height=10, selectmode=tk.EXTENDED)
file_list.pack(pady=10)
file_list.drop_target_register(DND_FILES)
file_list.dnd_bind("<<Drop>>", drop)
order_frame = tk.Frame(root)
order_frame.pack(pady=5)
tk.Button(order_frame, text="↑ 上へ", command=move_up, width=10).pack(side=tk.LEFT, padx=5)
tk.Button(order_frame, text="↓ 下へ", command=move_down, width=10).pack(side=tk.LEFT, padx=5)
tk.Button(order_frame, text="削除", command=delete_selected, width=10).pack(side=tk.LEFT, padx=5)
tk.Button(root, text="保存先を選択", command=select_output_path).pack(pady=5)
output_entry = tk.Entry(root, width=60)
output_entry.pack(pady=5)
tk.Button(root, text="PDFに変換", command=convert_to_pdf, bg="lightblue").pack(pady=20)
root.mainloop()
GUIイメージ
ツール起動直後の画面ファイルリストに画像やPDFをドラッグ&ドロップで追加し、順序を並べ替えてから「PDFに変換」ボタンを押すだけで、複数ファイルを1つのPDFにまとめられます。
機能とこだわりポイント
- 複数のPDF・画像をまとめて一括結合
- ドラッグ&ドロップ対応で直感的にファイル追加
- ファイル順の入れ替え(↑↓)
- 選択ファイルの削除
👉 今後の改良予定として、以下の機能も検討しています。
- PDFの分解(ページごとの抽出)
- 画像サイズ・向きの自動調整
- 大量ファイル対応のバッチ処理
- 圧縮(容量を小さくして共有しやすく)
“一歩先の実用化”は手間が増えます。
その場合は 仕様だけ渡して丸投げ が一番早いです。
- 大量ファイルでも落ちないよう最適化
- 圧縮・ページ番号・余白・サイズ統一などの追加仕様
- 社内配布用(EXE化 / アイコン / 画面整備)
①入力例(PDF/画像) ②出力イメージ ③結合順ルール ④動作環境(Win/Mac) ⑤納期
EXEファイル化でさらに便利に
Pythonスクリプトを毎回実行するのが面倒な方には、PyInstallerを使ったEXE化がおすすめです。
pyinstaller your_script.py --onefile
EXE化すると、タスクバーに固定したり、他人に配布したりすることも可能になります。
詳しい手順は以下の記事で解説しています。
Pythonを.exeに変換する方法|PyInstallerで配布用実行ファイルを作成する手順
補足情報(詰まりやすいポイント)
- 環境依存:Windowsは動きやすい一方、Mac/LinuxはD&D周りで追加設定が必要な場合があります。
- 処理速度:高解像度画像が多いと時間がかかるため、将来的に圧縮機能を入れると便利です。
- 代替ライブラリ:PyPDF2でも結合は可能ですが、画像混在や実用化の観点ではPyMuPDFが扱いやすいです。
既存ソフト・オンラインサービスとの比較
PDF編集といえば「Adobe Acrobat」などの市販ソフトや、Smallpdfなどのオンラインサービスが有名です。便利ですが、以下の制約があります。
- 市販ソフト:有料ライセンスが必要(サブスク費用が高め)
- オンライン:アップロード容量や回数に制限がある
- セキュリティ:機密ファイルをアップロードするリスク
一方、Python自作ツールは以下が強みです。
- 完全無料:Python環境があれば利用可能
- カスタマイズ自由:結合順序・追加機能を自分好みに拡張
- オフライン完結:ファイルを外部に送らないので安心
- 待ち時間が少ない:アップロード不要でローカル即処理
※処理時間の実測値は環境や画像解像度で変わるため、目安として捉えてください。
まとめ
今回はPythonとChatGPTを活用して、PDFと画像を一括で結合できるGUIツールを作成しました。
市販ソフトの代わりに自作ツールを使うことで、コストをかけずに業務効率を改善できます。
特に今回の開発では、ChatGPTを「プログラミングの相棒」として活用し、エラー修正や機能追加を会話ベースで進められました。
次の一手:改良して「実務で使える形」に寄せたいなら、
・圧縮(容量削減)
・画像の向き/サイズ自動補正
・EXE化&配布用UI調整
このあたりが伸びしろです。

