LoginSignup
10
7

More than 5 years have passed since last update.

Apache:PDFBoxを使って透かしを入れる

Last updated at Posted at 2017-10-14

Apache:PDFBox

javaで一般的なPDF編集ツールというとiTextかと思うが、(商用目的で利用してソースを公開しない場合)iTextの場合ライセンス購入が必要なため、導入においてハードルがある。

初期導入時点であれば(金銭面で)話も通しやすいかもしれないが、既存システムへの導入となると困ることがある。。

ライセンスフリーでPDFの編集を行えるツールとして検討したところ、ApacheからPDFBoxなるものが提供されているとのことで、その実装についてメモ。

導入

以下のサイトからダウンロード可能。

(Apacheのサイトです)

記事作成時点の最新は2.0.7だが、実装時は2.0.7リリース前であったため、サンプル実装は2.0.6で行っている。

ダウンロードしたjarをプロジェクトに取り込んで導入完了。

サンプル実装

実装環境は、windows10端末、java1.8。

ちょっとググれば既に日本語で実装サンプルが上がっている。

PDFBoxを使って透かしを入れるサンプル
    public static void main(String[] args) {
        File pdfPath = new File("…/sample/sample.pdf");//元のPDF
        File outPath = new File("…/sample/makepdf.pdf");//編集後のPDF
        String tmpPath = "…/sample/temp.pdf";//一時ファイル

        // 背景として透かす用のPDFを作成する
        PDDocument tmp = new PDDocument();
        PDRectangle rectangle = PDRectangle.A4;//A4サイズ
        PDPage tmpPage = new PDPage(rectangle);
        tmp.addPage(tmpPage);

        File file = new File("/Windows/Fonts/msgothic.ttc");//マルチバイトを扱う場合フォントファイルを読み込む必要がある
        try (TrueTypeCollection collection = new TrueTypeCollection(file)) {
            PDPageContentStream cont = new PDPageContentStream(tmp, tmpPage);
            PDFont font = PDType0Font.load(tmp, collection.getFontByName("MS-Gothic"), true);// MS ゴシックを指定
            float fontSize = 50;// 出力する文字の大きさを指定
            //float size = font.getFontDescriptor().getFontBoundingBox().getHeight() / 1000 * fontSize;// 指定フォントにおける1文字の高さを取得
            //cont.transform(new Matrix(1, 0, 0, 1, 20, 100));// 出力領域の位置を指定(Matrix(前半4つ「線形変換を表す2行2列の行列の 00, 01, 10, 11成分に対応します」だそな。。。後半2つ「 X軸、Y軸方向への平行移動の成分」))
            PDExtendedGraphicsState state = new PDExtendedGraphicsState();
            state.setNonStrokingAlphaConstant(0.2f);// 透過率:1は無透過、0は完全に透過
            cont.stGraphicsStateParameters(state);
            cont.setNonStrokingColor(255, 0, 0);//色の指定:RGBで行える
            cont.beginText();//出力文字の指定を開始する
            cont.setTextMatrix(Matrix.getRotateInstance(0.7, (rectangle.getWidth()/4), (rectangle.getHeight()/6)*2));//出力領域の位置を指定(arg0:傾き、arg1:X軸の位置、arg2:Y軸の位置)
            cont.setFont(font, fontSize);//フォントを設定
            cont.newLine();//新規行を生成
            cont.showText("これはテストです。");// 出力文字を指定
            cont.endText();//出力文字の指定を終了する
            cont.close();
            tmp.save(tmpPath);//PDFを出力
        } catch (IOException e1) {
            // 必要があれば例外処理
            e1.printStackTrace();
        } finally {
            try {
                tmp.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        HashMap<Integer, String> overlayGuide = new HashMap<Integer, String>();// どのページにどのドキュメントを差し込むかの指定を保持するMAP

        try (PDDocument doc = PDDocument.load(pdfPath)) {//元のPDFを読み込む
            for (int i = 0; i < doc.getPages().getCount(); i++) {//PDFのページ数繰り返す
                overlayGuide.put(i + 1, tmpPath);//1オリジンでどのページにどのドキュメントを重ねるかを指定
            }
            Overlay overlay = new Overlay();
            overlay.setInputPDF(doc);//元のPDFのPDDocumentを指定
            overlay.setOverlayPosition(Overlay.Position.FOREGROUND);//差し込むドキュメントの位置を指定(前面or背面)
            overlay.overlay(overlayGuide);// MAPの設定に従い元のPDFにドキュメントを差し込む
            //PDFファイルを出力
            doc.save(outPath);// 加工後のPDFを出力する
            overlay.close();
            doc.close();
        } catch (InvalidPasswordException e) {
            // 必要があれば例外処理
            e.printStackTrace();
        } catch (IOException e) {
            // 必要があれば例外処理
            e.printStackTrace();
        } finally {
            // 一時ファイルを削除する
            File fl = new File(tmpPath);
            fl.deleteOnExit();
        }
    }

#コメントアウト行は個人的なメモのため、読み飛ばして頂きたい。。

実行すると、社外秘とかにありがちな斜めになった文字が元PDFの全ページに重ねられて表示されます。

実装内容について簡単に

実装内容について簡単に説明。

透かし用の文字を記入したPDFを作成。

このPDFを透かしを反映したいPDFの全ページに重ねるようにして、編集後のPDFを出力している。

このページを重ねる役割を担っているのが、Overlayオブジェクト。

どのページにどのドキュメントを重ねるかを指定するのはMAPで行う。

このため、あるページでは透かしを入れる、あるページでは入れないなどの出しわけが可能。

Overlayオブジェクトの呼び出し
    Overlay overlay = new Overlay();
    overlay.setInputPDF(doc);//元のPDFのPDDocumentを指定
    overlay.setOverlayPosition(Overlay.Position.FOREGROUND);//差し込むドキュメントの位置を指定(前面or背面)
    overlay.overlay(overlayGuide);// MAPの設定に従い元のPDFにドキュメントを差し込む

透かし用PDFの透かし設定は、PDExtendedGraphicsStateオブジェクトのsetNonStrokingAlphaConstant()で行っている。

引数はフロート値で、1は無透過、0は完全に透過なので、その間の数値で透過率を指定する。

透かし設定
    PDPageContentStream cont = new PDPageContentStream(tmp, tmpPage);
    PDExtendedGraphicsState state = new PDExtendedGraphicsState();
    state.setNonStrokingAlphaConstant(0.2f);// 透過率:1は無透過、0は完全に透過
    cont.setGraphicsStateParameters(state);

その他、理解できた範囲でコメントをつけているので、参考にして頂ければ幸い。

別の実装方法もあるかと思うのでお試し下さい。。。

10
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
7