PDF座標系の基礎と変換テクニック:正確な位置を決める方法

PDF の座標系は「点・点・点」

PDF でページを描画するとき、最初に決めるべきことは座標系の見方です。
多くの人は「印刷物のページをそのまま横軸=左→右、縦軸=上→下」というイメージで書きたいだけなのに、
実は PDF の座標系はそれとは逆転しています。実際に正しい位置を決めるために、
まずは座標系の基礎を押さえておきましょう。

1. 1 点 (point) の意味

PDF の単位は ポイント (pt) です。
1pt は 1/72 英寸(約 0.3528 mm)で、印刷業界で広く使用されている単位です。
ですので、ページ内の座標 (10, 25) は、左端から 10 pt、下端から 25 pt の位置に相当します。
ページの幅・高さを確認するには、/MediaBox で取得できます。

792 612 0 0 res 1 dict begin
...
792 612 0 0 5 2 0 PDF
...
end

ここでは幅 792 pt、高さ 612 pt のページが定義されています。印刷時は 8.5×11 inch に相当します。

2. 座標原点の位置

多くのグラフィックソフトは「左上」を原点に想定しているため、
「左上を原点にしたい」「左上に(100,100)のテキストを配置したい」といった要望は、
PDF では単純に原点を上端にずらす必要があります。
PDF では 下から上 が Y 軸正方向です。従って、ある要素を「上方 100 pt」と表記したい場合は
pdfCanvas.moveTo(x, pageHeight - 100) のように調整します。

変換演算の基本:CTM (Current Transformation Matrix)

PDF では CTM という 3×3 行列で座標変換を管理します。
CTM の各要素は次のような意味を持ちます。

行列要素 意味
a X スケール
b X 反転/スキュー
c Y スケール
d Y 反転/スキュー
e X 変位
f Y 変位

CTM を利用して 回転、拡大・縮小、平行移動 を行います。
大変重要なのは、CTM は 累積 されるという点です。
つまり、ある図形を描画する前に q でグラフィック状態を保存し、
cm で変換行列を掛け合わせ、描画後に Q で元に戻します。

q                         # 画面状態を保存
1 0 0 1 100 200 cm        # X→+100, Y→+200 移動
0 1 -1 0 0 0 cm           # Y 軸を反転(上端を原点にしたい場合に便利)
% 描画命令
q
... # ここに描画
Q                         # 影響を消す
Q                         # 最初の状態へ戻る

PDF + 画像座標の相互変換

PDF を閲覧ツールやライブラリで描画するとき、
画面のピクセル座標と PDF のポイント座標を変換する必要があります。
典型的な変換計算は次の通りです。

変換式

変換 係数
PDF のポイント(x, y)を画面ピクセルに変換
pixelX = (pdfX / 72) * dpiX
pixelY = pageHeight - (pdfY / 72) * dpiY

ここで dpiX, dpiY は画面の解像度(1 inch 当たりピクセル数)です。
ページの高さもピクセル単位で同じ計算を行い、
Y 軸が逆転する点に注意しましょう。

具体例:Java + PDFBox で座標変換

PDDocument document = PDDocument.load(new File("sample.pdf"));
PDPage page = document.getPage(0);

// PDFBox でページの MediaBox を取得
PDRectangle mediaBox = page.getMediaBox();
float pageWidth = mediaBox.getWidth();   // 例: 612.0f
float pageHeight = mediaBox.getHeight(); // 例: 792.0f

// 画面の DPI
float dpi = 96.0f;

// PDF 位置(100pt, 200pt) を画面ピクセルへ計算
float pdfX = 100.0f, pdfY = 200.0f;
int pixelX = Math.round((pdfX / 72f) * dpi);
int pixelY = Math.round((pageHeight - pdfY) / 72f * dpi);

System.out.println("X:" + pixelX + ", Y:" + pixelY);

このコードは、PDF座標画面ピクセル に正確にマッピングする最も単純な例です。
実際のレポートやビジュアル化ツールで組み込むときは、
MediaBox 以外に CropBox, BleedBox, TrimBox などを使うと、
印刷業務でよく使われる「裁ち落とし」や「トリムライン」まで正確に反映できます。

反転・拡大・回転の実践テクニック

A. 位置の反転(縦方向)

多くのレポートでは「左上から配置」したいケースが多いです。
PDF の CTM を使って、ページ全体を Y 軸で反転し、さらに上端を原点に移動します。

1 0 0 -1 0 pageHeight cm
  • -1 が Y 軸反転
  • 0 pageHeight: Y 方向に pageHeight だけ移動すれば、上端が原点になります

B. 回転

90° 回転させたいときは CTM の a, b, c, d を設定します。

0 1 -1 0 0 0 cm   # 90° 反時計回り

C. 拡大/縮小

スケールファクターを a(X スケール)と d(Y スケール)に入れます。

2 0 0 2 0 0 cm   # 2 倍に拡大(幅・高さ両方)

画像やフォームファイルの座標管理

PDF には XObject(フォームオブジェクト、画像オブジェクト) が埋め込み可能。
それぞれは自身の CTM で描画されます。
例として、PDF に埋め込まれた PNG 画像内で要素を正確に配置するには、

q
0 0 1 1 0 0 cm     # 画像座標系で原点を左下に
100 200 0 0 0 0 cm # 画像内10 cm, 20 cm 位置に描画
% 画像描画命令
Q

このように、メインページの CTMXObject の CTM は独立しているため、
階層ごとに変換を管理しなければなりません。

よくある疑問と解決策

疑問 解決策
PDF の Y 軸が逆転して見える 1 0 0 -1 0 pageHeight cm を先に配置
画像の拡大率が画面と異なる PNG のピクセルサイズを PDF のポイントサイズに合わせ、CTM でスケール
異なる DPI で同じ位置を表示したい DPI を変数化しておき、pixel = (point / 72) * dpi で算出
ページの余白を無視したい /CropBox を取得して、実際の描画領域を調整
PDFBox で座標を取得したい COSArraygetFloat(index) で座標値を取得

実用的なワークフロー

  1. ページメタ情報を取得
    • MediaBox, CropBox, Size, DPI を読み込み。
  2. 描画前に CTM を初期化
    • 上端を原点にしたい場合は 1 0 0 -1 0 pageHeight cm
  3. 座標系を整えた上で描画
    • テキストは BT /F1 12 Tf 100 200 Td (Text) Tj ET など。
    • 画像は Do を使い、必要に応じて cm で拡大。
  4. 変換結果をテスト
    • 画像を PNG でエクスポートし、GIMP 等でピクセル座標を確認。
  5. パフォーマンス最適化
    • CTM の累積が重複しないように、q/Q の使用を徹底。

まとめ

  • PDF の座標は 左下が原点
  • 1 pt = 1/72 in, 1 inch は 72 pt。
  • CTM(Current Transformation Matrix)で回転・拡大・平行移動が可能。
  • PDF 位置を画面ピクセルに変換するには、DPI を掛け、Y 軸反転を忘れない。
  • 大規模なレポートや印刷物を作るときは、CropBoxBleedBox も確認。
  • 変換は 階層的に管理。XObject 内では別 CTM が存在。

これらを押さえておけば、PDF で「正確な位置」を決める作業が格段に楽になります。
座標の基礎と変換テクニックを活用して、あなたの文書制作をさらに精度の高いものへと導いてください。

コメント