JAN コード/EANコードのバーコードをPython を使って作成する。無料でバーコードフォントのダウンロードが可能
20年前に作ったフォントが少し手直しが必要なため新たに作るようにしました
https://www.vector.co.jp/soft/data/writing/se475905.html
ソースコードを公開しています。数字なしのバーコードやバーコードの高さを変更できますので必要な場合はご自身で変更してください
JANコードの仕様書に基づいて、JANコードの構成と符号化のプロセスを簡単に説明します。
JANコードの仕様
JANコードの基本構造
JANコードは通常13桁で構成され、短縮バージョンは8桁です。13桁の場合、次のように分かれます。
- 最初の1桁: プレフィックス・キャラクタ(国や地域を示す)
- 次の6桁: メーカーコード
- その次の5桁: 商品コード
- 最後の1桁: チェックデジット(エラーチェック用)
現在は JAN コードの枯渇のため仕様が変更されています
レフトカードバーからライトガードバーまで(標準は幅31.35mm、高さ22.86mm)
例として「4901234567894」を使います。
4 | 901234 | 567894
パリティの概要
JANコードでは、バーコードの左側と右側で数字の表現が異なります。各数字は奇数パリティまたは偶数パリティによって表現されます。具体的には、奇数パリティでは黒いバー(1)の数が奇数、偶数パリティでは黒いバーの数が偶数になります。
- 左側(L側): 奇数パリティまたは偶数パリティを使用。
- 右側(R側): すべて偶数パリティを使用(L側の奇数パリティのビット反転)。
各数字の符号化パターンは以下の通りです。
数字ごとのパリティパターン(0~9)
JANコードの各数字は、7ビットのモジュールで表され、パリティに応じて異なるビットパターンになります。表を使って説明します。
1文字は7モジュールから構成され、1つの数字は幅の違う2本のバー(黒)と
2本のスペース(白)でできています。
例)□□□■■□■
数字 | 左側奇数パリティ (L-奇数) | 左側偶数パリティ (L-偶数) | 右側偶数パリティ (R-偶数) |
---|---|---|---|
0 | 0001101 | 0100111 | 1110010 |
1 | 0011001 | 0110011 | 1100110 |
2 | 0010011 | 0011011 | 1101100 |
3 | 0111101 | 0100001 | 1000010 |
4 | 0100011 | 0011101 | 1011100 |
5 | 0110001 | 0111001 | 1001110 |
6 | 0101111 | 0000101 | 1010000 |
7 | 0111011 | 0010001 | 1000100 |
8 | 0110111 | 0001001 | 1001000 |
9 | 0001011 | 0010111 | 1110100 |
左側と右側の違い
- 左側奇数パリティ(L側奇数)は、ビット列の中で黒いバー(1)の数が奇数となるようなパターンです。
- 左側偶数パリティ(L側偶数)は、黒いバーの数が偶数になるパターンです。
- 右側偶数パリティ(R側偶数)は、左側奇数パリティのビットを反転させたものです。
これにより、数字0から9の符号化が異なるパリティを使って表現され、バーコードの形式が決まります。
プリフィックス・キャラクタによるパリティの決定
JANコードの先頭1桁(プリフィックス・キャラクタ)は、左側の6桁の数字が奇数パリティか偶数パリティかを決定します。下記の表に従い、プリフィックスの数字に応じたパリティの組み合わせが適用されます。
1桁目 | 2桁目 | 3桁目 | 4桁目 | 5桁目 | 6桁目 | 7桁目 |
---|---|---|---|---|---|---|
0 | 奇 | 奇 | 奇 | 奇 | 奇 | 奇 |
1 | 奇 | 奇 | 偶 | 奇 | 偶 | 偶 |
2 | 奇 | 奇 | 偶 | 偶 | 奇 | 偶 |
3 | 奇 | 奇 | 偶 | 偶 | 偶 | 奇 |
4 | 奇 | 偶 | 奇 | 奇 | 偶 | 偶 |
5 | 奇 | 偶 | 偶 | 奇 | 奇 | 偶 |
6 | 奇 | 偶 | 偶 | 偶 | 奇 | 奇 |
7 | 奇 | 偶 | 奇 | 偶 | 奇 | 偶 |
8 | 奇 | 偶 | 奇 | 偶 | 偶 | 奇 |
9 | 奇 | 偶 | 偶 | 奇 | 偶 | 奇 |
例:プリフィックスが「4」の場合
「4」はパリティの組み合わせが「奇・偶・奇・奇・偶・偶」となるため、左側の6桁「901234」に適用すると、次のような符号化になります。
- 9: 奇数パリティ
0001011
- 0: 偶数パリティ
0100111
- 1: 奇数パリティ
0011001
- 2: 奇数パリティ
0010011
- 3: 偶数パリティ
0100001
- 4: 偶数パリティ
0011101
バーコードの完全な構造
JANコードには、レフトマージン、ガードバー、データバー、センターバー、ライトデータバー、チェックデジットバー、ライトガードバー、ライトマージンが含まれます。各部位のモジュール数は次の通りです。
- レフトマージン: 11モジュール以上
- レフトガードバー: 3モジュール(101)
- レフトデータバー: 42モジュール(6キャラクタ分)
- センターバー: 5モジュール(01010)
- ライトデータバー: 42モジュール(6キャラクタ分)
- チェックデジットバー: 7モジュール
- ライトガードバー: 3モジュール(101)
- ライトマージン: 7モジュール以上
符号化の例
例えば、JANコード「4901234567894」を符号化すると、次のようになります。
レフトデータバー
- 9: 奇数パリティ
0001011
- 0: 偶数パリティ
0100111
- 1: 奇数パリティ
0011001
- 2: 奇数パリティ
0010011
- 3: 偶数パリティ
0100001
- 4: 偶数パリティ
0011101
ライトデータバー
- 5: 偶数パリティ
1001110
- 6: 偶数パリティ
1101100
- 7: 偶数パリティ
1100110
- 8: 偶数パリティ
1011100
- 9: 偶数パリティ
1110100
- 4: 偶数パリティ
1011100
ガードバー、センターバー、マージン
- レフトガードバー:
101
- センターバー:
01010
- ライトガードバー:
101
最終出力
00000000000_101_000101101001110110111000110101100110110011_01010_100111011011001100110101110011100101000010_101_0000000
このフォントとバーコードの関係
各数字のパリティ符号化
以下の表は、0から9までの数字が奇数パリティ、偶数パリティ、および右側の偶数パリティでどのように符号化されるかを示しています。
数字 | 左側奇数パリティ | 左側偶数パリティ | 右側偶数パリティ |
---|---|---|---|
0 | 0001101 (0) | 0100111 (@) | 1110010 (P) |
1 | 0011001 (1) | 0110011 (A) | 1100110 (Q) |
2 | 0010011 (2) | 0011011 (B) | 1101100 (R) |
3 | 0111101 (3) | 0100001 (C) | 1000010 (S) |
4 | 0100011 (4) | 0011101 (D) | 1011100 (T) |
5 | 0110001 (5) | 0111001 (E) | 1001110 (U) |
6 | 0101111 (6) | 0000101 (F) | 1010000 (V) |
7 | 0111011 (7) | 0010001 (G) | 1000100 (W) |
8 | 0110111 (8) | 0001001 (H) | 1001000 (X) |
9 | 0001011 (9) | 0010111 (I) | 1110100 (Y) |
- 左側の奇数パリティは、黒いバーの数が奇数。
- 左側の偶数パリティは、黒いバーの数が偶数。
- 右側の偶数パリティは、左側奇数パリティのビット反転です。
例: プリフィックス「4」の場合
「4」は「奇偶奇奇偶偶」のパリティで符号化されます。例えば、左側の6桁が「901234」の場合、次のように符号化されます。
この符号化パターンを適用すると、901234
は次のようになります。
901234 -> 9@12CD
ここで、「@」は0の偶数パリティ、「C」は3の偶数パリティ、「D」は4の偶数パリティです。
バーコードの全体構造
JANコードのバーコードにはスタートコード、センターコード、ストップコードが含まれます。符号化されたデータは次のように表されます。
- スタートコード:
{
- 左側データ: 9@12CD
- センターコード:
|
- 右側データ: UVWXYT
- ストップコード:
}
これにより、バーコード表記は次のようになります。
{9@12CD|UVWXYT}
このフォントでは次のようにしています
レフトガードバー: 00000000000101
ライトガードバー:
0000000101
数字付きバーコードの表現
バーコードの先頭にあるスタートコードは1桁目のプリフィックス・キャラクタによって決まります。各プリフィックスに対応するコードは以下の通りです。
- 0 →
p
- 1 →
q
- 2 →
r
- 3 →
s
- 4 →
t
- 5 →
u
- 6 →
v
- 7 →
w
- 8 →
x
- 9 →
y
これにより、最終的なバーコード表記は次のようになります。
t9@12CD|UVWXYT}
プログラム
パターンファイルでバーコードを作るプログラム
このプログラムは1モジュール12ポイントで作っています
フォントの高さは1000ポイントです
import csv
import os
# 文字列を16進数に変換し、"0x" をつける
def string_to_hex(s):
hex_value = ''.join([format(ord(c), 'x') for c in s]) # 文字列をUTF-8バイト列の16進数に変換
return f"0x{hex_value}" # "0x"を先頭につけて返す
# CSVからデータを読み込み、指定のフォルダにSVGファイルを生成
def generate_svg_from_csv(csv_file_path, output_folder):
# フォルダが存在しない場合は作成する
if not os.path.exists(output_folder):
os.makedirs(output_folder)
# CSVファイルを読み込み
with open(csv_file_path, mode='r') as file:
reader = csv.reader(file)
for row in reader:
binary_string = row[0] # 1列目の文字列を取得
hex_value = string_to_hex(row[1]) # 2列目の文字列を16進数に変換
file_name = f"{hex_value}.svg" # 変換した16進数をファイル名にする
# SVGデータを生成
svg_data = generate_svg_from_string(binary_string)
# 出力ファイルのパスを作成
file_path = os.path.join(output_folder, file_name)
# SVGファイルとして保存
with open(file_path, 'w') as svg_file:
svg_file.write(svg_data)
# SVGデータを生成する関数
def generate_svg_from_string(binary_string, width=12, height=832):
if len(binary_string) != 7:
height+=24
# SVGのヘッダー部分
svg_header = '<?xml version="1.0" standalone="no"?>\n'
svg_open = '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 {} {}">\n'.format(len(binary_string) * width, 1024)
svg_close = '</svg>'
svg_path_open = ' <path fill="black"\n'
svg_path_d = 'd="'
# 文字列をループして「1」に対する黒の四角を作成
for index, char in enumerate(binary_string):
if char == '1':
x_position = index * width
svg_path_d += 'M{} 0v{}h{}v-{}h-{}z'.format(x_position, height, width, height, width)
# pathタグを閉じる
svg_path_d += '" />\n'
# すべてのパーツを結合してSVGデータを完成
svg_content = svg_header + svg_open + svg_path_open + svg_path_d + svg_close
return svg_content
# 実行例: CSVファイルを読み込み、指定フォルダにSVGファイルを生成
csv_file_path = 'input.csv' # CSVファイルのパス
output_folder = 'output_svgs' # SVGファイルを保存するフォルダ
generate_svg_from_csv(csv_file_path, output_folder)
パターンファイル
0001101,0
0100111,@
1110010,P
0011001,1
0110011,A
1100110,Q
0010011,2
0011011,B
1101100,R
0111101,3
0100001,C
1000010,S
0100011,4
0011101,D
1011100,T
0110001,5
0111001,E
1001110,U
0101111,6
0000101,F
1010000,V
0111011,7
0010001,G
1000100,W
0110111,8
0001001,H
1001000,X
0001011,9
0010111,I
1110100,Y
00000000000101,{
1010000000,}
01010,|
00000000000101,p
00000000000101,q
00000000000101,r
00000000000101,s
00000000000101,t
00000000000101,u
00000000000101,v
00000000000101,w
00000000000101,x
00000000000101,y
バーコード と数字の SVG ファイルを合体させる バッチファイル
echo e %*
::@pwsh -NoProfile -Command "& (Invoke-Expression -Command ('{' + (Get-Content %~f0 -Encoding Shift-JIS | Where-Object {$_.readcount -gt 9}| Out-String )+ '}'))" %*
::
@powershell -Command "& (Invoke-Expression -Command ('{' + (Get-Content %~f0 | Where-Object {$_.readcount -gt 9}| Out-String )+ '}'))" %*
timeout /t 5&goto:eof
# フォルダパスの設定
$sourceFolder1 = "D:\WinPython\notebooks\output_svgs"
$sourceFolder2 = "D:\data2\input_s"
$outputFolder = "Y:\input_svg"
# ソースフォルダ1のテキストファイルを取得
$files = Get-ChildItem -Path $sourceFolder1 -Filter "*.*"
# 各ファイルを処理
foreach ($file in $files) {
# ファイル名の取得
$fileName = $file.Name
# ソース1のファイルを読み込み、最後の行を削除
$filePath1 = Join-Path $sourceFolder1 $fileName
$content0 = Get-Content $filePath1
$content1 = Get-Content $filePath1
$content1 = $content1[0..($content1.Count - 2)] # 最後の行を削除
# ソース2の対応するファイルパスを設定
$filePath2 = Join-Path $sourceFolder2 $fileName
# ソース2のファイルが存在するか確認
if (Test-Path $filePath2) {
# ソース2のファイルを読み込み、5行目から最後まで取得
$content2 = Get-Content $filePath2
$content2 = $content2[4..($content2.Count - 1)] # 5行目から最後まで
# 両方のファイルの内容を結合
$combinedContent = $content1 + $content2
} else {
# ソース2が存在しない場合はソース1のみ使用
Write-Host "$fileName のソース2が見つかりませんでした。ソース1のみを使用します。"
$combinedContent = $content0
}
# 出力フォルダに新しいファイルを保存
$outputFilePath = Join-Path $outputFolder $fileName
$combinedContent | Set-Content $outputFilePath
}
Write-Host "処理が完了しました。ファイルは $outputFolder に保存されました。"
ディスカッション
コメント一覧
まだ、コメントがありません