高見知英の技術ログ

技術関係のログをQiitaから移行してきました。プログラミングのほか、使っているアプリの細かい仕様についてなど書いていきます。

PDFのサイズ=インチサイズの72倍ではない

はじめに言おう。PDFは悪だ

まあそれはそれとして。ある日プログラムでPDFを作成する必要がでてきました。PDFの内部単位はインチサイズの72倍となっており、単純に考えれば72dpiのピクセル値を入れればよさそうです。

docs.leadtools.grapecity.com

www.benricho.org

ただ実際にやってみると、この通りにPDFを作成しても思い通りのかたちにならず。

Adobe Readerなどで読ませると何かサイズが違う。0.nミリ単位でずれる。これはなぜだろう?と思っていろいろ調べていました。

結果、PDFのサイズ=インチサイズの72倍ではないということが分かりました。

AnサイズのPDFサイズについて

これについてはルールみたいなものがよくわからなかったので、一覧です。このへんはしらみつぶしで探しました。

  • A0: 2383.87, 3370.23
  • A1: 1683.84, 2383.87
  • A2: 1190.52, 1683.84
  • A3: 841.92, 1190.52
  • A4: 595.32, 841.92
  • A5: 419.64, 595.32
  • A6: 297.66, 419.64
  • A7: 209.82, 297.66
  • A8: 147.57, 209.82
  • A9: 104.91, 147.57
  • A10: 73.82, 104.9

前の数値が短辺(縦長の場合は横)、あとの値が長辺(横長の場合は縦)となります。

なぜか小数点が出てしまっていますが、これでAdobe Readerで出力すると、その通りの値となります(PythonのPyPDF2の値を使って出力した場合)。

縦横のサイズ比によって、PDF単位の値は変わる?(未確認)

なんとなく値をいじっているときの感覚ですが、PDF単位の値は、長辺と短辺のサイズから若干変わるような印象を受けました。

このため、「A(n+1)の長い辺は、Anの短い辺と同じ長さ」なはずなのに、必ずしも「A(n+1)の長い辺は、Anの短い辺と同じ長さ」にはなっていません( ISO 216 - Wikipediaより )。

このへんについての最適解については分かりませんが、とりあえず上記の値を使ってページを出力すれば、なんとかなりそうです。

(おまけ)検証コード

検証コードについては以下のようなプログラムを作成しました(実行はGoogle Colabratoryで行なっています)。

!pip install PyPDF2
sizes = [
  { "name": "A0", "size": (2383.87, 3370.23)},
  { "name": "A1", "size": (1683.84, 2383.87)},
  { "name": "A2", "size": (1190.52, 1683.84)},
  { "name": "A3", "size": (841.92, 1190.52)},
  { "name": "A4", "size": (595.32, 841.92)},
  { "name": "A5", "size": (419.64, 595.32)},
  { "name": "A6", "size": (297.66, 419.64)},
  { "name": "A7", "size": (209.82, 297.66)},
  { "name": "A8", "size": (147.57, 209.82)},
  { "name": "A9", "size": (104.91, 147.57)},
  { "name": "A10", "size": (73.82, 104.91)}
]
from PyPDF2 import PdfFileWriter
from google.colab import files
import time
for i in sizes:
  if i["size"] != (0, 0):
    writer = PdfFileWriter()
    writer.addBlankPage(width=i["size"][0], height=i["size"][1])
    with open(f"PDF-{i['name']}.pdf", "wb") as f:
      writer.write(f)
    writer = PdfFileWriter()
    writer.addBlankPage(width=i["size"][1], height=i["size"][0])
    with open(f"PDF-{i['name']}_horz.pdf", "wb") as f:
      writer.write(f)
    print(f"> {i['name']}:{i['size']}")
    time.sleep(0.1)
    files.download(f"PDF-{i['name']}.pdf")
    time.sleep(0.1)
    files.download(f"PDF-{i['name']}_horz.pdf")

※ timesで随時ウェイトを入れないとダウンロードが行なわれない場合があります。

上記のコードで生成されたPDFファイルをAdobe Readerで開き、0.1mmずれていたら18.288(0.12.5472)ずつ値をずらして再度PDFを出力・・・ を繰り返しました。

PDFは悪だ

こんなことをしないと正しいA4のPDFを出力することもできないなんて、やはりPDFは悪だ*1