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-128105START C不要 (注1)105
GS1-128102FNC1(char)0x00F193 (注2)
GS1 DataMatrix232先頭のFNC1(char)29232 (注3)
GS1 DataMatrix232可変長項目の
終端につけるFNC1
(char)2930(注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を表すコードがあるのがややこしい・・・。調査に何日かかかってしまいました。