バーコード（コード 128：JIS X 0504 (ISO/IEC 15417) ）の生成

JIS X 0504 (ISO/IEC 15417) 規格のバーコード（HTMLとGIF画像）を JavaScript で生成します。

# 実行画面とソース

![スクリーンショット](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226677/5e9cba82-429b-912f-0619-3bc3a331b82f.png)

<details><summary>ソース（HTML+JavaScript）</summary><div>

動作確認した環境
　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:sample.html
<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;">&nbsp;</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>
```

</div></details>

<details><summary>旧バージョンのソース（HTML+JavaScript）</summary><div>

動作確認した環境
　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:sample.html
<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;">ここで対応している文字は半角（７ビット文字）のみです。</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>
```

</div></details>

# コード 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 モジュールになります。

　　ストップキャラクタ： ■■□□□■■■□■□ + ■■

<details><summary>キャラクタのパターン表</summary><div>

| 値 | パターン |
|--:|:-:|
| 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 | ■■□■□□■■■□□ |


```text:黒白の幅表
[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],
```

</div></details>

## キャラクタとコードセット

キャラクタ（値）の 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 モジュールとされています。