Hatena::ブログ(Diary)

アセトアミノフェンの気ままな日常

2015-10-29

dvipdfmx は /Rotate に対応していないという話、への対処法(補足編2)

先日の /Rotate 問題に対する別解が出された。

対処法5:gs で再び PDF → PDF 変換する

元の PDF が /Rotate を含んでいようといなかろうと

 $ gs -sDEVICE=pdfwrite -dBATCH -dNOPAUSE -dAutoRotatePages=/None -sOutputFile=out.pdf in.pdf

あるいは

 $ ps2pdf -dAutoRotatePages=/None in.pdf out.pdf   <= Unix 系,TeX Live (win32) の場合
 $ ps2pdf -dAutoRotatePages#/None in.pdf out.pdf   <= Windows で角藤版 Ghostscript を使用する場合

で変換するという方法である*1。試してみると、確かに gs で再変換すると /Rotate を含まない “回転が確定した” PDF が得られる。ファイルサイズを比べると

  in.pdf    3,620 byte
  out.pdf   3,630 byte

で、pdfTeX に比べてファイルサイズの増加は小さいという特徴もあるようだ。さて、pdfTeX にしろ gs にしろ、この処理で何が起きているのかをもう少し詳しく確かめたくなってくる。そこで、簡単にではあるが QPDF を使って PDF のストリームを読んでみることとしよう。

もう少し詳しく:QPDF による解析

元の /Rotate 付きの PDF から注目すべき部分だけ抜粋してみる:以下は1ページ目のサイズを規定した部分。実際の文字や描画内容はストリームのツリーで親子関係にある別の object に書かれている。

%% Page 1
%% Original object ID: 4 0
6 0 obj
<<
  /Contents 7 0 R
  /MediaBox [
    0
    0
    612
    792
  ]
  /Parent 5 0 R
  /Resources <<
    /ExtGState 9 0 R
    /Font 10 0 R
    /ProcSet [
      /PDF
      /Text
    ]
  >>
  /Rotate 90            % <= ここに注目
  /Type /Page
>>
endobj

これを gs で二度と回転させないように注意して

 $ gs -sDEVICE=pdfwrite -dBATCH -dNOPAUSE -dAutoRotatePages=/None -sOutputFile=out.pdf in.pdf

で変換すると、以下のようになる:

%% Page 1
%% Original object ID: 4 0
6 0 obj
<<
  /Contents 7 0 R
  /MediaBox [
    0
    0
    792
    612
  ]
  /Parent 5 0 R
  /Resources <<
    /ExtGState 9 0 R
    /Font 10 0 R
    /ProcSet [
      /PDF
      /Text
    ]
  >>
  /Type /Page
>>
endobj

このように、/Rotate が消滅して回転が “確定” する。このとき /MediaBox の値もこっそり変わっていることに注目してほしい。後の描画内容を記述した object も見てみると、gs は PDF の /Rotate を解釈したうえで全体を新しい向きに再描画していることに気づくだろう。これが “回転が確定” する理由である。

もし "majority decision" が2回働くと?

さて、doraTeX さんの指摘について:もし仮に

 $ gs -sDEVICE=pdfwrite -dBATCH -dNOPAUSE -sOutputFile=out.pdf in.pdf

で変換するとどうなるだろうか。当然ながら、これまた "majority decision" が働くのだが、この in.pdf が元々 "majority decision" の結果に一致するものであれば、さらに回転する必要がないので向きは維持される(abenori さんのはこれを想定していると思う)。ただ、よく見ると微妙な違いがある:

%% Page 1
%% Original object ID: 4 0
6 0 obj
<<
  /Contents 7 0 R
  /MediaBox [
    0
    0
    792
    612
  ]
  /Parent 5 0 R
  /Resources <<
    /ExtGState 9 0 R
    /Font 10 0 R
    /ProcSet [
      /PDF
      /Text
    ]
  >>
  /Rotate 0             % <= ここに注目
  /Type /Page
>>
endobj

この場合、extractbb や dvipdfmx で警告が出ることはない:というのは、extractbb は /Rotate が 0 でない場合に警告を出す仕様だからである。/Rotate は確かに存在するが、これは “回転が確定している” のである(/MediaBox の値もこっそり変わっていることに注目)。どうやら gs は「AutoRotatePages が有効になっている場合、必ず /Rotate 命令を書き込んで適切な数値(90の倍数または0)を与える」という仕様になっているらしい。

*1:ps2pdf は本来名前のとおり PS を PDF に変換するスクリプトであるが、実装は pdfwrite のラッパーであり .pdf も受け付ける。したがって、このような使い方も可能である。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証