「Barcode4J」タグのアーカイブ
1.説明
Apache FOP、Barcode4j および ZXing で、QRコードをPDFに出力する方法を説明します。
Barcode4jで、QRコードを生成する場合には、CVSサーバから、ソースファイルをダウンロードしてコンパイルする必要があります。注意事項として、ZXing で日本語を出力するために、Barcode4jの ECIUtil.java を修正する必要があります。修正箇所は下記に示してあります。QRコードに設定できるオプションは、Barcode4j QR Codeに説明があります。
Apache FOP と Barcode4j の連携は、バーコード付きPDFの作成のブログ記事を参考にして下さい。
CVSの設定 Barcode4J CVS
Host: barcode4j.cvs.sourceforge.net
Repository path: /cvsroot/barcode4j
User: anonymous
Password: パスワードはありません。
CVSサーバからダウンロードした、zxing-core-1.7.jarをクラスパスに追加して使用してください。
※最新バージョン2.1のZXingのライブラリィを使用する場合
Encoder クラスにおいてメソッドの引数と返却値が変わったため、Barcode4jのjavaプログラムの修正が必要です。
com.google.zxing.qrcode.encoder.Encoder
バージョン 1.7
void encode(String, ErrorCorrectionLevel, Hashtable, QRCode)
バージョン 2.1
QRCode encode(String, ErrorCorrectionLevel, Map)
※Barcode4jのjavaプログラムの修正クラス
org.krysalis.barcode4j.impl.qr.QRCodeBean
calcDimensions()
org.krysalis.barcode4j.impl.qr.QRLogicImpl
generateBarcodeLogic()
修正内容は、ソースをみればすごく簡単です。
2.出力結果
液晶ディスプレイ自体の解像度が、紙の印刷物に比較して低いため、PDF表示を150%で表示して下さい。スマートフォンにインストールされている、バーコードリーダで読み取ることが確認できると思います。
図 1. Apache FOPで出力したPDF(クリックするPDFが表示されます。)

図 2. qr_code.fo
32行目で、ZXingで使用するエンコード名「shift_jis」を明示的に指定しています。また33行目で、誤り訂正能力を「H」に指定しています。デフォルトは、「L」です。
<?xml version="1.0" encoding="UTF-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="ja">
<fo:layout-master-set>
<fo:simple-page-master page-width="210mm" page-height="297mm" margin-top="0mm" margin-left="0mm"
margin-right="0mm" margin-bottom="0mm" master-name="PageMaster">
<fo:region-body margin-top="15mm" margin-left="15mm" margin-right="15mm" margin-bottom="15mm" />
<fo:region-before extent="15mm" />
<fo:region-after extent="15mm" />
<fo:region-start extent="15mm" />
<fo:region-end extent="15mm" />
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="PageMaster">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="xx-large" font-family="MS 明朝">初めてのQRコード</fo:block>
<fo:block-container absolute-position="absolute" top="15mm" left="0mm" width="125mm" height="117.3mm">
<fo:block font-family="MS 明朝">QRコード内容は、「http://okulejp.com」です。</fo:block>
<fo:block>
<fo:instream-foreign-object>
<barcode xmlns="http://barcode4j.krysalis.org/ns" message="http://okulejp.com">
<qr/>
</barcode>
</fo:instream-foreign-object>
</fo:block>
</fo:block-container>
<fo:block-container absolute-position="absolute" top="35mm" left="0mm" width="125mm" height="117.3mm">
<fo:block font-family="MS 明朝">QRコード内容は、「日本語テスト」です。</fo:block>
<fo:block>
<fo:instream-foreign-object>
<barcode xmlns="http://barcode4j.krysalis.org/ns" message="日本語テスト">
<qr>
<encoding>shift_jis</encoding>
<ec-level>H</ec-level>
</qr>
</barcode>
</fo:instream-foreign-object>
</fo:block>
</fo:block-container>
<fo:block-container absolute-position="absolute" top="270mm" left="0mm" width="125mm" height="117.3mm">
<fo:block font-size="small" font-family="MS 明朝">*QRコード® は、株式会社デンソーウェーブの登録商標です。</fo:block>
</fo:block-container>
</fo:flow>
</fo:page-sequence>
</fo:root>
図 3. ECIUtil.javaの修正例。
53行目で、ZXingで使用するエンコード名「shift_jis」を使用できるように追加します。
/*
* Copyright 2012 Jeremias Maerki, Switzerland
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* $Id: ECIUtil.java,v 1.1 2012/01/27 14:36:35 jmaerki Exp $ */
package org.krysalis.barcode4j.tools;
import java.util.Map;
/**
* Utilities around ECI (extended channel interpretation).
*
* @version $Id: ECIUtil.java,v 1.1 2012/01/27 14:36:35 jmaerki Exp $
*/
public class ECIUtil {
/** ECI code for 8-bit binary data */
public static final int ECI_BINARY = 899;
private static final Map encodingToECI = new java.util.HashMap();
static {
mapEncoding("Cp437", 2);
mapEncoding("ISO-8859-1", 3);
mapEncoding("ISO-8859-2", 4);
mapEncoding("ISO-8859-3", 5);
mapEncoding("ISO-8859-4", 6);
mapEncoding("ISO-8859-5", 7);
mapEncoding("ISO-8859-6", 8);
mapEncoding("ISO-8859-7", 9);
mapEncoding("ISO-8859-8", 10);
mapEncoding("ISO-8859-9", 11);
mapEncoding("ISO-8859-10", 12);
mapEncoding("ISO-8859-11", 13);
mapEncoding("ISO-8859-13", 15);
mapEncoding("ISO-8859-14", 16);
mapEncoding("ISO-8859-15", 17);
mapEncoding("ISO-8859-16", 18);
mapEncoding("SJIS", 20);
mapEncoding("shift_jis", 30);
mapEncoding("Cp1250", 21);
mapEncoding("Cp1251", 22);
mapEncoding("Cp1252", 23);
mapEncoding("Cp1256", 24);
mapEncoding("UnicodeBigUnmarked", 25);
mapEncoding("UTF-8", 26);
mapEncoding("US-ASCII", 27);
mapEncoding("Big5", 28);
mapEncoding("GB18030", 29);
}
private static void mapEncoding(String encoding, int eci) {
encodingToECI.put(encoding, new Integer(eci));
}
/**
* Returns the ECI code for a given encoding.
* @param encoding the encoding
* @return the corresponding ECI code
*/
public static int getECIForEncoding(String encoding) {
Integer code = (Integer)encodingToECI.get(encoding);
if (code != null) {
return code.intValue();
} else {
return -1; //undefined
}
}
}
3.システムの応用例
QRコードには、全角文字が、最大1,817文字を保存できます。スキャナーで、CSV形式のデータを格納したQRコードの内容を読み込んで、入力画面に自動的に読み込むことができます。そうすることで、入力する際の間違えをなくしたり、入力する手間を省いたりすることができます。また暗号データを格納したQRコードを使用して、会員カードによるログイン認証にも応用できます。もちろん商品などの在庫管理にも応用できます。
4.参考及び注意事項
QRコードドットコム-QRコードの特長のご紹介。
攻略! ツール・ド・プログラミング34回 ZXingとは
QRコード® は、株式会社デンソーウェーブの登録商標です。
©中條勝徳 and okulejp.com, 2012.
1.Barcode4Jの紹介
Barcode4Jは、Javaで実装されたオープンソースのバーコード生成ソフトです。 次の様式のバーコードが出力できます。Interleaved 2 of 5、ITF-14、Code 39、Code 128、Codabar、UPC-A、UPC-E、EAN-13、EAN-8、POSTNET、Royal Mail Customer Barcode、USPS Intelligent Mail、PDF417、DataMatrix、DataMatrix、QR Code。またSVG、EPS、PNG、JPEGなどの画像データに出力できます。Apache FOPの可能性と日本語設定のブログ記事にて、コンビニ請求書の例があります。またApache FOP、Barcode4j および ZXing を使用したQRコード付きPDFについては、Apache FOP、Barcode4j および ZXing を使用して、QRコード付きPDFファイルを生成する方法(日本語可能)のブログ記事にて掲載しています。
2.Apache FOPとの連携
Barcode4JをApache FOPのアドオンとして使用することにより、簡単にバーコードをPDFに出力できます。barcode4j.jarと、barcode4j-fop-ext.jarをクラスパスに追加します(ダウンロードサイトにあるbarcode4j-2.1.0-bin.zipに含まれています)。
3.XSL-FO文書への組み込み方
17行目のfo:instream-foreign-object要素下位に、Barcode4Jの独自の要素を追加します。名前空間は、http://barcode4j.krysalis.org/nsです。
18行目のbarcode要素のmessage属性で、バーコードの値を設定します。barcode要素の次は、バーコードの種類に対応した要素が出現します。下記の例の場合は、ean-128要素です。human-readable要素の子要素であるパターンpattern要素で目視文字の出力フォーマットを指定します。template要素では、AI、チェックディ ジットの計算方法とバーコードの内容(数字、英字の桁数)を指定します。AIは括弧でくくります。nは、数字、cdはチェックディ ジットを示します。cd0は チェックディ ジットの計算にAIを含む場合に使用します。template要素は任意で、message属性の値が、template要素で示した内容とあっているかどうか確認します。22行目の(91)n41+cd0は、AIは91、n41は41桁の数字、cd0は、AIと41桁の数字を含めたチェックディ ジットの計算結果を示します。またmodule-width要素でモジュール幅を指定できます。
図 1.barcode.fo
<?xml version="1.0" encoding="UTF-8" ?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master page-height="297mm" page-width="210mm" margin-top="0mm" margin-left="0mm" margin-right="0mm" margin-bottom="0mm" master-name="pageMaster">
<fo:region-body margin-top="30mm" margin-left="10mm" margin-right="10mm" margin-bottom="20mm" />
<fo:region-before display-align="after" region-name="header" extent="25mm" />
<fo:region-after region-name="footer" extent="15mm" />
<fo:region-start extent="8mm" />
<fo:region-end extent="8mm" />
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="pageMaster">
<fo:flow flow-name="xsl-region-body">
<fo:block>EAN-128</fo:block>
<fo:block>
<fo:instream-foreign-object>
<barcode xmlns="http://barcode4j.krysalis.org/ns" message="9176643219876543210987654321098765432109178">
<ean-128>
<height>15mm</height>
<module-width>0.21mm</module-width>
<template>(91)n41+cd0</template>
<human-readable>
<pattern>__________-____________________________-_-______-_</pattern>
</human-readable>
</ean-128>
</barcode>
</fo:instream-foreign-object>
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
図 2.PDFバーコード付きPDF(クリックするとPDFを表示します。)

参照
FOP add-ons
http://xmlgraphics.apache.org/fop/resources.html#products-fop-add-ons
Instructions for the Apache FOP extension
http://barcode4j.sourceforge.net/2.1/fop-ext.html
©中條勝徳 and okulejp.com, 2012.
1.Apache FOPの紹介
Apache FOPは、オープンソースのXSL-FOプロセッサである。XSL-FOオブジェクトからPDFを作成したり、FAX送信に必要なTIFF(CCITT T.4, CCITT T.6)ファイルなど、いろいろなフォーマットのファイルを作成することができます。日本語を使用するには、フォントメトリックファイルを作成する必要がありましたが、バージョン0.95からは、設定ファイルfop.xconfの<fonts>タグに、<auto-detect/>タグを追加するだけで、日本語が使用できます。詳細は、Basic font configurationに掲載されています。また使用できるフォントは、Type 1 FontとTrueType Fontです。Apach FOPの使用方法を掲載している、日本語のサイトの大部分では、日本語を使用する場合、フォントメトリックファイルを必ず作成しなければならないような記述がありますが、それは古いバージョンではそうでしたが、今は、バージョン0.95、1.0では必要ありません。たまたま見た日本語のサイトで、自動設定が可能であることを発見しました。これで日本語導入の煩わしい作業が減りました。公式の英語サイトを、詳細に読む手間を惜しまない事の大切さを身に染みて感じました。詳細に読んだおかげで、fop1.1rc1では、128bitの暗号が可能となったことを知りました。今までは、40bitの暗号でしたが、128bit に変更するこができます。正式バージョンの1.1のリリースが楽しみです。(2012年10月20日に正式バージョンの1.1がリリースしました。) PDFの暗号の設定は、Apache FOP 1.1の新機能(2012/11/16から掲載)にて掲載しています。
Apach FOPは、SVGを使用することができます。単純な帳票ならXSL-FOのみで、複雑ならSVGを使用することができます。SVGの機能に、テキストや図形作成などのいろいろな機能がありますので、それを応用して帳票を作成することができます。SVGとの連携は、Apache FOPとSVGの連携のブログ記事にて掲載しています。またBarcode4jを使用したバーコード付きPDFについては、バーコード付きPDFの作成のブログ記事にて掲載しています。そしてApache FOPとBarcode4jの連携方法は、Using the barcode extension for Apache FOPにあります。それからTIFF出力にいて、Apache FOPのTIFF出力の方法のブログ記事にて掲載しています。最後に、Apache FOP、Barcode4j および ZXing を使用したQRコード付きPDFについては、Apache FOP、Barcode4j および ZXing を使用して、QRコード付きPDFファイルを生成する方法(日本語可能)のブログ記事にて掲載しています。
2.実際のシステム作りでの帳票作成の流れ
XSL-FOまたは、XSL-FOとSVGで一度、様式ファイルを作成します。その後、動的に変わる部分を、XSLTプロセッサを利用して動的に変わるようにXSLTで書き直します。最終的に、フォーム層は、XSLT形式で記述し、データ層は、XML形式で記述します。フォーム層とデータ層から、XSLTプロセッサでXSL-FOオブジェクトを生成し、Apache FOPで帳票を作成します。
3.XSLT + Apach FOP + SVG + テキストエディタ による帳票作成のメリットとデメリット。
●メリット
- 商用の大部分の帳票作成ツールは、メーカ独自のフォーマットを使用するが、標準技術のXSLT、XSL-FOとSVGで、GUIツールなしにテキストエディタで、実際に役立つ帳票を作成できる。
- 帳票のGUIツールは便利だが、XSLT、Apach FOPとSVGなら、テキストファイルを直に修正して、0.1mm単位の微調整ができる。
- SVGだけで帳票の様式ファイルをデザインすれば、ウェブブラウザで、すぐにデザインを確認できる。
- 帳票様式は、フォーム層とデータ層に分離でき、イラストレータなど、市販のSVG画像編集ソフトを使用してフォーム層の基礎部分を作成できる。(SVGの部分だけ、デザイナーに外注できる。)
- XSL-FOは、一つの帳票を複数の区画に分割できるので、一つの帳票を、同時に複数人で作成・修正でき、後で統合することが可能である。
- XML形式なので、プログラムソースのようにコメントを追加できる。
- XSL-FO形式で、ネイティブXMLデータベースで保存すれば、帳票内容のデータ分析を行うことができ、また再度、帳票を作成するときにデータを一から作成する必要がない。
- 無料である。デザインをするクライアント及び、帳票の作成を実行するサーバのライセンス料がかからない。メーカによるが、ライセンス料が、開発、評価及び本番環境を含めると、約数十万~数百万円くらいで、高機能すぎるがゆえにとても高価である。(気のせいか、昔に比べて、全体的に値段が高くなっているような気がする。オープンソースのツールの利用が増えて売り上げが落ちているのだろうか。)
- いろいろなファイル形式(PDF, PS, PCL, AFP, XML, Print, TIFF, AWT and PNG)に対応している。メーカ製なら、オプション扱いで別当料金が発生する場合がある。
- 負け惜しみであるが、帳票のGUIツールは頭をあまり使わなく便利である。しかし標準技術を使うことで、自由度は極めて高く、また頭を使って苦労するのでいいアイディアも生まれやすい。また帳票作成で使用したXMLに関する標準技術は、他の分野にも必ず役立つ。
●デメリット
- XSLT、XSL-FO及びSVGの仕様を覚える必要がある。
- 帳票のGUIツールに比べ、帳票作成の生産性が低い。会社で帳票のテンプレートをストックすることで、ある程度は解消できる。
- メーカ独自の便利な機能は、自前で実現しないといけない。(たいていの帳票作成ツールを提供するメーカには、メーカ独自の便利な機能がある。たとえば、ソート機能、合計機能、ある項目が変わったときの改ページ等。)
4.定型様式及び非定型様式の帳票
様式が非定型ならXLS-FO、様式が定型なら、XLS-FOかSVGが原則になると思います。
XLS-FOは、たとえば、文字が一行にはいりきれなかったら自動的に改行をし、またページがいっぱいになったら改ページをしてくれます。またページ番号、総ページ数を表示することも可能です。しかし、既存の大部分の帳票作成ソフトは、表示する項目の文字数が決まっていてあふれた文字を、特別な設定をしない限り、改行、改ページをすることはありません。私が、帳票を設計するのなら、XLS-FOのみの機能で実現できるのならXLS-FOで、そうでなければSVGも使用して帳票を作成します。
5.実際の帳票作成例
コンビニ請求書の例は、休みの空いた時間に、Apache FOP、Barcode4jとSVGでどこまでできるのか試しに作成したものである。
※注意
1.サンプルであって、実際に使用する場合、印刷品質とバーコードの読取精度の確認等が必要である。
2.バーコードの内容を確認する目視文字は、改行文字を出力できないため、Barcode4jのソースファイルを修正しています。修正箇所は2ファイルで、下記、「9.付録 Barcode4jの修正例」にて説明しています。
3.Apache FOPは、日本語の縦書きに対応していませんが、SVGは対応しています。
図 1. コンビニ請求書(クリックするとPDFを表示します。)
(Adobe Readerの100%表示で一部太線のレイアウトが崩れていますが、125%で表示すれば、きちんと太線が描かれているのが確認できます。)

6.SVGのアニメ
SVGを使用することで、無制限にどんなものも作成できてしまうと思わせるアニメがありました。
SVG女子は、マイクロソフト基調講演MIX11で公開され、世界中から注目を浴びましたが、日本でも公開されました。
詳細は、右記サイトです。 http://jsdo.it/event/svggirl/
7.最後に
SVGには、テキストや図形作成などのいろいろな機能があるので、それらを駆使することで、サンプル例のように、実際に役立ちそうな帳票を作成することもできます。
自分がSEになったときに比べて、XMLの技術がより浸透し、実際のシステム作りに役立ってきているという実感があります。最新のEclipseは、XMLスキーマファイルを読み込んで、XML文書のコード補完が当たり前のようにできています。つい10年前なら、数万円出してXMLエディタを買わないといけなかったのに便利になったものである。Apache FOPのコード補完の設定もEclipseで使用できます。またそれを応用してSVGのコード補完の設定もできます。詳細は、Apache FOPのEclipseコード補完設定(コンテンツアシスト)とSVGのEclipseコード補完設定(コンテンツアシスト)を参照して下さい。
8.参照
公共料金等代理収納GS1-128(旧:UCC/EAN-128)システム
オフィスプリンターの「コンビニバーコード出力」対応
9.付録 Barcode4jの修正例
11行目をコメントアウトして、13~16行目にて、目視文字の出力フォーマットに改行文字が含まれていた場合の処理を追加しています。修正の仕方は、改行文字が含まれていない場合は、既存の処理と同じようになるようにしています。
図 2. org.krysalis.barcode4j.impl.AbstractBarcodeBean getHumanReadableHeight()
public double getHumanReadableHeight() {
if (getMsgPosition() != HumanReadablePlacement.HRP_NONE) {
double textHeight = this.fontSize;
if (hasFontDescender()) {
//return 1.3 * textHeight;
textHeight *= 1.3;
//1.3 is the factor for the font descender
//(just an approximation due to the lack of a font engine)
} else {
//return textHeight;
}
if(getPattern()!=null && getPattern().indexOf("\n")>0) {
textHeight *= 2.0;
}
return textHeight;
} else {
return 0.0;
}
}
6行目をコメントアウトして、8~17行目にて、目視文字の出力フォーマットに改行文字が含まれていた場合の処理と、そうでない場合の処理を追加しています。修正の仕方は、改行文字が含まれていない場合は、既存の処理と同じようになるようにしています。
図 3. org.krysalis.barcode4j.impl.DefaultCanvasLogicHandler endBarcode()
public void endBarcode() {
if (bcBean.getMsgPosition() == HumanReadablePlacement.HRP_NONE) {
//nop
} else {
double ty = getTextBaselinePosition();
//DrawingUtil.drawText(canvas, bcBean, formattedMsg, getStartX(), x, ty, TextAlignment.TA_CENTER);
if(formattedMsg!=null & formattedMsg.indexOf("\n")>0) {
String msgBeforeNewline = formattedMsg.substring(0, formattedMsg.indexOf("\n"));
String msgAfterNewline = formattedMsg.substring(formattedMsg.indexOf("\n")+1);
DrawingUtil.drawText(canvas, bcBean, msgBeforeNewline, getStartX(), x, ty - bcBean.getFontSize()-bcBean.getHumanReadableHeight() / 100, TextAlignment.TA_LEFT);
DrawingUtil.drawText(canvas, bcBean, msgAfterNewline, getStartX(), x, ty,TextAlignment.TA_LEFT);
} else {
DrawingUtil.drawText(canvas, bcBean, formattedMsg, getStartX(), x, ty, TextAlignment.TA_CENTER);
}
}
}
©中條勝徳 and okulejp.com, 2012.