ZXingでバーコードアプリ開発(3)
GS1-128, GS1 DataMatrixの生成時にFNC1を埋め込む件
GS1を扱うときにFNC1の処理は避けて通れないのですが、ZXingがFNC1をどう扱っているのかが不明でした。日本語のページでもそのことに言及しているサイトが見つからなかったので、ZXingでエンコードしたバーコードをデコードしてRawデータを確認することにしました。
FNC1をバーコードに埋め込むルールは以下の通りです。
(1)可変長のセクションの後に付ける
AI(10)のロットや、AI(30)の入り数などにおいて、セクションの終わりの印として使います。これは、GS1-128 と GS1 DataMatrix の両方に共通するルールです。
(2)GS1-128のスタートコードの後に付ける
GS1-128とCODE128を区別するため、スタートコードの後にFNC1を埋め込むことになっています。
(3)GS1 DataMatrixの先頭
GS1 DataMatrixでは必ずFNC1を先頭に付けます。
尚、読み取り(デコード)時はFNC1は「GS (グループセパレータ)」に置き換えて出力することになっています。 GSはASCIIコード29の制御文字なので、印刷しても出力されません。そのため、市販のバーコードスキャナではGSをスペースに置き換えるなどの機能がついていたりします。
で、ZXingでバーコードを生成するときに、FNC1やSTARTコードをどのように指定すればよいのかを調べたところ、以下の通りとなりました。
表.ZXing.BarcodeWriterのGS1エンコードの動作
フォーマット | コード | 解釈 | C#でZxingに 渡す文字 | バーコード内のコード |
GS1-128 | 105 | START C | 不要 (注1) | 105 |
GS1-128 | 102 | FNC1 | (char)0x00F1 | 93 (注2) |
GS1 DataMatrix | 232 | 先頭のFNC1 | (char)29 | 232 (注3) |
GS1 DataMatrix | 232 | 可変長項目の 終端につけるFNC1 | (char)29 | 30(注4) |
【注1】 ZXingではBarcodeFormatの値を「CODE_128」に指定すると自動的にスタートコードとして「105」が埋め込まれます。 ちなみに、文字列の途中でアルファベットを検知すると「CODE B」への切り替え文字も自動的にバーコードに埋め込んでくれます。
【注2】 GS1-128での「93」は制御文字「GS (ASCII 29)」を表します
【注3】 GS1 DataMatrixでは先頭は必ずFNC1と決められています。ZXingはBarcodeFormatの値を「DATA_MATRIX」にすると、GS (ASCII 29)を「232(FNC1)」に変換してバーコードに埋め込んでくれます。
【注4】 ZXingはBarcodeFormatを「DATA_MATRIX」にすると、先頭以外のGS (ASCII 29)は 「30 (GS)」をバーコードに埋め込みます。
例えば、C#で書くとこんな感じになります、、、
// (01)14512345678903(10)ABCD123(17)201201 をエンコードする例
//writer.Optionsによる画像サイズや余白マージンの指定などはここでは省きます
BitMatrix bitMatrix;
ZXing.BarcodeWriterPixelData writer = new BarcodeWriterPixelData();
string _code;
//GS1-128の場合
writer.Format = BarcodeFormat.CODE_128;
_code = $"{(char)0x00F1}"
+ "0114512345678903"
+ "10ABCD123" + $"{(char)0x00F1}"
+ "17201201";
bitMatrix = writer.Encode(_code);
//-----------------------------------
//bitMatrixからBitmapを作成する処理 (省略)
//-----------------------------------
//GS1 DataMatrixの場合
writer.Format = BarcodeFormat.DATA_MATRIX;
_code = $"{ (char)29}"
+ "0114512345678903"
+ "10ABCD123" + $"{ (char)29}"
+ "17201201"
bitMatrix = writer.Encode(_code);
//-----------------------------------
//bitMatrixからBitmapを作成する処理 (省略)
//-----------------------------------
調査してみて、、、
DataMatrixの可変長項目のFNC1に「GS(ASCII 29) を指定すると、コードワード232を指定したことになる」っていうところが分かりにくかったですね。コードワードにも「30」というGSを表すコードがあるのがややこしい・・・。調査に何日かかかってしまいました。