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
このように、メインページの CTM と XObject の CTM は独立しているため、
階層ごとに変換を管理しなければなりません。
よくある疑問と解決策
| 疑問 | 解決策 |
|---|---|
| PDF の Y 軸が逆転して見える | 1 0 0 -1 0 pageHeight cm を先に配置 |
| 画像の拡大率が画面と異なる | PNG のピクセルサイズを PDF のポイントサイズに合わせ、CTM でスケール |
| 異なる DPI で同じ位置を表示したい | DPI を変数化しておき、pixel = (point / 72) * dpi で算出 |
| ページの余白を無視したい | /CropBox を取得して、実際の描画領域を調整 |
| PDFBox で座標を取得したい | COSArray の getFloat(index) で座標値を取得 |
実用的なワークフロー
- ページメタ情報を取得
- MediaBox, CropBox, Size, DPI を読み込み。
- 描画前に CTM を初期化
- 上端を原点にしたい場合は
1 0 0 -1 0 pageHeight cm。
- 上端を原点にしたい場合は
- 座標系を整えた上で描画
- テキストは
BT /F1 12 Tf 100 200 Td (Text) Tj ETなど。 - 画像は
Doを使い、必要に応じてcmで拡大。
- テキストは
- 変換結果をテスト
- 画像を PNG でエクスポートし、GIMP 等でピクセル座標を確認。
- パフォーマンス最適化
- CTM の累積が重複しないように、
q/Qの使用を徹底。
- CTM の累積が重複しないように、
まとめ
- PDF の座標は 左下が原点。
- 1 pt = 1/72 in, 1 inch は 72 pt。
- CTM(Current Transformation Matrix)で回転・拡大・平行移動が可能。
- PDF 位置を画面ピクセルに変換するには、DPI を掛け、Y 軸反転を忘れない。
- 大規模なレポートや印刷物を作るときは、CropBox や BleedBox も確認。
- 変換は 階層的に管理。XObject 内では別 CTM が存在。
これらを押さえておけば、PDF で「正確な位置」を決める作業が格段に楽になります。
座標の基礎と変換テクニックを活用して、あなたの文書制作をさらに精度の高いものへと導いてください。


コメント