概略
ZXing.Netで1次元バーコードを作成した際の注意点を以下にメモしておきます。
コード
以前に書いた記事と同様に
以下のようにすることでC#で1次元バーコードの作成も可能なのですが、注意点があります。
var barcodeWriter = new BarcodeWriter(); barcodeWriter.Format = BarcodeFormat.UPC_A // 1次元バーコードのサイズ決定 barcodeWriter.Options.Height = 50; barcodeWriter.Options.Width = 200; // 1次元バーコードを出力 Bitmap bmp = barcodeWriter.Write(501234012017);
注意点
エラーの取り扱い
上記の数字の部分を”456995111617”とするとSystem.ArgumentExceptionのエラーが発生します。内容としては、”Contents do not pass checksum”です。
下記のコードのようにすれば、例外としては扱えます。
string str = string.Empty; try { Bitmap bmp = barcodeWriter.Write("456995111617"); } catch(System.ArgumentException ex) { str = ex.Message; }
チェックディジット
上記のコードで取得した文字列はstr=”Contents do not pass checksum”という文字列が入っています。この文字列が意味することは、入力桁のチェックディジットの部分がおかしいので、エラーが発生しています。ということが推測されました。テストを行うとやはりその推測のようになっていました。その結果を下の方にテスト状況の表について書いています。
Zxing.netではチェックディジットの確認をおこなっているものもあります。(おおむね行っている。)なので、チェックディジットを理解しながら、値を入力するか、こちら側でチェックディジットを計算してから正しい値をZxing.netの関数に入力する必要があります。
キーエンス解説などにも解説されていますが、チェックディジットを計算して、誤り率を減らすための仕組みです。
- チェックディジットを計算して入力する。≪モジュラス10/ウェイト3≫や、[メモ] 各種チェックデジットの計算方法, バーコード入門編 13:チェックデジット算出方法, チェックデジットとチェックデジット計算機などの計算方法を解説してもらえるサイトがいくつもありますので、それに従って計算チェックをするとよいでしょう。
- C#で探すと、komozoさんのコードが参考になるかと思います。
- 正しいチェックディジットを持つ文字列を入力する。バーコードどころさんの、UPCコード(UPC-A/UPC-E)を作成するや、GS1 Japanや、海外のBarcode Checkdigit calculator等で作成した後に、引数部分に入力するのもよいでしょう。
バーコード毎のチェックディジット一覧
ZXing.netで作成できるバーコードは以下の通り
The encoder supports the following formats: UPC-A, EAN-8, EAN-13, Code 39, Code 128, ITF, Codabar, Plessey, MSI, QR Code, PDF-417, Aztec, Data Matrix
(Github – micjan/ZXing.netより 2018/08/13時点)
そのうちの1次元はUPC-A, EAN-8, EAN-13, Code 39, Code 128, ITF, Codabar, Plessey, MSIです。チェックディジットを計算するものしないもの、多数のアルゴリズムで計算するものなどがあります。以下を参考にしてください。
モジュラス10/ウェイト3
モジュラス10/ウェイト3解説を参照ください。
- UPC-A
- EAN-8,EAN-13
- ITF
(*) 注意 UPC-E は少しまた複雑で注意が必要です。ここを参照したり、「UPC-E チェックディジット 計算方法」などを参考にされるとよいかもしれません。
モジュラス43
モジュラス43解説を参照ください。
- Code 39(チェックディジット必須ではない)
モジュラス103
モジュラス103解説,キーエンスCODE128解説を参照ください。
- Code 128
CRC(巡回冗長検査)
- Plessy
* CODABAR(NW-7)は注意
CODABAR(NW-7)はチェックディジットが必須ではないのですが、いろいろなチェックディジットの計算方法を使用できるようです。
NW-7(CODABAR)AIMより。一般的にはモジュラス16(ここより引用)。ここも参照。
(2018.08.19 以下追記)
上記までで、初めこのCODABARの項目を書いていました。チェックディジットの計算アルゴリズム見ていくと、モジュラス16の計算ではスタート・ストップキャラクターを含めて、チェックディジットの計算を行います。こちらを参照ください。
また一方で、数字のみのCODABAR(NW-7)も存在しているようです。こちらとこちらを参照ください。この場合、いろいろな他のWeb上の記事を参照にしましたが、スタート・ストップキャラクターが省かれていました。いろいろとCODABAR(NW-7)自身もバリエーションがあるようです。
数字のみのCODABAR(NW-7)は、以下のようなチェックディジットの計算方法を採用されているようです。
- モジュラス10 ウェイト2・1分割
- ジュラス10 ウェイト2・1一括
- モジュラス10 ウェイト3・1
- モジュラス11 ウェイト1~0
- セブンチェック(7DR及び7DSR)
- ナインチェック(9DR及び9DSR)
そして、この項目の初めの『CODABAR(NW-7)はチェックディジットが必須ではなく、いろいろなチェックディジットの計算方法を使用できる』というところに戻るのですが、このようなCODABAR(NW-7)の状況のために、ZXing.netではチェックディジットの確認を省いているように見受けられます。このため、スタート・ストップキャラクタのありなしにかかわらず、バーコードを作成はしてくれます。
* MSIも注意
こちらを参照
- No check digit (least common)
- Mod 10 (most common)
- Mod 11
- Mod 1010
- Mod 1110
バーコード毎に対応状況を確認
コードによるテスト
C#でテストのプロジェクトを作成して、以下のようにバーコードの作成と読み取り。またチェックディジットを確認しているかのテストを行いました。
- 01テスト側で、作成→読み取りのテストが通っています。(作成・読み取り可能)
- 02テスト側で、チェックディジットが間違ったものを入れて、例外が発生していますので、チェックディジットの確認をしていることがわかります。
const string str_UPC_A_correct = "501234012017"; const string str_UPC_A_wrong = "456995111617"; [TestMethod] public void Encode01_UPC_A_01() { BarcodeWriter barcodeWriter = new BarcodeWriter(); // 出力するコードの形式を選択 barcodeWriter.Format = BarcodeFormat.UPC_A; // 1次元コードのサイズ決定 barcodeWriter.Options.Height = 50; barcodeWriter.Options.Width = 200; // バーコードを出力 // 値はチェックディジットの正しい値を入れること // https://barcode-place.azurewebsites.net/Barcode/upc using (Bitmap bmp = barcodeWriter.Write(str_UPC_A_correct)) { BarcodeReader barcodeReader = new BarcodeReader(); Result result = barcodeReader.Decode(bmp); Assert.AreEqual(BarcodeFormat.UPC_A, result.BarcodeFormat, "UPC-A 読み取りフォーマットが異なります。"); Assert.AreEqual(str_UPC_A_correct, result.Text, "UPC-A 読み取ったデータが異なります。"); } } [TestMethod] public void Encode01_UPC_A_02_チェックディジット確認() { BarcodeWriter barcodeWriter = new BarcodeWriter(); // 出力するコードの形式を選択 barcodeWriter.Format = BarcodeFormat.UPC_A; // 1次元コードのサイズ決定 barcodeWriter.Options.Height = 50; barcodeWriter.Options.Width = 200; // バーコード出力 try { Bitmap bmp = barcodeWriter.Write(str_UPC_A_wrong); } catch (System.ArgumentException ex) { Assert.AreEqual("Contents do not pass checksum", ex.Message, "正しくエラーが処理できていません。"); } }
テスト結果
UPC-A, EAN-8, EAN-13, Code 39, Code 128, ITF, Codabar, Plessey, MSI について、一つずつ同じようなコードを書き、対応状況を確認しました。
The following barcodes are supported by the decoder: UPC-A, UPC-E, EAN-8, EAN-13, Code 39, Code 93, Code 128, ITF, Codabar, MSI, RSS-14 (all variants), QR Code, Data Matrix, Aztec and PDF-417.
(Github – micjan/ZXing.netより 2018/08/13時点)
で、一次元の読み取りできる種類が、UPC-A, UPC-E, EAN-8, EAN-13, Code 39, Code 93, Code 128, ITF, Codabar, MSI, RSS-14 となっていますので、この一覧にあるPlessyが読み取れないのはなっとくがいきますが、MSIが読み取れないのは何故か理由は不明でした。(しばらくこの2つを除いた形で実装していきたいと思います。あと、RSS-14は特に調査も行っていませんので、これも除外。)
その他
まとまった解説のあるページ
チェックディジットの計算方法、Canonさん、キーエンス解説さんはまとまっていて参考になるときもあります。
バーコード読み取り後、作成前のデータからのつながり
CODE128などですと、読み取り前後でこのようなデータとのリンクがあるはずですので、これもまた参考になります。
とりあえず、1次元のバーコードのZXing.netについてはおおむねこんな感じでしょうか。