【実践】PDF無損圧縮:PyMuPDFに基づく構造最適化方案
【実践】PDF無損圧縮:PyMuPDFに基づく構造最適化方案
日常業務において、PDFファイルのサイズが大きすぎる問題にしばしば直面します:メールの添付ファイルのサイズ制限で送信できない、アップロードやダウンロードの速度が遅い、大量のストレージスペースを占有するなど。従来の圧縮方法は、画像の品質を低下させてぼやけさせるか、テキストを画像に変換して検索可能性を失わせるため、実際には得策ではありません。
今日は、無損PDF圧縮方案を共有します——PyMuPDF(fitz)ライブラリを基にPDF内部構造を最適化し、冗長データをクリーンアップすることで、ファイルサイズを効果的に小さくし、テキストの検索可能性と視覚的な明瞭さを完璧に保持します。
一、核心実装原理
まずは核心コードを紹介します。これはPDF構造最適化圧縮を実現するための重要なロジックです:
import os
from pathlib import Path
import fitz # PyMuPDF
def compress_pdf_simple(input_path, output_path=None):
"""
簡単PDF圧縮方法 - 構造最適化のみ(無損)
パラメータ:
input_path (str): 入力PDFファイルのパス
output_path (str): 出力PDFファイルのパス
戻り値:
str: 出力ファイルのパス
"""
try:
# PDFファイルを開く
doc = fitz.open(input_path)
# 出力パスをスマートに生成(指定がない場合)
if output_path is None:
input_file = Path(input_path)
output_path = str(input_file.parent / f"{input_file.stem}_simple_compressed{input_file.suffix}")
# 核心:パラメータの組み合わせを通じて無損圧縮を実現
doc.save(
output_path,
garbage=4, # 未使用のオブジェクトを最大限にクリーンアップ
deflate=True, # deflate無損圧縮アルゴリズムを使用
clean=True, # PDF内部構造をクリーンアップ/最適化
pretty=False # コンパクトな出力、空白文字を除去
)
# ドキュメントを閉じてリソースを解放
doc.close()
# 圧縮情報を計算
original_size = os.path.getsize(input_path)
compressed_size = os.path.getsize(output_path)
compression_ratio = (1 - compressed_size / original_size) * 100
# 圧縮結果を出力
print(f"✅ 簡単圧縮が完了しました!")
print(f"📄 元のファイル: {input_path} ({original_size / 1024 / 1024:.2f} MB)")
print(f"📦 圧縮ファイル: {output_path} ({compressed_size / 1024 / 1024:.2f} MB)")
print(f"📉 圧縮率: {compression_ratio:.1f}%")
print(f"🔍 テキストの検索可能性を保持: はい")
return output_path
except Exception as e:
print(f"❌ 圧縮中にエラーが発生しました: {str(e)}")
return None
# 呼び出し例
# compress_pdf_simple("あなたのファイル.pdf")
この方案の核心は、PyMuPDFのsave()メソッドの4つの重要なパラメータを利用し、組み合わせてPDFの「スリム化」を実現し、文書の内容自体を変更することなく行います。
二、重要パラメータの深堀り
2.1 garbage=4:孤立したオブジェクトの正確なクリーンアップ
PDFファイル内部には大量の間接オブジェクト(ページ、フォント、画像、注釈など)が存在し、文書を編集する際に内容を削除しても底層の参照が即座にクリーンアップされず、大量の「孤立オブジェクト」が蓄積されます。
| garbageパラメータ値 | クリーンアップの程度 | 適用シーン |
|---|---|---|
| 0 | クリーンアップしない | 迅速に保存するだけで、圧縮は不要 |
| 1 | 明らかに未使用のオブジェクトをクリーンアップ | 軽度の最適化、互換性を優先 |
| 2 | 参照関係を深くチェック | 一般的な最適化、効果と安全性のバランス |
| 3 | 積極的なクリーンアップ | シンプルなPDFファイルの最大圧縮 |
| 4 | 最大限のクリーンアップ | 複数回編集された文書、完全性を先に検証する必要あり |
作用フロー:すべての間接オブジェクトを遍歴 → 参照関係図を構築 → 参照のないオブジェクトを削除 → ストレージスペースを解放。 実際の効果:複数回編集された文書は10-30%のサイズ削減が可能です。
2.2 deflate=True:汎用無損圧縮アルゴリズム
deflateはPDF規格で推奨される無損圧縮アルゴリズム(LZ77+ハフマン符号化に基づく)で、互換性が高く、ほぼすべてのPDFリーダーがデコード可能です。
有効にすると、以下のオブジェクトが圧縮されます:
- ページ内容ストリーム
- フォントデータストリーム
- 他のアルゴリズムで圧縮されていない画像データストリーム
2.3 clean=True:文書構造の最適化
PDFは「文書構造」と「内容ストリーム」の2つの部分を含み、clean=Trueは構造部分を最適化します:
- 重複するPDFオブジェクトを削除
- 同じ内容のオブジェクト参照を統合
- ページツリー構造を最適化
- メタデータの冗長情報をクリーンアップ
実際の効果:複数ページの文書は5-15%のサイズ削減が可能です。
2.4 pretty=False:コンパクトな出力
PDFは本質的にバイナリ形式であり、pretty=Trueはインデントや改行などの空白文字を保持して可読性を向上させますが、pretty=Falseはすべての不要な空白文字を除去し、さらにサイズを小さくします(すでにdeflate圧縮されたファイルに対して補助的な効果がありますが、効果は薄いです)。
三、完全な圧縮プロセス

四、技術的な難点と解決策
4.1 圧縮率 vs 文書の完全性
課題:積極的なガーベジコレクション(garbage=4)は、複雑なPDF(スクリプト/フォームを含む)を損傷する可能性があります。 解決策:
- 圧縮前に文書の完全性を検証
- 暗号化されたPDFは、圧縮前に解読する必要があります
- try-exceptを使用して例外をキャッチし、プログラムのクラッシュを回避
4.2 テキストの検索可能性を保持
課題:一部の圧縮方案はテキストを画像に変換し、選択や検索ができなくなる可能性があります。 本方案の利点:
- テキストの内容とエンコーディングを変更しない
- オブジェクトの参照関係のみを最適化
- フォントオブジェクトの完全性を保持
- 検証方法:圧縮後にPDFリーダーでテキスト選択機能をテスト
4.3 大ファイルのメモリ管理
課題:数百MBのPDFはメモリオーバーフローを引き起こしやすいです。 最適化提案:
- 超大ファイルをページ単位で処理
- docオブジェクトを適時閉じてリソースを解放
- メモリ使用量を監視し、ストリーミング処理を採用
4.4 スマートな出力パスの生成
pathlibライブラリを利用して自動的にパスを生成し、元のファイル名+圧縮マークを保持し、クロスプラットフォームの互換性を確保します:
if output_path is None:
input_file = Path(input_path)
output_path = str(input_file.parent / f"{input_file.stem}_simple_compressed{input_file.suffix}")
五、使用シーンと効果の予測
5.1 適用シーン
- 学術文書:arXivからダウンロードしたPDFは通常、大量の冗長情報を含んでいます
- 電子書籍のアーカイブ:圧縮後にストレージスペースを節約
- 文書の転送:メール/クラウドストレージにアップロードする前の前処理
- バッチ処理:Celeryと組み合わせて自動化圧縮を実現
5.2 効果の予測
| 文書タイプ | 典型的な圧縮率 | 備考 |
|---|---|---|
| 純文書 | 10-25% | 効果が最も顕著 |
| 大量の画像を含む | 5-15% | 構造最適化のみ |
| 複数回編集された文書 | 20-40% | ガーベジコレクションの効果が顕著 |
| スキャンPDF | 0-5% | すでに画像形式であり、最適化は限られています |
5.3 注意事項
- 元のファイルのバックアップ:圧縮は不可逆です
- 内容の完全性を検証:圧縮後に全面的にチェック
- 印刷効果をテスト:出力に影響を与えないように
- 大量処理には分散アーキテクチャを推奨
六、同類方案の比較
| 圧縮方案 | 圧縮率 | 品質損失 | テキストの検索可能性 | 実装の複雑さ |
|---|---|---|---|---|
| PyMuPDF構造最適化 | 10-30% | なし | 保持 | 低 |
| 画像の質を下げる圧縮 | 30-70% | 明らか | 保持 | 中 |
| PDFの再エンコード | 20-50% | 損失の可能性 | 失う可能性あり | 高 |
七、性能最適化の提案
- バッチ処理:マルチプロセスで複数のファイルを同時に処理し、効率を向上させる
- 進捗監視:進捗コールバック関数を追加し、ユーザー体験を向上させる
- 増分圧縮:PDF内の変更されたページのみを圧縮し、重複操作を減らす
- キャッシュメカニズム:圧縮済みファイルを記録し、重複処理を避ける
八、まとめ
重要ポイントの振り返り
- 本方案はPyMuPDFの
garbage=4、deflate=True、clean=True、pretty=Falseの4つの核心パラメータに基づき、PDFの無損圧縮を実現します; - 方案の利点は文書の品質を損なわず、テキストの検索可能性を保持し、実装が簡単で互換性が良いことです;
- 異なるタイプのPDFの圧縮効果には大きな差があり、スキャンされた文書の最適化は限られていますが、複数回編集された純文書の効果が最も良好です。
このPDF無損圧縮方案は実用性と安全性を兼ね備え、コードはシンプルで統合が容易であり、ほとんどの文書処理シーンに適しています。より高い圧縮率が必要な場合は、画像の無損圧縮(DPIの最適化など)と組み合わせることもできますが、効果と複雑さのバランスに注意が必要です。
