toge's diary

コンピュータ関連の趣味をつらつらと。

既存のPDFをPoDoFoで変換

ふとしたことでそこらへんに転がっているPDFを加工したいことがあります。
PDFを生成するライブラリではなくて、PDFのパーザが必要になるのですがC++でやるには何がいいんですかね〜。

今回は、ざっと探して最初に見つかったPoDoFoを使おうと思ってます。
PoDoFo

ライセンスがLGPLv2なのがちょっと気に入りませんが、ちょっとしたツールを作るだけなので問題ありません。
2014年で開発止まっているようですが、今のところ問題なく使えます。
cmakeを使っているのも好印象。
命名規則がかなりごちゃごちゃなのがちょっと気になりますが。
(GetPageCount()だったり、GetNumAnnots()だったりするんです。)

残念ながらサンプルはPDFの生成しか無いし、ドキュメントはDoxygenでのクラスリファレンスなのでぱっと見使い方が分かりません。
PoDoFo ToolsとしていろいろPoDoFoライブラリを使ったツールが公開されているので、これを触りながら使い方を理解してます。
http://podofo.sourceforge.net/tools.html#tools

どうやら、PDFの編集をする一番楽な方法は全部メモリに読み込んで、編集して、書き出す方法のようなので、これに習おうと思います。
ちゃんと理解すればStream処理もできるのかもしれませんが、とりあえず後回し。

奇数頁だけ削除して書き出すプログラムを書いてみました。

#include <iostream>
#include <podofo/podofo.h>

int main(int argc, char* argv[]) {
  if (argc < 3) {
    std::cout << "usage : "
              << argv[0]
              << " <input file> <output file>"
              << std::endl;
    return 1;
  }

  PoDoFo::PdfMemDocument pdfdoc(argv[1]);
  int page_number = pdfdoc.GetPageCount();
  for (int index = page_number - 1; index >= 0; --index) {
    if (index % 2 == 0) {
      continue;
    }
    pdfdoc.DeletePages(index, 1);
  }
  pdfdoc.Write(argv[2]);

  return 0;
}

PdfMemDocumentというクラスを使うのがキモですね。
ファイル名を渡せばPDFの構造としてメモリの読み込んでくれます。
DeletePagesでメモリ上の情報から指定ページだけ決して、最後にWriteでファイル書き出し。
案外簡単。


PDFによっては次のようなメッセージがでちゃいます。
消したページを参照している処が問題起こしてるのかな。
これもおいおい対応できるようにしたいですね。

WARNING: Treating object 110 0 R as a free object.

まあ、この程度ならプログラム書かなくてもできちゃうので、もう少し中身を弄れるようになりたいところです。