【2025年版】PyMuPDF実践:PDFからの画像抽出、変換、そして編集テクニック

はじめに:PDFのビジュアルコンテンツを自在に操る

PDFドキュメントは、ビジネスシーンや学術分野で広く利用されています。しかし、その中から特定の画像だけを抜き出したい、PDFのページ全体を画像として扱いたい、あるいはちょっとした修正を加えたい、といったニーズに直面することは少なくありません。手作業での対応は時間がかかり、非効率的です。

「Python PDFライブラリ徹底活用ガイド」シリーズ第9弾となる本記事では、高速PDF処理ライブラリPyMuPDFを使い、PDFドキュメント内のビジュアルコンテンツを自在に操る実践的なテクニックを深掘りします。画像抽出からページ変換、さらには簡単な編集操作まで、具体的なコード例を交えながら解説することで、あなたのPDF自動化スキルを次のレベルへと引き上げます。

この記事を読み終える頃には、あなたはPyMuPDFを使ってPDFの画像コンテンツを効率的に管理・活用できるようになり、日々の業務におけるPDF処理の自動化を加速させる自信を手にしているでしょう。


対象読者

  • PDFドキュメントから画像を効率的に抽出したい開発者
  • PDFページを画像ファイルとして変換・利用したいエンジニア
  • PyMuPDFを使ったPDFの簡単な編集操作に興味がある方
  • PythonでPDF処理の自動化を進めたい中級者レベルのエンジニア

動作検証環境

この記事で紹介するPythonを使ったPDF動作は、以下の環境で検証しています。

  • OS : macOS Tahoe Version 26.0
  • ハードウェア : MacBook Air 2024 M3 24GB
  • uv : 0.8.22 (ade2bdbd2 2025-09-23)
  • python : 3.13.7
  • PyMuPDF : 1.26.4
    • pymupdf-stubs : 1.26.1.post1

目次

  1. PDFからの画像抽出
    • ページ内の画像オブジェクトの特定
    • 画像をファイルとして保存
    • 実践例:PDF資料からの画像アセット収集
  2. PDFページの画像変換
    • PDFページをPNG, JPEGなどの画像形式に変換
    • 解像度と品質の制御
  3. PDFの簡単な編集操作
    • テキストや図形の追加(既存コンテンツの上書き)
    • ページのトリミングとリサイズ
  4. まとめ:PyMuPDFでPDFのビジュアルコンテンツを操る
  5. FAQ
    • Q1: 抽出した画像の品質が悪いのですが、改善できますか?
    • Q2: PDFの編集は既存のコンテンツを完全に削除できますか?
    • Q3: 大量のPDFから画像を抽出する際の注意点は?
  6. 参考資料
  7. 免責事項

1. PDFからの画像抽出

PDFドキュメントには、テキストだけでなく様々な画像が埋め込まれています。プレゼンテーション資料からロゴを抜き出したり、報告書内のグラフ画像を再利用したりする際に、PyMuPDFの画像抽出機能が非常に役立ちます。


ページ内の画像オブジェクトの特定

PyMuPDFでは、page.get_images() メソッドを使って、ページ内に埋め込まれている画像オブジェクトの情報を取得できます。このメソッドは、各画像に関する詳細な情報(参照番号、マスク情報、幅、高さ、ビット深度、フィルター、カラースペース、ファイル名、拡張子、ストリーム)を含むタプルのリストを返します。

import pymupdf


doc = pymupdf.open("image_report.pdf")
page = doc[0]  # 最初のページを取得

# ページ内の画像情報を取得
image_list = page.get_images(full=True)

print(f"ページ内の画像数: {len(image_list)}")
for i, img in enumerate(image_list):
    xref = img[0]  # 画像の参照番号
    smask = img[1]  # ソフトマスクの参照番号 (透過情報など)
    width = img[2]
    height = img[3]
    bpc = img[4]  # ビット/コンポーネント
    colorspace = img[5]
    ext = img[7]  # 拡張子 (例: "jpeg", "png")

    print(f"--- 画像 {i + 1} ---")
    print(f"  XREF: {xref}")
    print(f"  サイズ: {width}x{height}")
    print(f"  拡張子: {ext}")

doc.close()

画像をファイルとして保存

doc.extract_image(xref) メソッドを使用すると、指定した参照番号(xref)の画像データを抽出できます。このメソッドは、画像データとメタデータを含む辞書を返します。

import pymupdf
import os
from pymupdf import Document

doc: Document = pymupdf.open("image_report.pdf")

output_dir = "extracted_images"
os.makedirs(output_dir, exist_ok=True)

# 各ページをループして画像を抽出
for page_num in range(len(doc)):
    page = doc.load_page(page_num)
    image_list = page.get_images(full=True)

    if not image_list:
        print(f"ページ {page_num + 1} に画像は見つかりませんでした。")
        continue

    print(f"ページ {page_num + 1}{len(image_list)} 個の画像が見つかりました。")

    for i, img in enumerate(image_list):
        xref = img[0]

        # 画像データを抽出
        try:
            base_image = doc.extract_image(xref)
            image_bytes = base_image["image"]
            image_ext = base_image["ext"]

            # ファイルとして保存
            image_filename = os.path.join(
                output_dir, f"image_{page_num + 1}_{i}.{image_ext}"
            )
            with open(image_filename, "wb") as f:
                f.write(image_bytes)
            print(f"画像を保存しました: {image_filename}")
        except Exception as e:
            print(f"画像 (xref: {xref}) の抽出中にエラーが発生しました: {e}")

doc.close()
[著者の経験談]: 以前、クライアントから受け取ったPDF形式のプレゼン資料から、ロゴやグラフの画像を個別に抽出してWebサイト用に最適化する必要がありました。手作業では途方もない時間がかかるところでしたが、PyMuPDFのこの機能を使って一括で抽出し、大幅な時間短縮と効率化を実現できました。

実践例:PDF資料からの画像アセット収集

特定のPDFドキュメントから、すべての画像を自動的に抽出し、指定したディレクトリに保存するスクリプトは、画像アセットの収集に非常に便利です。

import pymupdf
import os


def extract_all_images_from_pdf(pdf_path, output_folder):
    """
    PDFファイルからすべての画像を抽出し、指定されたフォルダに保存します。
    """
    doc = pymupdf.open(pdf_path)
    os.makedirs(output_folder, exist_ok=True)

    for i in range(len(doc)):
        page = doc[i]
        image_list = page.get_images(full=True)

        for img_index, img in enumerate(image_list):
            xref = img[0]
            base_image = doc.extract_image(xref)
            image_bytes = base_image["image"]
            image_ext = base_image["ext"]

            image_filename = os.path.join(
                output_folder, f"page{i + 1}_img{img_index + 1}_{xref}.{image_ext}"
            )
            with open(image_filename, "wb") as f:
                f.write(image_bytes)
            print(f"抽出・保存: {image_filename}")

    doc.close()
    print(f"'{pdf_path}' からすべての画像の抽出が完了しました。")


# 使用例
if __name__ == "__main__":
    # mymupdfディレクトリに存在するimage_report.pdfを対象とする
    pdf_to_extract = "image_report.pdf"
    output_directory = "extracted_images"

    if os.path.exists(pdf_to_extract):
        extract_all_images_from_pdf(pdf_to_extract, output_directory)
    else:
        print(f"サンプルPDFファイルが見つかりません: {pdf_to_extract}")
[!TIP]: 抽出した画像が重複している場合や、特定のサイズにリサイズしたい場合は、PythonのPillowライブラリなどと連携することで、さらに高度な画像処理を自動化できます。抽出後に画像のハッシュ値を計算して重複を排除したり、一括でリサイズ処理を行うことで、アセット管理を効率化できます。

2. PDFページの画像変換

PDFドキュメントの特定のページを、PNGやJPEGなどの画像ファイルとして保存したい場合も、PyMuPDFが強力なツールとなります。サムネイルの生成、Webサイトでのプレビュー表示、あるいは画像編集ソフトウェアでの加工など、様々な用途で活用できます。


PDFページをPNG, JPEGなどの画像形式に変換

page.get_pixmap() メソッドは、PDFページをピクセルマップ(画像データ)としてレンダリングします。このピクセルマップオブジェクトは、

import pymupdf
import os

# PDFドキュメントを開く
doc = pymupdf.open("image_report.pdf")
page = doc[0]  # 最初のページを取得

output_dir = "converted_images"
os.makedirs(output_dir, exist_ok=True)

# ページをPNG画像として保存
pix = page.get_pixmap()
png_filename = os.path.join(output_dir, "page1.png")
pix.save(png_filename)
print(f"ページをPNGとして保存しました: {png_filename}")

# ページをJPEG画像として保存 (品質指定も可能)
jpeg_filename = os.path.join(output_dir, "page1.jpeg")
pix.save(jpeg_filename, jpg_quality=90)  # 品質を90%に設定
print(f"ページをJPEGとして保存しました: {jpeg_filename}")

doc.close()

解像度と品質の制御

page.get_pixmap() メソッドには、レンダリング時の解像度を制御するための matrix パラメータがあります。これにより、高解像度の画像や、逆に軽量なサムネイル画像を生成することが可能です。

import pymupdf
import os

# PDFドキュメントを開く
doc = pymupdf.open("image_report.pdf")
page = doc[0]  # 最初のページを取得

output_dir = "converted_images_hires"
os.makedirs(output_dir, exist_ok=True)

# 高解像度でページをレンダリング (例: 2倍の解像度)
# fitz.Matrix(zoom_x, zoom_y) で拡大率を指定
zoom_matrix = pymupdf.Matrix(2, 2)
pix_hires = page.get_pixmap(matrix=zoom_matrix)

hires_filename = os.path.join(output_dir, "page1_hires.png")
pix_hires.save(hires_filename)
print(f"高解像度でページをPNGとして保存しました: {hires_filename}")

doc.close()
[!NOTE]: 大量のPDFページを高解像度で画像変換する場合、メモリ使用量が増大し、処理に時間がかかることがあります。システムのリソースと変換の目的に応じて、適切な解像度と品質を設定することが重要です。必要に応じて、ページごとに処理を行い、メモリを解放するなどの工夫も検討しましょう。

3. PDFの簡単な編集操作

PyMuPDFは、PDFの読み込みや変換だけでなく、既存のPDFにテキストや図形を追加したり、ページをトリミングしたりといった簡単な編集操作もサポートしています。これにより、既存のPDF資料に透かしを追加したり、不要な余白を削除したりする自動化が可能になります。


テキストや図形の追加(既存コンテンツの上書き)

PyMuPDFの編集機能は、既存のPDFコンテンツの上に新しい要素を描画する形で機能します。これにより、透かしの追加や、簡単な注釈の挿入などが可能です。

import pymupdf

# ファイルパスの定義
input_pdf = "image_report.pdf"
output_pdf = "sample_edited.pdf"

# PDFを開く
doc = pymupdf.open(input_pdf)

# 最初のページを取得
page = doc.load_page(0)

# ページに透かしテキストを挿入
page.insert_text(
    (50, 70),  # 挿入位置の座標 (左下の原点から)
    "CONFIDENTIAL",
    fontsize=50,
    rotate=0,  # rotateは0, 90, 180, 270のいずれかである必要があります
    color=(0.8, 0.8, 0.8),  # 薄いグレー (R, G, B)
    overlay=True,  # True: コンテンツの上に描画, False: 下に描画
)

# ページに四角形を描画
page.draw_rect(
    pymupdf.Rect(100, 100, 200, 150),  # 矩形の座標 (x0, y0, x1, y1)
    color=(1, 0, 0),  # 赤色 (R, G, B)
    width=2,  # 線の太さ
)

# 変更を新しいPDFとして保存
doc.save(output_pdf)
doc.close()

print(f"編集されたPDFを保存しました: {output_pdf}")
[著者の経験談]: 以前、急遽PDF資料に「社外秘」の透かしを入れる必要がありましたが、元の編集データが見つからず困っていました。PyMuPDFを使って、既存のPDFにプログラムで透かしテキストを挿入することで、迅速に対応できた経験があります。このような緊急時の対応にもPyMuPDFは非常に有効です。

ページのトリミングとリサイズ

PDFページの表示領域を調整するために、トリミングやリサイズを行うことができます。これは、不要な余白を削除したり、特定のコンテンツ領域だけを抽出したりする際に役立ちます。

import pymupdf

doc = pymupdf.open("image_report.pdf")
page = doc[0]  # 最初のページを取得

original_rect = page.rect
print(f"元のページサイズ: {original_rect}")

# ページをトリミング (例: 上下左右から50ポイントずつ削る)
# set_cropbox() は表示領域を定義する
page.set_cropbox(
    pymupdf.Rect(
        original_rect.x0 + 50,
        original_rect.y0 + 50,
        original_rect.x1 - 50,
        original_rect.y1 - 50,
    )
)

# 変更を新しいPDFとして保存
output_pdf_path = "sample_trimmed.pdf"
doc.save(output_pdf_path)
doc.close()
print(f"トリミングされたPDFを保存しました: {output_pdf_path}")
[!TIP]: 複数のPDFページに一括でトリミングを適用したい場合は、ループ処理を使って各ページに set_cropbox() を適用します。これにより、統一されたレイアウトのPDFドキュメントを効率的に作成できます。

まとめ:PyMuPDFでPDFのビジュアルコンテンツを操る

本記事では、PyMuPDFを使ったPDFドキュメントからの画像抽出、ページの画像変換、そして簡単な編集操作について、実践的なテクニックを解説しました。

  • 画像抽出: page.get_images()doc.extract_image() を使って、PDF内の画像を効率的に取得し、ファイルとして保存する方法を学びました。
  • 画像変換: page.get_pixmap()pix.save() を利用して、PDFページをPNGやJPEGなどの画像形式に変換し、解像度を制御する方法を理解しました。
  • 編集操作: page.insert_text()page.draw_rect()page.set_cropbox() を用いて、既存のPDFにテキストや図形を追加したり、ページをトリミングしたりする基本的な編集方法を習得しました。

これらの機能は、データ分析レポートの作成、プレゼンテーション資料の準備、ドキュメント管理、Webコンテンツの生成など、多岐にわたる業務であなたの生産性を飛躍的に向上させるでしょう。PyMuPDFは、PDFのビジュアルコンテンツを自在に操るための強力なツールです。

次回の記事では、PyMuPDFのさらに高度なレンダリング機能や注釈操作、そして他のPDFライブラリとの連携について深掘りします。

このPyMuPDFの活用術があなたのプロジェクトに役立ったら、ぜひチームに共有したり、X(旧Twitter)で感想をポストしてください!


FAQ

Q1: 抽出した画像の品質が悪いのですが、改善できますか?

A1: PDFから抽出される画像の品質は、元のPDFに埋め込まれている画像の品質に依存します。PyMuPDFは画像をそのまま抽出するため、元の画像が低解像度であれば、抽出後も低解像度になります。ただし、PDFページ全体を画像に変換する際には、page.get_pixmap(matrix=fitz.Matrix(zoom_x, zoom_y)) のように matrix パラメータでズームレベルを上げることで、より高解像度の画像を生成できます。

Q2: PDFの編集は既存のコンテンツを完全に削除できますか?

A2: PyMuPDFの基本的な編集機能は、既存のコンテンツの上に新しい要素を描画する「オーバーレイ」方式が主です。既存のテキストや画像を完全に削除したり、編集したりする機能は限定的です。より高度なPDFコンテンツの構造的な編集(例えば、特定のテキストブロックを完全に削除する)には、PDFの内部構造を深く理解し、より低レベルな操作が必要になる場合があります。

Q3: 大量のPDFから画像を抽出する際の注意点は?

A3: 大量のPDFから画像を抽出する場合、以下の点に注意してください。

  1. メモリ使用量: 一度に多くのPDFを開いたり、高解像度の画像を大量に抽出したりすると、メモリを大量に消費する可能性があります。処理をバッチ化したり、PDFごとに処理を完結させてメモリを解放するなどの工夫が必要です。
  2. ファイル名衝突: 抽出した画像を保存する際に、ファイル名が重複しないように工夫が必要です。ページ番号や元の画像IDなどをファイル名に含めることで、衝突を避けることができます。
  3. エラーハンドリング: 破損したPDFや予期せぬ構造のPDFに対応できるよう、適切なエラーハンドリング(try-exceptブロックなど)を実装することが重要です。

参考資料


免責事項

本記事の内容は、PyMuPDFの利用に関する一般的な情報提供を目的としています。コードの実行、およびその結果生じるいかなる損害についても、筆者および公開元は一切の責任を負いません。ご自身の責任においてご利用ください。


SNSでもご購読できます。

コメントを残す

*