PDFBoxでPDFに画像を差し込む

PDFBoxを使うと、既存のPDFにjpg画像を差し込むことができる。実装例としてはここにあるけど、以下のような感じ。

PDDocument doc = null;
try
{
    doc = PDDocument.load( inputFile );
    //we will add the image to the first page.
    PDPage page = (PDPage)doc.getDocumentCatalog().getAllPages().get( 0 );
    PDXObjectImage ximage = null;
    if( image.toLowerCase().endsWith( ".jpg" ) )
    {
        ximage = new PDJpeg(doc, new FileInputStream( image ) );
    }
    else if (image.toLowerCase().endsWith(".tif") || image.toLowerCase().endsWith(".tiff"))
    {
        ximage = new PDCcitt(doc, new RandomAccessFile(new File(image),"r"));
    }
    else
    {
        //BufferedImage awtImage = ImageIO.read( new File( image ) );
        //ximage = new PDPixelMap(doc, awtImage);
        throw new IOException( "Image type not supported:" + image );
    }
    PDPageContentStream contentStream = new PDPageContentStream(doc, page, true, true);
    contentStream.drawImage( ximage, 20, 20 );
    contentStream.close();
    doc.save( outputFile );
}
finally
{
    if( doc != null )
    {
        doc.close();
    }
}

ポイントは

  • contentStreamの前にximageを取得しておくこと
  • drawImageが左下から始まっていること

かな。

Javaの例外処理

例外処理について、漠然と進めてしまうと後で問題を特定するのが難しくなるので、開発チームのメンバーと意識を合わせて進めたほうが良いかと思う。というわけで、私の経験に基づいて、独断と偏見があるとは思うけど、思うことを以下にまとめておく。

  • 投げる例外は基本的に独自に作ったものを投げる。Exceptionとか、NullPointerExceptionとか、newして投げない。独自に作った例外のほうがログを見たときに自分のシステムのエラーなのかがわかりやすいと思う。
  • Seasar2とか、DI系のシステムだと独自に作った例外はRuntimeExceptionから継承しておく。メソッドにthrowsでいろいろと指定されていても変な依存になるし、面倒な気がするから。
  • Android系とかではExceptionを継承したほうが良いと思う。Androidの場合は、catchしないような例外はアプリを落とすことになるので、明示的な例外処理の方がリスクが低くなると思う。
  • 例外のログはthrowするところでなく、catchして例外を最終的に処理するところで書きだす。なので、必要な情報はthrowする例外にできるだけ保持させるのが良い。
  • 例外をこれからthrowしようとするところではERRORやWARNのログを吐かない。DEBUGやINFOであればよいが、ERRORやWARNをあちこちで書き出すと、ログファイルで追いにくくなる。
  • catchして、別な例外をthrowする場合は、Root Causeを忘れずに指定する。
  • Throwableはcatchしないほうが良い。Throwableの場合、その後の処理が継続できるかわからないし、Sonarに怒られるからやめたほうが良いと思う。
  • catchして例外を無視する場合、確実に無視して良いような例外以外はcatchしたときにログを書きだしておく。つまり、絶対にいらないと自信を持って言えなければログしておく。

まぁ、例外事項はあるかもしれないけど、あとはケースバイケースで…。