PDFの座標系完全ガイド:基本概念から実装まで徹底解説

PDFの座標系の基本概念から境界ボックス、座標変換、プログラミングでの実装方法まで、PDFの座標について網羅的に解説します。

📝

この記事について

PDFファイルの座標系について基本概念から実装まで包括的に解説します。PDF開発者、データ抽出エンジニア、DTPデザイナーの方に役立つ内容です。

PDFドキュメントを扱う際、座標系の理解は必要不可欠です。テキストや図形の位置指定、データ抽出、印刷設定など、あらゆる場面で座標の概念が登場します。本記事では、PDFの座標系について基礎から応用まで詳しく解説します。

PDFの座標系とは

基本的な仕組み

PDFの座標系は、紙面上の位置を数学的に表現するためのシステムです。2次元平面上で、任意の点や図形の位置を正確に指定できます。

📊

デカルト座標系

X軸(水平方向)とY軸(垂直方向)で構成される標準的な座標系

📏

ポイント単位

1ポイント = 1/72インチ(約0.35mm)がデフォルト単位

🎯

座標原点

一般的にページの左下角が原点(0,0)として設定される

📐

座標表現

点は(x, y)、矩形は[x1, y1, x2, y2]で表現

座標の方向性

座標方向の特徴

PDFの座標系では、左から右がX軸の正方向下から上がY軸の正方向となります。これは多くのコンピューターグラフィックスとは異なる点です。

座標軸の方向

Y軸(上方向が正)
↑
|
|
+--------→ X軸(右方向が正)
(0,0)
原点(左下角)
  • X軸: 左から右へ向かう水平方向
  • Y軸: 下から上へ向かう垂直方向
  • 原点: ページの左下角(通常)

境界ボックス(Bounding Box)の種類

PDFでは複数の境界ボックスを使ってページの領域を定義します。これらは印刷、表示、トリミングなど異なる目的で使用されます。

5つの境界ボックス

PDF印刷媒体の物理的境界

  • すべての境界ボックスの最外側領域
  • 用紙サイズを定義
  • トンボや裁ち落とし領域も含む
  • MediaBoxの外側に描画された要素は無視される

設定例(A4サイズ):

MediaBox: [0, 0, 595.3, 841.9]

境界ボックスの関係性

📄

一般文書

通常のオフィス文書では、すべての境界ボックスが同じサイズに設定されます。

MediaBox = CropBox = TrimBox = BleedBox
🖨️

印刷用PDF

商業印刷用では各境界ボックスが異なる役割を持ちます。

MediaBox > BleedBox > TrimBox
🌐

Web表示

Web表示では主にCropBoxが使用され、ユーザーの表示領域を制御します。

座標変換と原点設定

ユーザー空間と座標変換

PDFの座標系は柔軟性があり、原点位置や単位を変更できます。

原点の位置は変更できますか?
💡
はい、PDFでは原点位置を自由に設定できます。一般的には左下角が原点ですが、アプリケーションや用途に応じて任意の位置に設定可能です。
座標の単位は変更できますか?
💡
デフォルトは1/72インチ(1ポイント)ですが、変換行列を使用して任意の単位に変更できます。例えば、ミリメートル単位での作業も可能です。

座標変換の実例

1

デフォルト設定

標準的なPDFページの座標設定

原点: (0, 0) - ページ左下
単位: 1ポイント = 1/72インチ
A4サイズ: 595.3 × 841.9 ポイント
2

原点移動

ページ中央を原点とする設定

原点移動: (-297.65, -420.95)
新しい座標系: ページ中央が(0, 0)
3

単位変換

ミリメートル単位への変換

変換係数: 72/25.4 ≈ 2.834
1mm = 2.834ポイント
A4サイズ: 210 × 297 mm

プログラミングでの座標取得

Python実装

PythonでPDFの座標を扱う主要なライブラリを紹介します。

pdfminer.sixを使用した座標取得

from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.pdfpage import PDFPage
from pdfminer.layout import LAParams, LTTextContainer
from pdfminer.converter import PDFPageAggregator

def extract_text_coordinates(pdf_path):
    manager = PDFResourceManager()
    with open(pdf_path, 'rb') as file:
        with PDFPageAggregator(manager, laparams=LAParams()) as device:
            interpreter = PDFPageInterpreter(manager, device)
            
            for page in PDFPage.get_pages(file):
                interpreter.process_page(page)
                layouts = device.get_result()
                
                for layout in layouts:
                    if isinstance(layout, LTTextContainer):
                        # 座標情報の取得
                        text = layout.get_text().strip()
                        x0, y0, x1, y1 = layout.x0, layout.y0, layout.x1, layout.y1
                        width = x1 - x0
                        height = y1 - y0
                        
                        print(f"テキスト: {text}")
                        print(f"左下: ({x0:.2f}, {y0:.2f})")
                        print(f"右上: ({x1:.2f}, {y1:.2f})")
                        print(f"サイズ: {width:.2f} × {height:.2f}")
                        print("-" * 40)

# 使用例
extract_text_coordinates("sample.pdf")

特徴:

  • テキストの詳細な位置情報を取得
  • ページの左下が原点 (0, 0)
  • フォントサイズや文字配置も取得可能

JavaScript実装

ブラウザ環境でのPDF座標操作を見てみましょう。

// PDF.jsを使用した座標取得
import * as pdfjsLib from 'pdfjs-dist';

async function extractPDFCoordinates(pdfData) {
    const pdf = await pdfjsLib.getDocument(pdfData).promise;
    
    for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
        const page = await pdf.getPage(pageNum);
        
        // ページのビューポート(表示領域)
        const viewport = page.getViewport({ scale: 1.0 });
        console.log(`ページ ${pageNum}:`);
        console.log(`サイズ: ${viewport.width} × ${viewport.height}`);
        
        // テキストコンテンツと座標の取得
        const textContent = await page.getTextContent();
        
        textContent.items.forEach((item, index) => {
            if (item.str.trim()) {
                const transform = item.transform;
                const x = transform[4];  // X座標
                const y = transform[5];  // Y座標
                
                console.log(`テキスト ${index}: "${item.str}"`);
                console.log(`位置: (${x.toFixed(2)}, ${y.toFixed(2)})`);
                console.log(`フォントサイズ: ${item.height.toFixed(2)}`);
            }
        });
    }
}

// 使用例
document.getElementById('pdfInput').addEventListener('change', async (event) => {
    const file = event.target.files[0];
    if (file && file.type === 'application/pdf') {
        const arrayBuffer = await file.arrayBuffer();
        await extractPDFCoordinates(arrayBuffer);
    }
});

実践的な応用例

データ抽出における座標活用

座標情報を活用して、PDFから構造化データを抽出する例を紹介します。

1

座標ベースの表認識

def extract_table_data(pdf_path):
    # テキストの座標を取得
    text_elements = extract_text_coordinates(pdf_path)
    
    # Y座標でグループ化(行の認識)
    rows = {}
    for element in text_elements:
        y = round(element['y0'])  # Y座標を丸める
        if y not in rows:
            rows[y] = []
        rows[y].append(element)
    
    # X座標でソート(列の認識)
    table_data = []
    for y in sorted(rows.keys(), reverse=True):  # 上から下へ
        row = sorted(rows[y], key=lambda x: x['x0'])  # 左から右へ
        table_data.append([item['text'] for item in row])
    
    return table_data
2

フォーム要素の位置特定

def find_form_fields(pdf_path, field_labels):
    text_elements = extract_text_coordinates(pdf_path)
    form_fields = {}
    
    for element in text_elements:
        for label in field_labels:
            if label in element['text']:
                # ラベルの右側にある入力欄を推定
                input_x = element['x1'] + 10  # 10ポイント右側
                input_y = element['y0']
                
                form_fields[label] = {
                    'label_position': (element['x0'], element['y0']),
                    'input_position': (input_x, input_y),
                    'input_area': [input_x, input_y, input_x + 100, input_y + 20]
                }
    
    return form_fields
3

レイアウト解析

def analyze_layout(pdf_path):
    text_elements = extract_text_coordinates(pdf_path)
    
    # ページ領域の分析
    x_coords = [e['x0'] for e in text_elements] + [e['x1'] for e in text_elements]
    y_coords = [e['y0'] for e in text_elements] + [e['y1'] for e in text_elements]
    
    layout_info = {
        'content_area': {
            'left': min(x_coords),
            'right': max(x_coords),
            'bottom': min(y_coords),
            'top': max(y_coords)
        },
        'margins': {
            'left': min(x_coords),
            'right': 595.3 - max(x_coords),  # A4幅から計算
            'bottom': min(y_coords),
            'top': 841.9 - max(y_coords)     # A4高さから計算
        }
    }
    
    return layout_info

座標変換ユーティリティ

PDF座標系とスクリーン座標系の変換

class PDFCoordinateConverter:
    def __init__(self, pdf_width, pdf_height, screen_width, screen_height):
        self.pdf_width = pdf_width
        self.pdf_height = pdf_height
        self.screen_width = screen_width
        self.screen_height = screen_height
        
        # スケール計算
        self.scale_x = screen_width / pdf_width
        self.scale_y = screen_height / pdf_height
    
    def pdf_to_screen(self, pdf_x, pdf_y):
        """PDF座標をスクリーン座標に変換"""
        screen_x = pdf_x * self.scale_x
        screen_y = self.screen_height - (pdf_y * self.scale_y)  # Y軸反転
        return screen_x, screen_y
    
    def screen_to_pdf(self, screen_x, screen_y):
        """スクリーン座標をPDF座標に変換"""
        pdf_x = screen_x / self.scale_x
        pdf_y = (self.screen_height - screen_y) / self.scale_y  # Y軸反転
        return pdf_x, pdf_y

# 使用例
converter = PDFCoordinateConverter(595.3, 841.9, 800, 600)
screen_x, screen_y = converter.pdf_to_screen(100, 700)
print(f"PDF座標(100, 700) → スクリーン座標({screen_x:.1f}, {screen_y:.1f})")

トラブルシューティング

よくある問題と解決方法

座標が期待した位置と異なります
💡

以下の点を確認してください:

  1. 原点位置: PDFの原点は左下角です
  2. Y軸方向: 下から上が正方向です
  3. 単位: デフォルトはポイント(1/72インチ)です
  4. ページ回転: ページが回転している場合があります
テキストの座標が取得できません
💡

考えられる原因:

  1. 画像化されたテキスト: OCRが必要な場合があります
  2. フォント埋め込み: 一部のフォントで問題が発生する場合があります
  3. 暗号化: パスワード保護されたPDFの場合があります
  4. 破損: PDFファイルが破損している可能性があります
境界ボックスの情報が正しく取得できません
💡

確認ポイント:

  1. PDFバージョン: 古いPDFでは一部の境界ボックスが未定義の場合があります
  2. 作成アプリケーション: アプリケーションにより設定が異なります
  3. ライブラリの対応: 使用するライブラリの制限があります

デバッグのヒント

💡

デバッグに役立つツール

  • Adobe Acrobat Pro: 座標やプロパティの詳細確認
  • PDF-XChange Editor: 無料で座標情報を表示
  • Pythonスクリプト: 自作ツールでの詳細分析
  • ブラウザ開発者ツール: PDF.jsでの座標確認

まとめ

PDFの座標系は、デジタル文書処理において重要な概念です。基本的な座標の仕組みから、実際のプログラミング実装まで理解することで、PDF処理の幅が大きく広がります。

重要なポイント

📍

座標の基本

左下原点、X軸は右方向、Y軸は上方向、単位はポイント

📦

境界ボックス

5種類の境界ボックスで用途に応じた領域管理

🔧

プログラミング

各言語・ライブラリでの実装方法をマスター

🎯

実践応用

データ抽出やレイアウト解析での活用

PDF座標系の理解は、効率的なPDF処理システムの構築に不可欠です。本記事で紹介した概念と実装例を参考に、ぜひ実際のプロジェクトで活用してください。

次のステップ

座標系を理解したら、より高度なPDF処理技術も学んでみましょう:

💭この記事はいかがでしたか?

あなたの感想やご意見をお聞かせください。今後のコンテンツ改善の参考にさせていただきます。

📤この記事をシェア

この記事が役に立ったら、ぜひ他の人にも共有してください!

✍️記事について

この記事の内容に関してご質問やご指摘がございましたら、お気軽にお問い合わせください。

⚠️ 記事の内容は投稿時点での情報です。最新の情報については公式サイト等でご確認ください。

🔄 内容の正確性には注意を払っていますが、誤りがある場合はお知らせください。

📂 このカテゴリーの他の記事

pdf の記事一覧を見る →

📂同じカテゴリの記事

🏷️関連記事

最新記事

🚀もっと見つける