JIS X 0504 (ISO/IEC 15417) 規格のバーコード(HTMLとGIF画像)を JavaScript で生成します。
実行画面とソース
ソース(HTML+JavaScript)
動作確認した環境
macOS 12.0.1
Safari: 15.1
Microsoft Edge: 96.0.1054.43
Google Chrome: 96.0.4664.93
FireFox: 95.0
Opera: 82.0.4227.23
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" >
<title>バーコード(コード 128):JIS X 0504 (ISO/IEC 15417)</title>
</head>
<body>
<h3>JIS X 0504 (ISO/IEC 15417) 規格</h3>
<hr>
<p>バーコード(コード 128)をローカル(JavaScript)で生成します。</p>
<p>
<input
type="text"
id="gbcinp" size="50"
placeholder="ここに半角文字を入力"
style="font-size: large;"
oninput="genBarCode128()"
/>
</p>
<div>HTMLによるバーコード</div><blockquote id="gbcout"></blockquote>
<div>GIF画像によるバーコード</div>
<blockquote>
<table style="border-collaspe: collaspe; border-spacing: 0;">
<tr>
<td id="gbcimg" style="border: solid 1px; margin: 0; padding: 0px 8px; font-size: xx-small;"></td>
<td style="font-size: 12px; padding: 36px 1px;"> </td>
</tr>
</table>
</blockquote>
<hr>
<table id="chartab" style="border: solid 1px; border-collaspe: collaspe; border-spacing: 0;"></table>
<script type="text/javascript">
<!--
function code128CharSet() {
let tab = document.getElementById("chartab");
if (true) {
let tr = document.createElement('tr');
let th = document.createElement('th');
th.setAttribute("colspan", "16");
th.style.setProperty('border', 'solid 1px');
th.style.setProperty('padding', '5px 10px');
th.innerText = "使用可能な文字";
tr.appendChild(th);
tab.appendChild(tr);
}
for (let y = 2; y < 16; y++) {
let tr = document.createElement('tr');
for (let x = 0; x < 16; x++) {
let td = document.createElement('td');
td.style.setProperty('border', 'solid 1px');
td.style.setProperty('padding', '5px 10px');
td.innerText = String.fromCharCode(y * 16 + x);
tr.appendChild(td);
}
tab.appendChild(tr);
}
}
code128CharSet();
// -->
</script>
<script type="text/javascript">
<!--
/* **************************************** */
class GenBarCode128 {
static CodeSet = { Shift: 98 };
static CodeSetA = { Flag: 1, Start: 103, Next: 101, FNC4: 101 }
static CodeSetB = { Flag: 2, Start: 104, Next: 100, FNC4: 100 }
static CodeSetC = { Flag: 4, Start: 105, Next: 99 }
static CodeSetX = { Flag: 8 }
static CodeSetAB = { Flag: 3 }
static CodeSetABC = { Flag: 7 }
static CodeSetFlagTable = [
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 3, 3, 3, 3,
+3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
]
static CodePatternTable = [
411, 435, 819, 201, 393, 401, 153, 281, 305, 147, 275, 291, 461, 473, 921, 413,
441, 825, 627, 467, 915, 315, 371, 951, 407, 423, 807, 311, 359, 615, 219, 795,
867, 197, 209, 785, 141, 177, 561, 139, 163, 547, 237, 909, 945, 221, 797, 881,
887, 907, 931, 187, 571, 955, 215, 791, 839, 183, 567, 711, 759, 531, 655, 101,
389, 105, 777, 417, 801, 77, 269, 89, 537, 353, 609, 579, 83, 751, 323, 753,
485, 489, 969, 317, 377, 633, 303, 335, 591, 987, 891, 879, 245, 965, 977, 189,
573, 175, 559, 989, 957, 983, 943, 267, 75, 459,
]
static StopPattern = [1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1]
static QuietPattern = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
static byteToCodeSetA(b) { return (b < 32) ? (b + 64) : (b - 32); }
static byteToCodeSetB(b) { return (b - 32); }
static byteToCodeSetC(b) { return (b - 48); }
static FlagToCodeSet = [
undefined,
{ CodeSet: GenBarCode128.CodeSetA, byteToCodeSet: GenBarCode128.byteToCodeSetA },
{ CodeSet: GenBarCode128.CodeSetB, byteToCodeSet: GenBarCode128.byteToCodeSetB },
{ CodeSet: GenBarCode128.CodeSetB, byteToCodeSet: GenBarCode128.byteToCodeSetB },
{ CodeSet: GenBarCode128.CodeSetC, byteToCodeSet: GenBarCode128.byteToCodeSetC },
]
constructor() {
this.S = GenBarCode128;
this.useQuietZone = true;
this.useCodeSetC = true;
this.data = [];
this.charData = [];
this.codeData = [];
}
buildCodeData(data) {
this.data = data;
this.makeCharData();
this.checkCodeSetC();
this.makeCodeSetSpan();
this.updateCodeSet();
this.makeFnc4Span();
this.updateFnc4Code();
this.makeCodeData();
}
makeCharData() {
const S = this.S;
const flagA = S.CodeSetA.Flag;
const flagB = S.CodeSetB.Flag;
const flagC = S.CodeSetC.Flag;
const flagX = S.CodeSetX.Flag;
const table = S.CodeSetFlagTable;
let cdata = [];
for (let b of this.data) {
let flag = table[b];
cdata.push({
flag: flag,
aflag: ((flag & flagA) != 0),
bflag: ((flag & flagB) != 0),
cflag: ((flag & flagC) != 0),
xflag: ((flag & flagX) != 0),
data: (b & 0x7f),
code: -1,
shift: false,
next: false,
xshift: false,
xenter: false,
xleave: false,
});
}
this.charData = cdata;
}
checkCodeSetC() {
const S = this.S;
const flagC = S.CodeSetC.Flag;
let cdata = this.charData;
let dilen = cdata.length;
if (!this.useCodeSetC) {
this.clearCodeSetC(0, dilen);
return;
}
let cspan = [];
let cindex = 0;
let pf = false;
for (let index = 0; index < dilen; index++) {
let di = cdata[index];
let nf = di.cflag;
if (pf != nf) {
if (pf)
cspan.push({ start: cindex, end: index });
cindex = index;
pf = nf;
}
}
if (pf)
cspan.push({ start: cindex, end: dilen });
for (let span of cspan) {
let sc = span.start;
let ec = span.end;
let nc = ec - sc;
let bt = (sc == 0);
let be = (ec == dilen);
let odd = ((nc & 1) != 0);
let amove = false;
let pmove = false;
let nmove = false;
if (bt && be) {
amove = ((nc == 1) || (nc == 3));
nmove = odd;
} else {
amove = (nc < ((bt || be) ? 4 : 6));
if (be)
pmove = odd;
else
nmove = odd;
}
let mp = {
clear: { start: -1, end: -1 },
set: { start: -1, end: -1 }
};
if (amove)
mp.clear = { start: sc, end: ec };
else if (pmove)
mp = {
clear: { start: sc, end: sc+1 },
set: { start: sc+1, end: ec }
};
else if (nmove)
mp = {
set: { start: sc, end: ec-1 },
clear: { start: ec-1, end: ec }
};
else
mp.set = { start: sc, end: ec };
this.clearCodeSetC(mp.clear.start, mp.clear.end);
this.setCodeSetC(mp.set.start, mp.set.end);
}
}
clearCodeSetC(start, end) {
for (let index = start; index < end; index++)
this.disableCodeSetC(this.charData[index]);
}
setCodeSetC(start, end) {
for (let index = start; index < end; index++)
this.enableCodeSetC(this.charData[index]);
}
disableCodeSetC(di) {
if (!di.cflag) return;
di.flag -= this.S.CodeSetC.Flag;
di.cflag = false;
}
enableCodeSetC(di) {
if (!di.cflag) return;
di.flag = this.S.CodeSetC.Flag;
di.aflag = false;
di.bflag = false;
}
makeCodeSetSpan() {
const S = this.S;
const flagA = S.CodeSetA.Flag;
const flagB = S.CodeSetB.Flag;
const flagC = S.CodeSetC.Flag;
const flagAB = S.CodeSetAB.Flag;
const flagABC = S.CodeSetABC.Flag;
let cdata = this.charData;
let dilen = cdata.length;
if (dilen == 0) return;
let addspan = function(l, f, s, e) {
if (f == flagAB)
f = flagB;
let index = l.length;
l.push({
index: index,
flag: f,
shift: false,
next: false,
start: s,
end: e,
});
}
let cspan = [];
let pindex = 0;
let pflag = flagABC;
for (let index = 0; index < dilen; index++) {
let di = cdata[index];
let nflag = di.flag & flagABC;
let mflag = pflag & nflag;
if (mflag != 0) {
pflag = mflag;
continue;
}
addspan(cspan, pflag, pindex, index);
pindex = index;
pflag = nflag;
}
if (pindex != dilen)
addspan(cspan, pflag, pindex, dilen);
let csplen = cspan.length;
for (let index = 1; index < csplen; index++) {
let psp = cspan[index - 1];
let nsp = cspan[index];
if ((psp.flag == flagC) ||
(nsp.flag == flagC)) {
nsp.next = true;
continue;
}
if (index == (csplen - 1)) {
nsp.next = !psp.shift;
continue;
}
let shift = ((nsp.end - nsp.start) < 3);
nsp.shift = shift;
nsp.next = !shift;
}
this.cspan = cspan;
}
updateCodeSet() {
let cdata = this.charData;
let ftable = this.S.FlagToCodeSet;
for (let span of this.cspan) {
let top = span.start;
let end = span.end;
let flag = span.flag;
let shift = span.shift;
let b2cs = ftable[flag].byteToCodeSet;
cdata[top].next = span.next;
for (let i = top; i < end; i++) {
let di = cdata[i];
di.flag = flag;
di.shift = shift;
di.code = b2cs(di.data);
}
}
}
makeFnc4Span() {
let cdata = this.charData;
let dilen = cdata.length;
if (dilen == 0) return;
let addspan = function(l, f, s, e) {
l.push({
flag: f,
start: s,
end: e,
});
}
let xspan = [];
let pindex = 0;
let pflag = false;
for (let index = 0; index < dilen; index++) {
let di = cdata[index];
let nflag = di.xflag;
if (pflag == nflag)
continue;
addspan(xspan, pflag, pindex, index);
pindex = index;
pflag = nflag;
}
if (pindex != dilen)
addspan(xspan, pflag, pindex, dilen);
this.xspan = xspan;
}
updateFnc4Code() {
let cdata = this.charData;
let dilen = cdata.length;
for (let span of this.xspan) {
if (!span.flag)
continue;
let ss = span.start;
let es = span.end;
let ep = (es == dilen);
let ns = es - ss;
let nc = (ep ? 2 : 4);
if (ns < nc) {
for (let dp = ss; dp < es; dp++)
cdata[dp].xshift = true;
continue;
}
cdata[ss].xenter = true;
if (!ep)
cdata[es].xleave = true;
}
}
makeCodeData() {
let S = this.S;
let Shift = S.CodeSet.Shift;
let ftable = this.S.FlagToCodeSet;
let cdata = this.charData;
if (cdata.length == 0) {
this.codeData = [S.CodeSetA.Start];
return;
}
let pdi = cdata[0];
let pcs = ftable[pdi.flag].CodeSet;
let code = [pcs.Start];
let cskip = false;
let clast = 0;
for (let di of cdata) {
let cs = ftable[di.flag].CodeSet;
let xleave = true;
if (di.xleave && di.cflag) {
code.push(pcs.FNC4);
code.push(pcs.FNC4);
xleave = false;
}
if (di.next)
code.push(cs.Next);
if (di.xenter || (xleave && di.xleave)) {
code.push(cs.FNC4);
code.push(cs.FNC4);
}
if (di.xshift)
code.push(cs.FNC4);
if (di.shift)
code.push(Shift);
if (!di.cflag)
code.push(di.code);
else {
if (cskip)
code.push(clast + di.code);
else
clast = di.code * 10;
cskip = !cskip;
}
pdi = di;
pcs = cs;
}
this.codeData = code;
}
addSymbolCheck() {
let code = this.codeData;
let clen = code.length;
let sum = code[0];
for (let index = 1; index < clen; index++)
sum += code[index] * index;
code.push(sum % 103);
}
buildModule() {
let S = this.S;
let table = S.CodePatternTable;
let r = [];
for (let code of this.codeData) {
let bin = table[code];
for (let b = 0; b < 11; b++, bin >>= 1)
r.push(bin & 1);
}
r = r.concat(S.StopPattern);
if (this.useQuietZone) {
let q = S.QuietPattern;
r = q.concat(r, q);
}
return r;
}
}
class BarCode128FromString extends GenBarCode128 {
static toByteList(s) {
let bs = [];
for (let index = 0; index < s.length; index++) {
let c = s.charCodeAt(index);
if ((c < 0) || (c >= 0x100))
throw ('unknown char: ' + c)
bs.push(c);
}
return bs;
}
constructor(s, useQuietZone=true, useCodeSetC=true) {
super();
let bs = BarCode128FromString.toByteList(s);
this.useQuietZone = useQuietZone;
this.useCodeSetC = useCodeSetC;
this.buildCodeData(bs);
this.addSymbolCheck();
}
}
/* **************************************** */
class GenBarCode128GIF {
constructor(barcode, scale=2, height=20, padding={ top: 10, bottom: 10, left: 10, right:10 }) {
let sbarcode = [];
for (let b of barcode)
for (let n = 0; n < scale; n++)
sbarcode.push(b);
let sheight = height * scale;
let spadding = {
top: padding.top * scale,
bottom: padding.bottom * scale,
left: padding.left * scale,
right: padding.right * scale,
}
let width = padding.left + barcode.length + padding.right;
let swidth = width * scale;
let space = new Array(swidth);
for (let x = 0; x < swidth; x++)
space[x] = 0;
let raster = space.slice(0, spadding.left).concat(sbarcode, space.slice(0, spadding.right))
let data = [];
for (let y = 0; y < spadding.top; y++)
data = data.concat(space);
for (let y = 0; y < sheight; y++)
data = data.concat(raster);
for (let y = 0; y < spadding.bottom; y++)
data = data.concat(space);
sheight += spadding.top + spadding.bottom;
this.S = GenBarCode128GIF;
this.width = swidth;
this.height = sheight;
this.source = data;
this.binary = [
0x47, 0x49, 0x46, // Signature
0x38, 0x39, 0x61, // Version89a
// Logical Screen Descriptor
(swidth & 0xff), ((swidth >> 8) & 0xff),
(sheight & 0xff),((sheight >> 8) & 0xff),
0x91, 3, 49,
// Global Color Table
0xff, 0xff, 0xff,
0x00, 0x00, 0x00,
0xff, 0xff, 0xff,
0xff, 0xff, 0xff,
// Image Descriptor
0x2c,
0x00, 0x00,
0x00, 0x00,
(swidth & 0xff), ((swidth >> 8) & 0xff),
(sheight & 0xff),((sheight >> 8) & 0xff),
0,
];
this.tableBasedImage();
// Trailer
this.binary.push(0x3b);
}
tableBasedImage() {
this.buffer = [];
this.bs_pos = 0;
this.table = [];
this.code_max = (1 << 12) - 1;
let tree = [];
let tree_size = this.code_max + 1;
for (let i = 0; i < tree_size; i++)
tree.push({
code: i,
next: -1,
down: -1,
data: 0,
});
this.tree = tree;
this.bits_init = 3;
this.encodeImage();
this.binary.push(this.bits_init);
this.pushSubBlock(this.buffer)
}
pushSubBlock(data) {
let binary = this.binary;
let buffer = this.buffer;
let offset = 0;
let size = buffer.length;
while (size > 0) {
let count = size;
if (count > 255) count = 255;
binary = binary.concat([count], buffer.slice(offset, offset + count));
offset += count;
size -= count;
}
binary.push(0);
this.binary = binary;
}
encodeImage() {
let tree = this.tree;
let bits_init = this.bits_init;
let bits_curr = bits_init + 1;
let code_max = this.code_max;
let code_clear = (1 << bits_init);
let code_end = code_clear + 1;
let code_curr = code_end;
let code_step = (1 << bits_curr);
let source = this.source;
this.bs_pos = 0;
this.buffer = [];
this.bsWrite(code_clear, bits_curr);
if (source.length == 0) {
this.bsWrite(code_end, bits_curr);
return;
}
let s_curr = source.values();
let s_data = s_curr.next();
for (;;) {
let c_curr = s_data.value;
let data = c_curr;
lzw4: for (;;) {
s_data = s_curr.next();
if (s_data.done) {
this.bsWrite(c_curr, bits_curr);
this.bsWrite(code_end, bits_curr);
return;
}
data = s_data.value;
let next = tree[c_curr].down;
for (;;) {
if (next < 0)
break lzw4;
let ntree = tree[next];
if (data == ntree.data)
break;
next = ntree.next;
}
c_curr = next;
}
this.bsWrite(c_curr, bits_curr);
{
let node = tree[c_curr];
let next = tree[++code_curr];
next.code = code_curr;
next.next = node.down;
next.down = -1;
next.data = data;
node.down = code_curr;
}
if (code_curr < code_step)
continue;
if (code_curr < code_max) {
bits_curr++
code_step <<= 1;
if (code_step < code_max)
continue;
code_step = code_max;
continue;
}
this.bsWrite(code_clear, bits_curr);
this.clearTree();
bits_curr = bits_init + 1;
code_curr = code_end;
code_step = (1 << bits_curr);
}
}
clearTree() {
let tree = this.tree;
let tsz = (1 << this.bits_init);
for (let i = 0; i < tsz; i++) {
let node = tree[i];
node.code = i;
node.next = -1;
node.down = -1;
node.data = 0;
}
}
bsWrite(data, bits) {
let buffer = this.buffer;
let bpos = this.bs_pos;
let idxs = (bpos >> 3);
let idxe = ((bpos + bits - 1) >> 3);
data <<= (bpos & 7);
if (idxs < buffer.length) {
buffer[idxs] |= (data & 0xff);
data >>= 8;
idxs++;
}
while (idxs <= idxe) {
buffer.push(data & 0xff);
data >>= 8;
idxs++;
}
this.bs_pos = bpos + bits;
}
buildBase64() {
let table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
let padding = ['', '==', '='];
let data = this.binary;
let dlen = data.length;
let drem = dlen % 3;
let dsiz = dlen - drem;
let b0 = 0;
let b1 = 0;
let b2 = 0;
let d = 0;
let s = '';
let i = 0;
for (i = 0; i < dsiz;) {
b0 = data[i++];
b1 = data[i++];
b2 = data[i++];
d = (b0 << 16) | (b1 << 8) | b2;
s += table[(d >> 18) & 0x3f];
s += table[(d >> 12) & 0x3f];
s += table[(d >> 6) & 0x3f];
s += table[d & 0x3f];
}
if (drem == 0)
return s;
b0 = data[i++];
if (drem == 1)
b1 = data[i++];
d = (b0 << 16) | (b1 << 8);
s += table[(d >> 18) & 0x3f];
s += table[(d >> 12) & 0x3f];
if (drem == 2)
s += table[(d >> 6) & 0x3f];
return (s + padding[drem]);
}
}
/* **************************************** */
function createHTMLBarCode128(p) {
const tdcolor = ['white', 'black'];
const priority = 'important';
let table = document.createElement('table');
table.style.setProperty('background-color', 'white', priority);
table.style.setProperty('border-collaspe', 'collaspe', priority);
table.style.setProperty('border-spacing', '0', priority);
table.style.setProperty('margin', '0', priority);
table.style.setProperty('border', 'solid 1px', priority);
table.style.setProperty('padding', '32px', priority);
let tr = document.createElement('tr');
for (let b of p) {
let td = document.createElement('td');
td.style.setProperty('background-color', tdcolor[b], priority);
td.style.setProperty('color', tdcolor[b], priority);
td.style.setProperty('font-size', 'xx-small', priority);
td.style.setProperty('margin', '0', priority);
td.style.setProperty('border', '0', priority);
td.style.setProperty('padding', '20px 1px', priority);
tr.appendChild(td);
}
table.appendChild(tr);
return table;
}
/* **************************************** */
function genBarCode128() {
let clearChild = function(e) {
while (e.firstChild)
e.removeChild(e.firstChild);
}
let setError = function(e, msg) {
const priority = 'important';
let table = createHTMLBarCode128([]);
let tr = table.firstChild;
let td = document.createElement('td');
td.style.setProperty('font-size', '12px', priority);
td.style.setProperty('margin', '0', priority);
td.style.setProperty('border', '0', priority);
td.style.setProperty('padding', '11px 1px', priority);
td.innerText = msg;
tr.appendChild(td);
clearChild(e);
e.appendChild(table);
}
let setPattern = function(e, p) {
let t = createHTMLBarCode128(p);
clearChild(e);
e.appendChild(t);
}
let clrImage = function(e, msg) {
const priority = 'important';
let span = document.createElement('span');
span.style.setProperty('font-size', '12px', priority);
span.style.setProperty('padding', '0px 26px', priority);
span.innerText = msg;
clearChild(e);
e.appendChild(span);
}
let setImage = function(e, p) {
const priority = 'important';
let bcimage = new GenBarCode128GIF(pattern);
let b64s = bcimage.buildBase64();
let img = document.createElement('img');
img.setAttribute('src', 'data:image/gif;charset=utf-8;base64,' + b64s);
img.style.setProperty('margin', '0', priority);
img.style.setProperty('padding', '0px 4px', priority);
img.style.setProperty('image-rendering', 'pixelated');
clearChild(e);
e.appendChild(img);
}
let setMessage = function(dom, img, msg) {
setError(dom, msg);
clrImage(img, msg);
}
let inp = document.getElementById("gbcinp");
let out = document.getElementById("gbcout");
let img = document.getElementById("gbcimg");
let str = inp.value;
if (str.length == 0) {
setMessage(out, img, '(待機中)');
return;
}
let pattern = [];
try {
let barcode = new BarCode128FromString(str);
pattern = barcode.buildModule();
setPattern(out, pattern);
setImage(img, pattern);
} catch (e) {
setMessage(out, img, '(エラー:非対応の文字が使用されています)');
}
}
genBarCode128();
/* **************************************** */
// -->
</script>
</body>
</html>
旧バージョンのソース(HTML+JavaScript)
動作確認した環境
macOS 12.0.1
Safari: バージョン15.1 (17612.2.9.1.20)
Microsoft Edge: バージョン 96.0.1054.43
Google Chrome: 96.0.4664.55
FireFox: 95.0
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" >
<title>バーコード(コード 128):JIS X 0504 (ISO/IEC 15417)</title>
</head>
<body>
<h3>JIS X 0504 (ISO/IEC 15417) 規格(コード 128)のバーコード生成</h3>
<p>バーコードをローカル(JavaScript)で生成します。</p>
<p>
<input type="button" value="生成" onclick="genBarCode();" />
<input type="text" id="gbcinp" size="50" placeholder="ここに半角文字を入力" style="font-size: large;" />
</p>
<p style="font-size: small;">ここで対応している文字は半角(7ビット文字)のみです。</p>
<p style="font-size: small;">注意:コードセットC(数値二桁)による短縮は非対応です。</p>
<p id="gbcout">(待機中)</p>
<script type="text/javascript">
<!--
/* **************************************** */
const BARCODE_CSET_A2C = 99;
const BARCODE_CSET_B2C = 99;
const BARCODE_CSET_A2B = 100;
const BARCODE_CSET_B2A = 101;
const BARCODE_CSET_C2B = 100;
const BARCODE_CSET_C2A = 101;
const BARCODE_START_A = 103;
const BARCODE_START_B = 104;
const BARCODE_START_C = 105;
const BARCODE_PATTERN = [
411, 435, 819, 201, 393, 401, 153, 281, 305, 147, 275, 291, 461, 473, 921, 413,
441, 825, 627, 467, 915, 315, 371, 951, 407, 423, 807, 311, 359, 615, 219, 795,
867, 197, 209, 785, 141, 177, 561, 139, 163, 547, 237, 909, 945, 221, 797, 881,
887, 907, 931, 187, 571, 955, 215, 791, 839, 183, 567, 711, 759, 531, 655, 101,
389, 105, 777, 417, 801, 77, 269, 89, 537, 353, 609, 579, 83, 751, 323, 753,
485, 489, 969, 317, 377, 633, 303, 335, 591, 987, 891, 879, 245, 965, 977, 189,
573, 175, 559, 989, 957, 983, 943, 267, 75, 459,
];
const BARCODE_STOP = [1,1,0,0,0,1,1,1,0,1,0,1,1];
const BARCODE_QUIET = [0,0,0,0,0,0,0,0,0,0];
/* **************************************** */
const BARCODE_CSET_A = 1;
const BARCODE_CSET_B = 2;
const BARCODE_CSET_C = 4;
const BARCODE_CSET_X = 8;
const BARCODE_CSET_AB = 1 + 2;
const BARCODE_CSET_ABC = 1 + 2 + 4;
const BARCODE_CSET = [
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
];
/* **************************************** */
function gbcGetStrType(s)
{
let r = []
for (let i in s)
{
let c = s.charCodeAt(i);
if (c < 128)
r.push(BARCODE_CSET[c]);
else
r.push(BARCODE_CSET_X);
}
return r;
}
function gbcCompStrType(stl)
{
if (stl.length == 0)
return [0, 0];
let r = []
let t = stl[0];
let n = 0;
for (let i in stl)
{
let u = t & stl[i];
if (u != 0)
{
t = u;
n += 1;
continue;
}
r.push([n, t]);
t = stl[i];
n = 1;
}
r.push([n, t]);
return r;
}
function gbcGetCodeSet(pt, nt)
{
if (pt == 0)
{
if ((nt & BARCODE_CSET_A) != 0)
return BARCODE_START_A;
if ((nt & BARCODE_CSET_B) != 0)
return BARCODE_START_B;
if ((nt & BARCODE_CSET_C) != 0)
return BARCODE_START_C;
throw 'unknown code set';
}
if ((pt & BARCODE_CSET_A) != 0)
{
if ((nt & BARCODE_CSET_B) != 0)
return BARCODE_CSET_A2B;
if ((nt & BARCODE_CSET_C) != 0)
return BARCODE_CSET_A2C;
throw 'unknown code set';
}
if ((pt & BARCODE_CSET_B) != 0)
{
if ((nt & BARCODE_CSET_A) != 0)
return BARCODE_CSET_B2A;
if ((nt & BARCODE_CSET_C) != 0)
return BARCODE_CSET_B2C;
throw 'unknown code set';
}
if ((pt & BARCODE_CSET_C) != 0)
{
if ((nt & BARCODE_CSET_B) != 0)
return BARCODE_CSET_C2B;
if ((nt & BARCODE_CSET_C) != 0)
return BARCODE_CSET_C2A;
throw 'unknown code set';
}
throw 'unknown code set';
}
function gbcGetCodeSetA(c)
{
if (c < 32)
return (c + 96);
if (c < 96)
return (c - 32);
throw ('invalid code (A):' + c);
}
function gbcGetCodeSetB(c)
{
if (32 <= c && c < 128)
return (c - 32);
throw ('invalid code (B):' + c);
}
function gbcGetCodeSetFunc(t)
{
if ((t & BARCODE_CSET_A) != 0)
return gbcGetCodeSetA;
if ((t & BARCODE_CSET_B) != 0)
return gbcGetCodeSetB;
throw 'unknown code set';
}
function gbcStrToCode(str, cst)
{
let r = []
let si = 0;
let pt = 0;
for (let ct of cst)
{
let c = ct[0];
let nt = ct[1];
nt &= BARCODE_CSET_AB; /* コードセット C は非対応 */
r.push(gbcGetCodeSet(pt, nt));
pt = nt;
let s2c = gbcGetCodeSetFunc(nt);
for (let ci = 0; ci < c; ci++, si++)
{
r.push(s2c(str.charCodeAt(si)));
}
}
return r;
}
function gbcGetCheckCode(l)
{
let t = l[0];
for (let i = 1; i < l.length; i++)
{
t += l[i] * i;
}
return (t % 103);
}
/* **************************************** */
function gbcCodeToPattern(c)
{
let p = BARCODE_PATTERN[c];
let r = [];
for (let b = 0; b < 11; b++)
{
r.push(p & 1);
p >>= 1;
}
return r;
}
function gbcMakePattern(l)
{
let pl = [];
for (let c of l)
{
pl = pl.concat(gbcCodeToPattern(c));
}
let pc = gbcCodeToPattern(gbcGetCheckCode(l));
return BARCODE_QUIET.concat(pl, pc, BARCODE_STOP, BARCODE_QUIET);
}
function gbcStrToPattern(str)
{
let stl = gbcGetStrType(str);
let cst = gbcCompStrType(stl);
let bcs = gbcStrToCode(str, cst);
return gbcMakePattern(bcs);
}
/* **************************************** */
function gbcClearChild(e)
{
while (e.firstChild)
e.removeChild(e.firstChild);
}
function gbcSetError(e, msg)
{
let m = document.createElement('div');
m.innerText = msg;
gbcClearChild(e);
e.appendChild(m);
}
function gbcSetPattern(e, p)
{
const tdcolor = ['white', 'black'];
let priority = 'important';
let tab = document.createElement('table');
tab.style.setProperty('background-color', 'white', priority);
tab.style.setProperty('border-collaspe', 'collaspe', priority);
tab.style.setProperty('border-spacing', '0', priority);
tab.style.setProperty('margin', '0', priority);
tab.style.setProperty('border', 'solid 1px', priority);
tab.style.setProperty('padding', '32px', priority);
let tr = document.createElement('tr');
for (let b in p)
{
td = document.createElement('td');
td.style.setProperty('background-color', tdcolor[p[b]], priority);
td.style.setProperty('color', tdcolor[p[b]], priority);
td.style.setProperty('font-size', 'xx-small', priority);
td.style.setProperty('margin', '0', priority);
td.style.setProperty('border', '0', priority);
td.style.setProperty('padding', '20px 1px', priority);
tr.appendChild(td);
}
tab.appendChild(tr);
gbcClearChild(e);
e.appendChild(tab);
}
/* **************************************** */
function genBarCode()
{
let inp = document.getElementById("gbcinp");
let out = document.getElementById("gbcout");
let str = inp.value;
if (str.length == 0)
{
gbcSetError(out, '(待機中)');
return;
}
try
{
let bcp = gbcStrToPattern(str);
gbcSetPattern(out, bcp);
}
catch (e)
{
gbcSetError(out, '(エラー:非対応の文字が使用されています)');
}
}
// -->
</script>
</body>
</html>
コード 128 の構成
コード 128は、以下の要素で構成されています。
a | b | c | d | e | f |
---|---|---|---|---|---|
■□■□■□ | ■□■□■□ … ■□■□■□ | ■□■□■□ | ■□■□■□■ |
項目 | 内容 |
---|---|
a | 先頭クワイエットゾーン(余白) |
b | スタートキャラクタ |
c | データキャラクタ |
d | シンボルチェックキャラクタ |
e | ストップキャラクタ |
f | 末尾クワイエットゾーン(余白) |
キャラクタの構成
ストップキャラクタを除いて、キャラクタは「黒と白」の対が三つ並んでいます。
■ | □ | ■ | □ | ■ | □ |
---|
ストップキャラクタは最後に「黒」があります。
■ | □ | ■ | □ | ■ | □ | ■ |
---|
これで、キャラクタ(バーコード)の最初は黒で、バーコードの最後も黒になります。
黒または白の幅
黒または白の幅は 4 種類あります。
幅 | 黒 | 白 |
---|---|---|
1 | ■ | □ |
2 | ■■ | □□ |
3 | ■■■ | □□□ |
4 | ■■■■ | □□□□ |
幅(1) の倍数です。幅(1)をモジュールと呼ぶようです。
キャラクタの幅およびパターン
キャラクタの幅は固定で、三対の黒白の幅の合計が 11 モジュールになります。
例(35): ■□□□■□□□■■□
幅の異なるパターンで 0 から 105 の値を表します。
ストップキャラクタの幅は、2 モジュールの黒が追加されて、13 モジュールになります。
ストップキャラクタ: ■■□□□■■■□■□ + ■■
**キャラクタのパターン表**
値 | パターン |
---|---|
0 | ■■□■■□□■■□□ |
1 | ■■□□■■□■■□□ |
2 | ■■□□■■□□■■□ |
3 | ■□□■□□■■□□□ |
4 | ■□□■□□□■■□□ |
5 | ■□□□■□□■■□□ |
6 | ■□□■■□□■□□□ |
7 | ■□□■■□□□■□□ |
8 | ■□□□■■□□■□□ |
9 | ■■□□■□□■□□□ |
10 | ■■□□■□□□■□□ |
11 | ■■□□□■□□■□□ |
12 | ■□■■□□■■■□□ |
13 | ■□□■■□■■■□□ |
14 | ■□□■■□□■■■□ |
15 | ■□■■■□□■■□□ |
16 | ■□□■■■□■■□□ |
17 | ■□□■■■□□■■□ |
18 | ■■□□■■■□□■□ |
19 | ■■□□■□■■■□□ |
20 | ■■□□■□□■■■□ |
21 | ■■□■■■□□■□□ |
22 | ■■□□■■■□■□□ |
23 | ■■■□■■□■■■□ |
24 | ■■■□■□□■■□□ |
25 | ■■■□□■□■■□□ |
26 | ■■■□□■□□■■□ |
27 | ■■■□■■□□■□□ |
28 | ■■■□□■■□■□□ |
29 | ■■■□□■■□□■□ |
30 | ■■□■■□■■□□□ |
31 | ■■□■■□□□■■□ |
32 | ■■□□□■■□■■□ |
33 | ■□■□□□■■□□□ |
34 | ■□□□■□■■□□□ |
35 | ■□□□■□□□■■□ |
36 | ■□■■□□□■□□□ |
37 | ■□□□■■□■□□□ |
38 | ■□□□■■□□□■□ |
39 | ■■□■□□□■□□□ |
40 | ■■□□□■□■□□□ |
41 | ■■□□□■□□□■□ |
42 | ■□■■□■■■□□□ |
43 | ■□■■□□□■■■□ |
44 | ■□□□■■□■■■□ |
45 | ■□■■■□■■□□□ |
46 | ■□■■■□□□■■□ |
47 | ■□□□■■■□■■□ |
48 | ■■■□■■■□■■□ |
49 | ■■□■□□□■■■□ |
50 | ■■□□□■□■■■□ |
51 | ■■□■■■□■□□□ |
52 | ■■□■■■□□□■□ |
53 | ■■□■■■□■■■□ |
54 | ■■■□■□■■□□□ |
55 | ■■■□■□□□■■□ |
56 | ■■■□□□■□■■□ |
57 | ■■■□■■□■□□□ |
58 | ■■■□■■□□□■□ |
59 | ■■■□□□■■□■□ |
60 | ■■■□■■■■□■□ |
61 | ■■□□■□□□□■□ |
62 | ■■■■□□□■□■□ |
63 | ■□■□□■■□□□□ |
64 | ■□■□□□□■■□□ |
65 | ■□□■□■■□□□□ |
66 | ■□□■□□□□■■□ |
67 | ■□□□□■□■■□□ |
68 | ■□□□□■□□■■□ |
69 | ■□■■□□■□□□□ |
70 | ■□■■□□□□■□□ |
71 | ■□□■■□■□□□□ |
72 | ■□□■■□□□□■□ |
73 | ■□□□□■■□■□□ |
74 | ■□□□□■■□□■□ |
75 | ■■□□□□■□□■□ |
76 | ■■□□■□■□□□□ |
77 | ■■■■□■■■□■□ |
78 | ■■□□□□■□■□□ |
79 | ■□□□■■■■□■□ |
80 | ■□■□□■■■■□□ |
81 | ■□□■□■■■■□□ |
82 | ■□□■□□■■■■□ |
83 | ■□■■■■□□■□□ |
84 | ■□□■■■■□■□□ |
85 | ■□□■■■■□□■□ |
86 | ■■■■□■□□■□□ |
87 | ■■■■□□■□■□□ |
88 | ■■■■□□■□□■□ |
89 | ■■□■■□■■■■□ |
90 | ■■□■■■■□■■□ |
91 | ■■■■□■■□■■□ |
92 | ■□■□■■■■□□□ |
93 | ■□■□□□■■■■□ |
94 | ■□□□■□■■■■□ |
95 | ■□■■■■□■□□□ |
96 | ■□■■■■□□□■□ |
97 | ■■■■□■□■□□□ |
98 | ■■■■□■□□□■□ |
99 | ■□■■■□■■■■□ |
100 | ■□■■■■□■■■□ |
101 | ■■■□■□■■■■□ |
102 | ■■■■□■□■■■□ |
103 | ■■□■□□□□■□□ |
104 | ■■□■□□■□□□□ |
105 | ■■□■□□■■■□□ |
[2,1,2,2,2,2], [2,2,2,1,2,2], [2,2,2,2,2,1], [1,2,1,2,2,3],
[1,2,1,3,2,2], [1,3,1,2,2,2], [1,2,2,2,1,3], [1,2,2,3,1,2],
[1,3,2,2,1,2], [2,2,1,2,1,3], [2,2,1,3,1,2], [2,3,1,2,1,2],
[1,1,2,2,3,2], [1,2,2,1,3,2], [1,2,2,2,3,1], [1,1,3,2,2,2],
[1,2,3,1,2,2], [1,2,3,2,2,1], [2,2,3,2,1,1], [2,2,1,1,3,2],
[2,2,1,2,3,1], [2,1,3,2,1,2], [2,2,3,1,1,2], [3,1,2,1,3,1],
[3,1,1,2,2,2], [3,2,1,1,2,2], [3,2,1,2,2,1], [3,1,2,2,1,2],
[3,2,2,1,1,2], [3,2,2,2,1,1], [2,1,2,1,2,3], [2,1,2,3,2,1],
[2,3,2,1,2,1], [1,1,1,3,2,3], [1,3,1,1,2,3], [1,3,1,3,2,1],
[1,1,2,3,1,3], [1,3,2,1,1,3], [1,3,2,3,1,1], [2,1,1,3,1,3],
[2,3,1,1,1,3], [2,3,1,3,1,1], [1,1,2,1,3,3], [1,1,2,3,3,1],
[1,3,2,1,3,1], [1,1,3,1,2,3], [1,1,3,3,2,1], [1,3,3,1,2,1],
[3,1,3,1,2,1], [2,1,1,3,3,1], [2,3,1,1,3,1], [2,1,3,1,1,3],
[2,1,3,3,1,1], [2,1,3,1,3,1], [3,1,1,1,2,3], [3,1,1,3,2,1],
[3,3,1,1,2,1], [3,1,2,1,1,3], [3,1,2,3,1,1], [3,3,2,1,1,1],
[3,1,4,1,1,1], [2,2,1,4,1,1], [4,3,1,1,1,1], [1,1,1,2,2,4],
[1,1,1,4,2,2], [1,2,1,1,2,4], [1,2,1,4,2,1], [1,4,1,1,2,2],
[1,4,1,2,2,1], [1,1,2,2,1,4], [1,1,2,4,1,2], [1,2,2,1,1,4],
[1,2,2,4,1,1], [1,4,2,1,1,2], [1,4,2,2,1,1], [2,4,1,2,1,1],
[2,2,1,1,1,4], [4,1,3,1,1,1], [2,4,1,1,1,2], [1,3,4,1,1,1],
[1,1,1,2,4,2], [1,2,1,1,4,2], [1,2,1,2,4,1], [1,1,4,2,1,2],
[1,2,4,1,1,2], [1,2,4,2,1,1], [4,1,1,2,1,2], [4,2,1,1,1,2],
[4,2,1,2,1,1], [2,1,2,1,4,1], [2,1,4,1,2,1], [4,1,2,1,2,1],
[1,1,1,1,4,3], [1,1,1,3,4,1], [1,3,1,1,4,1], [1,1,4,1,1,3],
[1,1,4,3,1,1], [4,1,1,1,1,3], [4,1,1,3,1,1], [1,1,3,1,4,1],
[1,1,4,1,3,1], [3,1,1,1,4,1], [4,1,1,1,3,1], [2,1,1,4,1,2],
[2,1,1,2,1,4], [2,1,1,2,3,2],
キャラクタとコードセット
キャラクタ(値)の 0 〜 105 に対して、コードセットは 3 種類(A,B,C)あります。
値 | A | B | C |
---|---|---|---|
0 | 32 | 32 | 0 |
1 | 33 | 33 | 1 |
… | … | … | … |
63 | 95 | 95 | 63 |
64 | 0 | 96 | 64 |
… | … | … | … |
95 | 31 | 127 | 95 |
96 | FNC3 | FNC3 | 96 |
97 | FNC2 | FNC2 | 97 |
98 | シフト | シフト | 98 |
99 | コードC | コードC | 99 |
100 | コードB | FNC4 | コードB |
101 | FNC4 | コードA | コードA |
102 | FNC1 | FNC1 | FNC1 |
103 | スタートA | スタートA | スタートA |
104 | スタートB | スタートB | スタートB |
105 | スタートC | スタートC | スタートC |
103,104,105 はスタートキャラクタで、コードセット(A,B,C)の初期指定になります。
101,100,99 は後続のコードセット(A,B,C)の指定になります。
98 のシフトは、後続の「1キャラクタ」をコードセット「A→B」または「B→A」にする指定となります。
FNC1,FNC2,FNC3,FNC4 はファンクションキャラクタです。この記事では FNC4(bit7情報の追加) のみ使用しています。
コードセット
コードセット A は ISO/IEC 646 IRV の文字(0 〜 95)が含まれます。
コードセット B は ISO/IEC 646 IRV の文字(32 〜 127)が含まれます。
値 | 0 〜 63 | 64 〜 95 |
---|---|---|
A | 32 〜 95 | 0 〜 31 |
B | 32 〜 95 | 96 〜 127 |
コードセット C は 2 桁の数字(0 〜 99)を一つのキャラクタにします。
シンボルチェックキャラクタ
次の計算で、シンボルチェックキャラクタ(値)を算出します。
スタートキャラクタ: D[0]
データキャラクタ : D[1〜n]
シンボルチェックキャラクタ: (D[0] + D[1]*1 + D[2]*2 + … + D[n]*n) % 103
クワイエットゾーン
バーコード前後の余白は、最小で 10 モジュールとされています。