[Javascript + CSS] JAN-13のコード番号からバーコードを生成し表示する（１）～仕様の確認からロジックアウトラインの構築

# はじめに
プレーンなJavascript（Vanilla.js）による、コード番号からバーコードを生成するためのロジック構築について、前半と後半の２回に分けて紹介します。一般消費者では、恐らく一番目にすることが多い、**JAN-13** に限定し、モバイル端末等バーコードリーダーにて認識可能なバーコード表示を目的とします。

今回は前半ということで、**仕様の確認からロジックアウトラインの構築**までとなります。

バーコードの表示方法については印刷目的ではないことと、 [Canvasを使用したSVG版](https://qiita.com/Dolphin_0809/items/ac087aadcc43d15a01e2) は既に存在し、参考にもさせていただいているため、`CSS` による表示を選択しています。かなり泥臭く決してスマートとは言えない処理内容となってしまうのですが、ロジックとしては単純でわかりやすいかと思います。

なお、JANコードについての歴史や成り立ちなどの基本的な情報は割愛し、表示及び生成に必要な仕様情報のみをまとめています。また、当方ではjQueryは使用しませんので、ネットで散見されるライブラリについても一切触れません。

::: note
JANコードの公式な情報を確認したい方はこちらへ→[JISX0507:2004 バーコードシンボル－ＥＡＮ／ＵＰＣ－基本仕様](https://kikakurui.com/x0/X0507-2004-01.html)
:::

# 仕様を理解する
ロジック構築の前に、JANコードの生成及び表示にかかる要件や仕様などを理解しておく必要があります。まずは座学、ということで、以下、JANコードの仕様をまとめました。

## 理解していないと話が進まない単位について
最低限、以下の２点は理解しているものとして話を進めていきます。

- **キャラクタ**：JANを構成する数字１文字のこと
- **モジュール**：バーコードを示すための最小構成単位のこと（白または黒の１本のバー）

## コードのブロック構造
以下の７つのブロックによって構成されます。

![JAN-13コードのブロック構造](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1111613/6afc2a4e-1292-0952-78b1-63bc234c685a.png "図01:JAN-13コードのブロック構造")

1. レフトクワイエットゾーン：左余白（１１モジュール以上）
2. レフトガードバー：コード開始区切り
3. レフトデータバー：左側６キャラクタ
4. センターガードバー：中央区切り
5. ライトデータバー：右側６キャラクタ
6. ライトガードバー：コード終了区切り
7. ライトクワイエットゾーン：右側余白（７モジュール以上）

## キャラクタのモジュール構造
JANコードは１キャラクタにつき７つのモジュールを使用して表現します。モジュール構造は、白黒白黒、もしくは黒白黒白という **４本のバーによる交互パターン** になっている必要があります。（それぞれの太さのパターンバリエーションでキャラクタを識別します）

::: note
モジュールの色調については、必ずしも白と黒でなければいけないというものではありません。本稿では印刷用のJANコードを生成することが目的ではないため深掘りはいたしませんが、興味がある方はこちらを参照ください→ [バーコードの印字方法 | キーエンス](https://www.keyence.co.jp/ss/products/autoid/codereader/principles_printer.jsp)
:::

## モジュールパターン
１キャラクタにつき７モジュールで表現する、と言うのは先述の通りです。キャラクタごとに下表の通り１と０の７桁のビット文字列でパターンが定義されています。

それぞれ１が黒、０が白で表現され、また、１キャラクタにつき **ナンバーセット** ごと、３つのモジュールパターンが定義されています。

::: note
**ナンバーセット** については **そういったグループ分けがある** 程度の認識で問題ないと思います。
:::

■表１：キャラクタごとのモジュールパターン
|キャラクタ|ナンバーセットＡ|ナンバーセットＢ|ナンバーセットＣ|
|:--:|:--:|:--:|:--:|
|０|0001101|0100111|1110010|
|１|0011001|0110011|1100110|
|２|0010011|0011011|1101100|
|３|0111101|0100001|1000010|
|４|0100011|0011101|1011100|
|５|0110001|0111001|1001110|
|６|0101111|0000101|1010000|
|７|0111011|0010001|1000100|
|８|0110111|0001001|1001000|
|９|0001011|0010111|1110100|

## **奇数パリティ**と**偶数パリティ**
パターンの構成（７モジュール）において、１の数が奇数のものを**奇数パリティ** （ナンバーセットＡ）、偶数のものを **偶数パリティ** （ナンバーセットＢ）と呼びます。

上表において、ナンバーセットＣはナンバーセットＡをビット反転したものとなるため、**偶数パリティ** となります。

パターン及び **奇数パリティ**、**偶数パリティ** については以下がわかりやすいでしょう。

https://www.a-poc.co.jp/howto/howto_words_barcode-JAN.html

## １３桁のキャラクタそれぞれの役割について

![１３桁のキャラクタそれぞれの役割](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1111613/963c66ec-d20f-b45b-caef-dd0723dfa3f6.png "図02:１３桁のキャラクタそれぞれの役割")

1. **プレフィックスキャラクタ**：最初の１桁
2. **左データキャラクタ**：２～７桁目までの６キャラクタ
3. **右データキャラクタ**：８～１２桁目までの５キャラクタ
4. **チェックデジット**：最終桁の１キャラクタ（後述のモジュラス１０ウェイト３という計算式で算出される）

実は、バーコードそのものにはプレフィックスキャラクタのモジュールパターンは含まれていません。バーコードリーダー等で読み込んだ際、左データキャラクタのナンバーセットの並びを解析、プレフィックスキャラクタの数字を決定、出力データとして付加する、というハード側の仕様があります。

つまり、コード番号からJAN-13を生成しようとすると、プレフィックスキャラクタから左データキャラクタのナンバーセットパターンを参照、キャラクタごとのナンバーセットを決定、という逆の手順を踏む必要があります。

そのために必要なプレフィックスキャラクタとナンバーセットの並びを定義したものが以下の表となります。（表中ＡとＢはそれぞれナンバーセットを表します）

■表２：プレフィックスキャラクタごとのモジュールパターン定義
|プレフィックスキャラクタ|パターン構成|
|:----------------------------------:|:----------------:|
|０|AAAAAA|
|１|AABABB|
|２|AABBAB|
|３|AABBBA|
|４|ABAABB|
|５|ABBAAB|
|６|ABBBAA|
|７|ABABAB|
|８|ABABBA|
|９|ABBABA|

### プレフィックスキャラクタから左データキャラクタのナンバーセット決定プロセス
#### 具体例）4912345678904の場合
上記の場合、プレフィックスキャラクタが `４`、左データキャラクタが `９１２３４５` となります。表２より、左データキャラクタの構成は `ABAABB` となり、キャラクタごとのナンバーセットが決定されます。表１より、キャラクタごとのナンバーセットに対応するモジュールパターンが決定されます。

- 9 → ナンバーセットＡ → 0001011
- 1 → ナンバーセットＢ → 0110011
- 2 → ナンバーセットＡ → 0010011
- 3 → ナンバーセットＡ → 0111101
- 4 → ナンバーセットＢ → 0011101
- 5 → ナンバーセットＢ → 0111001

::: note
右データキャラクタはすべてナンバーセットＣ
:::

### 補足：**GS1事業者コード** と **商品アイテムコード**
画面表示には直接関係ありませんが、チェックデジット以外のキャラクタには、**GS1事業者コード（JAN企業コード）** と **商品アイテムコード** という別の意味も含まれています。

> 先頭の7桁（9桁）の「JAN企業コード」（メーカーコード）は2012年に「GS1事業者コード」に改称されました。
> 
> 従来、先頭の2桁が国コードで、45と49が日本という意味でしたが、現在は先頭3桁450～459、490～499が日本の事業者、という意味になります（参考：GS1 General Specifications V17）
> [JANコードの詳細](https://www.a-poc.co.jp/howto/howto_words_barcode-JAN.html)より

## モジュラス１０ウェイト３
後回しになりましたが、チェックデジットの計算式となります。その計算プロセスが以下となります。

1. チェックデジット以外の最下位桁から見て奇数桁と偶数桁に分けてそれぞれ合計する
2. 奇数桁の合計を３倍したものと偶数桁の合計をさらに合計する
3. １０から合計値の１の位の値を減じる
4. 3.の値がチェックデジットとなるが、合計値の１の位が０なら０となる

### 具体例）491234567890の場合

1. 奇数桁合計：9+2+4+6+8+0=29、偶数桁合計：4+1+3+5+7+9=29
2. 奇数桁合計×３+偶数桁合計：87+29=116
3. 10-6=4
4. チェックデジット：4

## 符号化プロセス
コード番号はプレフィックスキャラクタを除き、左右の余白、各ガードバーを含めて０と１のビット文字列へ変換します。なお、余白と各ガードバーのパターンは以下のように定義されています。

- 余白（１モジュール）：0
- 左右ガードバー（３モジュール）：101
- センターガードバー（５モジュール）：01010

先程の具体例に沿って符号化すると以下のようになります。

1. レフトクワイエットゾーン：00000000000
2. レフトガードバー：101
3. レフトデータバー：（９１２３４５）0001011-0110011-0010011-0111101-0011101-0111001
4. センターガードバー：01010
5. ライトデータバー：（６７８９０４）1010000-1000100-1001000-1110100-1110010-1011100
6. ライトガードバー：101
7. ライトクワイエットゾーン：0000000

便宜上、キャラクタごとの区切りとしてハイフンを付加していますが、符号化の結果、１１３桁（１１３モジュール）のビット文字列となります。

---

# バーコード生成ロジックの要件まとめ
## 挙動概要
- ブラウザベースとし、JANコード入力後ボタンクリックでバーコード表示
- エラーチェックは正規表現によるパターン照合とチェックデジットの照合のみ
- リセットボタンクリックでバーコード及びエラー表示の消去

## 表示
印刷用途としての利用ではないので忠実に再現する必要もないのですが、容易に実装できる範囲でこだわってみました。（反響があればさらに追求するかもしれません）

### 色調
白と黒の２値とします。

### サイズ
印刷前提での基準では、モジュール幅は0.33mmが基本となり、基本寸法の0.8 ～ 2.0倍まで拡大、縮小が可能とされています。

画面表示時においては、モジュール幅１pxとした基本寸法（113px x 70pxとします）での表示を基準とし、初期表示サイズ、縮小・拡大はデバイスに依存するようにしておきます。

### フォント
> 目視可能数字には，JIS X 9001で規定するOCR-Bなどの明確に読み取れるフォントを使用する。このフォントは，よく用いられる書体として参照しており，機械読取り又は検証することは意図していない。読みやすい表記形式であれば，適当なこれ以外の書体及び／又は文字サイズを用いてもよい。
> [JISX0507:2004 バーコードシンボル－ＥＡＮ／ＵＰＣ－基本仕様](https://kikakurui.com/x0/X0507-2004-01.html)より

CDNにてフリーのOCR-Bフォントが使用可能なので、利用させていただくことにしました。

https://www.cdnfonts.com/ocr-b-10-bt.font

## ロジック
1. JANコードを受け取りエラーチェック
    - 正規表現によるパターンチェック
    - モジュラス１０ウェイト３によるチェックデジット照合
2. JANコードの符号化
    - 左データキャラクタの符号化
    - 右データキャラクタの符号化
3. 桁数分のモジュール表示用DOMエレメントを追加
    - モジュールごとに奇数パリティ、偶数パリティ用のクラスを付加

# 最後に
JANコードやバーコード周辺の技術情報などについて興味がある方は以下を参考にしてみてください。これらがまとめられたPDF資料が大変参考になると思います。

https://www.keyence.co.jp/ss/products/autoid/codereader/

次回はサンプルコードとロジックの解説を予定しています。

誰かのお役に立てたなら幸いです。

# [参考・引用]
- [JISX0507:2004 バーコードシンボル－ＥＡＮ／ＵＰＣ－基本仕様](https://kikakurui.com/x0/X0507-2004-01.html)
- [JANバーコードの仕様](https://qiita.com/Dolphin_0809/items/ac087aadcc43d15a01e2)
- [バーコード講座 | キーエンス](https://www.keyence.co.jp/ss/products/autoid/codereader/)
- [JANコードの詳細｜株式会社エイポック](https://www.a-poc.co.jp/howto/howto_words_barcode-JAN.html)
- [OCR-B 10 BT Font Family Download for Desktop & WebFont | CDNFonts.com](https://www.cdnfonts.com/ocr-b-10-bt.font)