PDFファイルのページ数を知りたい

雨が続いています。通勤時はカッパを着込みますが、こう雨続きだとなかなか乾きませんし、面倒なのです。しかし、雨にぬれたりすると大変です。何が大変かって、湿度が高くて乾きにくいので少々におって来たりします。しまいには濡れた「犬のにおい」みたいなにおいがしてきかねませんのでしっかりと雨はブロックしなければなりません。
まあ、わたしの日常は置いておいて、PDFの配置って結構不便ですよね。PDFのページ数をチェック出来るプロパティがありませんから。Indesignなどで大量に配置する場合は、あらかじめページ数調べておいたりして手間がかかります。
ワードなんかから書き出したPDFを張り込んで…という作業は結構ありますので以前からここをなんとかしたかった訳です。

PDF 32000-1:2008より抜粋
7.7.3.2Page Tree Nodes
Table 29 shows the entries in a page tree node that shall always be present (Required).

Key Type Value
Type name (Required) The type of PDF object that this dictionary describes; shall be Pages for a page tree node.
Parent dictionary (Required except in root node; prohibited in the root node; shall be an indirect reference) The page tree node that is the immediate parent of this one.
Kids array (Required) An array of indirect references to the immediate children of this node. The children shall only be page objects or other page tree nodes.
Count integer (Required) The number of leaf nodes (page objects) that are descendants of this node within the page tree.

NOTE : The structure of the page tree is not necessarily related to the logical structure of the document; that is, page tree nodes do not represent chapters, sections, and so forth. Other data structures are defined for this purpose; see 14.7, “Logical Structure”.

Conforming products shall not be required to preserve the existing structure of the page tree.

EXAMPLE : The following illustrates the page tree for a document with three pages. See 7.7.3.3, “Page Objects,” for the contents of the individual page objects, and H.5, “Page Tree Example”, for a more extended example showing the page tree for a longer document.

Page Treeは基本的にヒエラルキーのトップにあるオブジェクトのCountキーに、包含されるオブジェクトの数が記述されています。
では見本を見てみましょう。

3 0 obj
<</Count 12/Kids[132 0 R 133 0 R]/Type/Pages>
endobj
132 0 obj
<</Count 5/Kids[134 0 R 135 0 R 136 0 R 137 0 R 138 0 R]/Parent 3 0 R/Type/Pages>>
endobj
133 0 obj
<</Count 7/Kids[139 0 R 140 0 R 141 0 R 142 0 R 143 0 R 144 0 R 145 0 R]/Parent 3 0 R/Type/Pages>>

上記の例では一番上のオブジェクト「3 0 obj」がヒエラルキーの頂上のオブジェクトになります。
ですからこの例では総ページ数はCountキーの引数12となります。
しかしながら、最近のバージョンはともかく、全てのPDFファイルがこの構造を持つ訳ではありません。よってこのトップレベルのCountキーを参照する方法だけでは不完全です。

<
/Type /Page

書き出し方にもよるのですが以上の様にページ毎にキーが記述されている場合もあります。
これらはドキュメントを頭から調べて数えていけばページ数を知る事ができます。
更に

/StructParents 0/Type/Page>>
/StructParents 0/Tabs/S/Type/Page>>

とうい感じの記述もあります。
これらを総合して…

function pgLen(f){
    var tg = /<<\/Count\s(\d+)/;
    var count = /<<\/Type\/Page\/Parent/;
    var count_2 = /\/Type\s\/Page\s/;
    var count_3 = /\/StructParents\s\d+.*\/Type\/Page>>/;
    var len = 0;

    if(f.open(‘r’)){
        while(!f.eof){
            wd = f.readln();
            if (tg.test(wd)) return RegExp.$1;
            if (count.test(wd)) len++;
            if (count_2.test(wd)) len++;
            if (count_3.test(wd)) len++;
            }
        }
    if(len>0) return len;
    return null;
    }

という感じのファンクションにしてみました。まだ不完全ですが必要な時にnull返された事無いのでなんとか使えると思います。
nullが返るPDFいただけたら解析してみたりするかもしれません。

追記
「Linearized PDF Document Structure」に対応しました。

function getPageLength(f){
 var tg = /<<\/Count\s(\d+)/;
 var count = /<<\/Type\/Page\/Parent/;
 var count_2 = /\/Type\s\/Page\s/;
 var count_3 = /\/StructParents\s\d+.*\/Type\/Page>>/;
 var tg2 = /<>/; //add target “Linearized PDF Document Structure”
 var len = 0;

 if(f.open(‘r’)){
  while(!f.eof){
  wd = f.readln();
  if (tg.test(wd)) return RegExp.$1 – 0;
   if (tg2.test(wd)) return RegExp.$1 – 0;
   if (count.test(wd)) len++;
   if (count_2.test(wd)) len++;
   if (count_3.test(wd)) len++;
   }
  }
 if(len>0) return len;
 return null;
 }

ドキュメントに目を通せば通す程出てきますね。気がついた分は随時アップデートしますね。

ten_a

Graphic Designer, Scripter and Coder. Adobe Community Professional.

シェアする