2
10

More than 5 years have passed since last update.

iTextを用いたJavaによるPDFファイル出力

Posted at

目的

  • ソースコードの文字を座標を指定して描画する
  • それぞれの文字がどの座標に存在するかを確認できるようにする

利用するツール

  • iText : JavaでPDFファイルを出力するライブラリ
  • PDFBox : PDF文書から文字とその文字のページ上の出現位置を取り出すために利用

手順

  1. iTextのインストールと利用方法の確認
  2. PDFBoxのインストールと利用方法の確認
  3. ソースコードの提示方法の設定
  4. 1件のコードにたいして実装
  5. N件のコード用に処理を自動化

1. iTextのインストール

Gradleで依存関係を処理する

  • ここでGradleの書き方を調べる:https://mvnrepository.com/
  • 作成したGradle projectの依存関係に以下を追加
// https://mvnrepository.com/artifact/com.itextpdf/itextpdf
compile group: 'com.itextpdf', name: 'itextpdf', version: '5.0.6'

Error 1

Exception in thread "main" com.itextpdf.text.DocumentException: Font 'KozMinPro-Regular' with 'UniJIS-UCS2-H' is not recognized.
    at com.itextpdf.text.pdf.BaseFont.createFont(BaseFont.java:699)
    at com.itextpdf.text.pdf.BaseFont.createFont(BaseFont.java:606)
    at com.itextpdf.text.pdf.BaseFont.createFont(BaseFont.java:441)
    at iText.IndexAction.createPdf(IndexAction.java:29)
    at iText.Main.main(Main.java:12)
  • 原因 : 'KozMinPro-Regular'が認識できていないこと
  • 解決法 : 使用するFontを以下のように変更
BaseFont bf1 = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);

iTextのページサイズの指定は"pt"を利用する

  • 1mm = 2.83pt
  • 1pt = 0.35mm
  • したがって,横幅を350mmにしたければ, 350[mm] * 2.83[pt/mm] = 992.1275 に設定
// define page size as 35x25cm
// iText use "pt" thus we need to transform "mm" to "pt"
// with multiplying "2.83465"
float PAGESIZE_X = (float) (350 * 2.83465);
float PAGESIZE_Y = (float) (250 * 2.83465);

2. PDFBoxのインストールと利用方法の確認

Gradleで依存関係を処理する

  • 作成したGradle projectの依存関係に以下を追加
  • 参考にしている記事と同じv1.8.0を利用する
// https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox
compile group: 'org.apache.pdfbox', name: 'pdfbox', version: '1.8.0'

PDFのテキストの座標を取得する

  • テキスト抽出にはPDFBoxのExtractTextを利用する
  • ExtractTextクラスではpdfbox.util.PDFTextStripperを呼び出して,実際にPDF文書からテキストを取り出している.したがって,PDFTextStripperのサブクラスを作成し、processTextPositionメソッドをoverrideすることで追加情報(文字列の座標)を取得する.
  • 参考:PDF文書から文字とその文字のページ上の出現位置を取り出す (http://www.my-notebook.net/8fd35020-e079-4856-b9bd-d4d5af86d885.html)
@Override
  protected void processTextPosition(TextPosition text) {
    StringBuffer sb = new StringBuffer();
    super.processTextPosition(text);

    sb.append(text.getCharacter()).append(",");
    // sb.append("pageIndex=" + pageIndex).append(",");

    sb.append("x=" + text.getX()).append(",");
    sb.append("y=" + text.getY()).append(",");
    sb.append("width=" + text.getWidth()).append(",");
    sb.append("height=" + text.getHeight());

    printWriter.println(sb.toString());
  }

3. ソースコードの提示形式の設定

提示形式は以下のとおり

  • 描画領域のサイズ:35x25 cm
  • 文字色:白
  • 文字サイズ:0.8x0.8 cm
  • 行間 : デフォルト
  • 背景色 : マイルドな黒 #7f7f7f

4. 1件のコードにたいして実装

  • ERROR : tab文字を読み込まない
  • 対処 : tabを空白に変換する

ソースコードの行数に応じて上下のマージンを調整する

コードブロックはParagraphとして格納している

BaseFontを使って文字のAscent, Decentを計算できる

以下のコードによってフォントのHeightを計算できる.
ascentは正の値,descentは負の値で返されるので,両者の差を取るとフォントのHeightになる.

float ascent = bf.getAscentPoint(text, FONTSIZE);
float descent = bf.getDescentPoint(text, FONTSIZE);
float height = ascent - descent;

LwZJF.png

PsychoPyで利用するためにPDFをJPEG画像化する

その他

Eclipseのformatterをgoogle style guideに変更

1行の折り返し文字数が気に入らないので,google のものに変更

手順

EclipseのKeybindをEmacsに変更

空白文字列のCheckにはApache Commons LangのStringUtilsクラスが便利。

// https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.0'

参考文献

2
10
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
2
10