qr_code3_3.htm

戻る

<!DOCTYPE HTML>
<HTML LANG="ja">

<HEAD>
<META CHARSET="Shift_JIS">
<TITLE>今どきの 新・QR コード作成(TextDecoder 版)</TITLE>
</HEAD>

<BODY onLoad="shift_jis_init()" STYLE="background-color:#CCFFFF">
<CENTER>
<BR>
<B>今どきの 新・QR コード作成(TextDecoder 版)</B>
<BR><BR>

<SCRIPT TYPE="text/javascript">
<!--
  MAX_VER = 40;
  MAX_MOD = 17 + MAX_VER * 4;

  document.writeln("<DIV STYLE='position:relative; width:", String(MAX_MOD * 2 + 40),
                     "px; height:", String(MAX_MOD * 2 + 40), "px; background-color:white'>",
                   "<DIV ID='vis' STYLE='position:relative'>");
  for(i = 0; i < MAX_MOD; i++) {
    for(j = 0; j < MAX_MOD; j++)
      document.write("<SPAN ID='", i.toString(16), "_", j.toString(16),
                       "' STYLE='position:absolute; left:", String(j * 2 + 20),
                       "px; top:", String(i * 2 + 20), "px; width:2px; height:2px'>",
                     "</SPAN>");
  }
  document.writeln("</DIV></DIV>");
//-->
</SCRIPT>

<BR>

<FORM>
誤り訂正レベル
<SELECT NAME="level">
<OPTION SELECTED>L
<OPTION>M
<OPTION>Q
<OPTION>H
</SELECT>
<BR><BR>
データ<BR>
<TEXTAREA NAME="data" ROWS=6 COLS=40></TEXTAREA>
<BR><BR>
<INPUT TYPE=BUTTON VALUE="作成" onClick="QR_encoding()">
</FORM>

<IFRAME ID="cvt" WIDTH=1 HEIGHT=1 FRAMEBORDER=0 SCROLLING=NO STYLE="visibility:hidden"></IFRAME>

<DIV ID="msg" STYLE="visibility:hidden">処理中...</DIV>

</CENTER>

<SCRIPT TYPE="text/javascript">
<!--

// エンコード
function QR_encoding() {
  data = document.forms[0].data.value;  // データ
  if(!data.length)
    return;
  level = document.forms[0].level.selectedIndex;  // 誤り訂正レベル

  document.getElementById("vis").style.visibility = "hidden";
  document.getElementById("msg").style.visibility = "visible";

  setTimeout("QR_encoding_body(); QR_encoding_end()", 0);
}

function QR_encoding_end() {
  if(data)  // エラー以外
    document.getElementById("vis").style.visibility = "visible";
  document.getElementById("msg").style.visibility = "hidden";
}

function QR_encoding_body() {
  var code1;
  var n1, n2;
  var b1, b2;
  var x, y;
  var i, j, k;

  // モード判定
  var mode;  // モード
  var data_len = 0;  // 入力データ長
  var f_num, f_alpha, f_kanji;
  f_num = f_alpha = f_kanji = 1;
  for(i = 0; i < data.length; i++) {
    var c = data.charAt(i);
    code1 = c.charCodeAt(0);
    if(code1 < 0x80 || code1 == 0xa5 || code1 == 0x203e) {  // ASCII
      data_len++;
      f_kanji = 0;
      if(c < "0" || c > "9") {
        f_num = 0;
        if(c < "A" || c > "Z") {
          switch(c) {
          case " ":
          case "$":
          case "%":
          case "*":
          case "+":
          case "-":
          case ".":
          case "/":
          case ":":
            break;
          default:
            f_alpha = 0;
          }
        }
      }
    }
    else {
      if(code1 >= 0xff61 && code1 <= 0xff9f) {  // 半角カナ
        data_len++;
        f_num = f_alpha = f_kanji = 0;
      }
      else {
        if(!unicode_sjis.has(c)) {
          alert("エンコードできない文字があります!");
          data = null;
          return;
        }
        data_len += 2;
        f_num = f_alpha = 0;
      }
    }
  }
  if     (f_num)
    mode = 0;  // 数字モード
  else if(f_alpha)
    mode = 1;  // 英数字モード
  else if(f_kanji)
    mode = 3;  // 漢字モード
  else
    mode = 2;  // 8 ビット バイト モード

  var version;  // 型番
  var len_bits;  // 文字数指示子ビット数
  var data_cws;  // データ コード語数
  var max_chars;  // 最大格納文字数

  i_code = 0;
  reg = 0;
  reg_bits = 0;
  switch(mode) {
  case 0:  // 数字モード
    // 型番決定
    for(version = 1; version <= MAX_VER; version++) {
      if     (version <= 9)
        len_bits = 10;
      else if(version <= 26)
        len_bits = 12;
      else
        len_bits = 14;
      n1 = (data_cws = get_data_cws(version, level)) * 8 - 4 - len_bits;
      max_chars = Math.floor(n1 / 10) * 3;
      n1 %= 10;
      if(n1 >= 4) {
        if(n1 >= 7)
          max_chars += 2;
        else
          max_chars++;
      }
      if(data_len <= max_chars)
        break;
    }
    if(version > MAX_VER) {
      alert("データが長すぎます!");
      data = null;
      return;
    }
    // データ コード語作成
    // モード指示子,文字数指示子
    put_code(0x1, 4);
    put_code(data_len, len_bits);
    // データ
    for(i = 0; ; ) {
      if(i + 2 < data_len) {
        put_code(Number(data.substr(i, 3)), 10);
        if((i += 3) == data_len)
          break;
      }
      else {
        if     (i + 1 < data_len)
          put_code(Number(data.substr(i, 2)), 7);
        else if(i < data_len)
          put_code(Number(data.charAt(i)), 4);
        break;
      }
    }
    break;

  case 1:  // 英数字モード
    // 型番決定
    for(version = 1; version <= MAX_VER; version++) {
      if     (version <= 9)
        len_bits = 9;
      else if(version <= 26)
        len_bits = 11;
      else
        len_bits = 13;
      n1 = (data_cws = get_data_cws(version, level)) * 8 - 4 - len_bits;
      max_chars = Math.floor(n1 / 11) * 2;
      if(n1 % 11 >= 6)
        max_chars++;
      if(data_len <= max_chars)
        break;
    }
    if(version > MAX_VER) {
      alert("データが長すぎます!");
      data = null;
      return;
    }
    // データ コード語作成
    // モード指示子,文字数指示子
    put_code(0x2, 4);
    put_code(data_len, len_bits);
    // データ
    for(i = 0; ; ) {
      if(i + 1 < data_len) {
        put_code(alpha_val(data.charAt(i)) * 45 + alpha_val(data.charAt(i + 1)), 11);
        if((i += 2) == data_len)
          break;
      }
      else {
        put_code(alpha_val(data.charAt(i)), 6);
        break;
      }
    }
    break;

  case 2:  // 8 ビット バイト モード
    // 型番決定
    for(version = 1; version <= MAX_VER; version++) {
      if     (version <= 9)
        len_bits = 8;
      else
        len_bits = 16;
      max_chars = Math.floor(((data_cws = get_data_cws(version, level)) * 8 - 4 - len_bits) / 8);
      if(data_len <= max_chars)
        break;
    }
    if(version > MAX_VER) {
      alert("データが長すぎます!");
      data = null;
      return;
    }
    // データ コード語作成
    // モード指示子,文字数指示子
    put_code(0x4, 4);
    put_code(data_len, len_bits);
    // データ
    for(i = 0; i < data.length; i++) {
      code1 = data.charCodeAt(i);
      if     (code1 < 0x80)  // ASCII
        put_code(code1, 8);
      else if(code1 == 0xa5)  // 円記号
        put_code(0x5c, 8);
      else if(code1 == 0x203e)  // オーバライン
        put_code(0x7e, 8);
      else if(code1 >= 0xff61 && code1 <= 0xff9f)  // 半角カナ
        put_code(code1 - 0xfec0, 8);
      else  // 漢字
        put_code(unicode_sjis.get(data.charAt(i)), 16);
    }
    break;

  case 3:  // 漢字モード
    data_len = data.length;
    // 型番決定
    for(version = 1; version <= MAX_VER; version++) {
      if     (version <= 9)
        len_bits = 8;
      else if(version <= 26)
        len_bits = 10;
      else
        len_bits = 12;
      max_chars = Math.floor(((data_cws = get_data_cws(version, level)) * 8 - 4 - len_bits) / 13);
      if(data_len <= max_chars)
        break;
    }
    if(version > MAX_VER) {
      alert("データが長すぎます!");
      data = null;
      return;
    }
    // データ コード語作成
    // モード指示子,文字数指示子
    put_code(0x8, 4);
    put_code(data_len, len_bits);
    // データ
    for(i = 0; i < data_len; i++) {
      // 13 ビットに変換
      var sjis = unicode_sjis.get(data.charAt(i));
      put_code(((sjis >> 8) - ((sjis < 0xe000) ? 0x81 : 0xc1)) * 192 + ((sjis & 0xff) - 0x40), 13);
    }
    break;
  }

  // 終端パターン“0000”付加
  if(i_code < data_cws - 1 || i_code < data_cws && !reg_bits)
    put_code(0x0, 4);
  // フラッシュ
  if(reg_bits)
    code[i_code++] = (reg << (8 - reg_bits)) & 0xff;
  // パディング
  for(; ; ) {
    if(i_code == data_cws)
      break;
    code[i_code++] = 0xec;
    if(i_code == data_cws)
      break;
    code[i_code++] = 0x11;
  }

  var n_blocks = rs_blocks[version - 1][level];  // RS ブロック数
  var n_ec = ec_codewords[version - 1][level];  // 誤り訂正コード語数
  var g_exp = g_exp_t[n_ec - 1];  // 誤り訂正コード α指数

  // 誤り訂正コード作成
  var i_data = 0;
  var i_ec = data_cws;
  n1 = Math.floor(data_cws / n_blocks);
  n2 = n_blocks - data_cws % n_blocks;
  for(i_block = 0; i_block < n_blocks; i_block++) {
    if(i_block == n2)
      n1++;
    var data_ec = code.slice(i_data, i_data + n1);
    data_ec.length = n1 + n_ec;
    for(i = 0; i < n_ec; i++)
      data_ec[n1 + i] = 0;
    for(i = 0; i < n1; i++) {
      if(data_ec[i]) {
        var exp1 = n_exp[data_ec[i]];
        for(j = 0; j < n_ec; j++)
          data_ec[i + 1 + j] ^= exp_n[(g_exp[j] + exp1) % 255];
      }
    }
    for(i = 0; i < n_ec; i++)
      code[i_ec + i] = data_ec[n1 + i];
    i_data += n1;
    i_ec += n_ec;
  }

  var n_modules1 = 21 + (version - 1) * 4;  // 1 辺のモジュール数

  for(i = 0; i < n_modules1; i++) {
    for(j = 0; j < n_modules1; j++)
      module1[i][j] = 0;
  }
  // 位置検出パターン & 分離パターン & 形式情報位置予約(一部)& 固定暗モジュール
  for(i = 0; i < 8; i++) {
    for(j = 0; j < 9; j++)  // 左上
      module1[i][j] = finder_pat[i + 1][1 + j];
    for(j = 0; j < 8; j++)  // 右上
      module1[i][n_modules1 - 8 + j] = finder_pat[i + 1][j];
    for(j = 0; j < 9; j++)  // 左下
      module1[n_modules1 - 8 + i][j] = finder_pat[i][1 + j];
  }
  // 形式情報位置予約
  module1[8].splice(0,              9, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40);
  module1[8].splice(n_modules1 - 8, 8, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40);
  // 型番情報位置予約
  if(version >= 7) {
    for(i = 11; i >= 9; i--)  // 左下
      module1[n_modules1 - i].splice(0, 6, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40);
    for(i = 0; i <= 5; i++)  // 右上
      module1[i].splice(n_modules1 - 11, 3, 0x40, 0x40, 0x40);
  }
  // タイミング パターン
  for(i = 8; i < n_modules1 - 9; i += 2) {
    module1[6][i    ] = module1[i    ][6] = 0x81;
    module1[6][i + 1] = module1[i + 1][6] = 0x80;
  }
  module1[6][i] = module1[i][6] = 0x81;
  // 位置合せパターン
  n1 = align_pos[version - 1].length;
  for(i = 0; i < n1; i++) {
    y = align_pos[version - 1][i];
    for(j = 0; j < n1; j++) {
      if(i == 0 && j == 0 || i == 0 && j == n1 - 1 || i == n1 - 1 && j == 0)
        continue;
      x = align_pos[version - 1][j];
      module1[y - 2].splice(x - 2, 5, 0x81, 0x81, 0x81, 0x81, 0x81);
      module1[y - 1].splice(x - 2, 5, 0x81, 0x80, 0x80, 0x80, 0x81);
      module1[y    ].splice(x - 2, 5, 0x81, 0x80, 0x81, 0x80, 0x81);
      module1[y + 1].splice(x - 2, 5, 0x81, 0x80, 0x80, 0x80, 0x81);
      module1[y + 2].splice(x - 2, 5, 0x81, 0x81, 0x81, 0x81, 0x81);
    }
  }

  // シンボル キャラクタ配置
  n1 = Math.floor(data_cws / n_blocks);
  n2 = n_blocks - data_cws % n_blocks;
  i_block = 0;
  i_code = 0;
  code1 = code[0];
  b1 = 0x80;
  i = j = n_modules1 - 1;
  var dir = 0;  // 走査方向
  var l_r = 0;  // 右/左
  for(; ; ) {
    if(!module1[i][j]) {  // 空き
      module1[i][j] = (code1 & b1) ? 1 : 0;
      if(!(b1 >>= 1)) {
        // 次のコード語
        if(++i_block == n_blocks) {
          i_block = 0;
          i_code++;
          if(n1) {  // データ コード
            if     (i_code == n1) {  // 短い方のデータ コードの長さ分終了
              if(n2 == n_blocks) {  // データ コードの長さがすべて等しい → 誤り訂正コードへ
                n1 = 0;
                i_code = 0;
              }
              else {  // 余り分
                i_block = n2;
              }
            }
            else if(i_code > n1) {  // データ コード終了 → 誤り訂正コードへ
              n1 = 0;
              i_code = 0;
            }
          }
          else {  // 誤り訂正コード
            if(i_code == n_ec)  // 終了
              break;
          }
        }
        if(n1) {  // データ コード
          k = i_block * n1;
          if(i_block > n2)
            k += i_block - n2;
        }
        else {  // 誤り訂正コード
          k = data_cws + i_block * n_ec;
        }
        code1 = code[k + i_code];
        b1 = 0x80;
      }
    }
    if(l_r) {  // 左
      if(dir) {  // 下方向
        if(i < n_modules1 - 1) {
          i++;
          j++;
        }
        else {
          dir = 0;  // 反転
          if(--j == 6)
            j = 5;
        }
      }
      else {  // 上方向
        if(i) {
          i--;
          j++;
        }
        else {
          dir = 1;  // 反転
          if(--j == 6)
            j = 5;
        }
      }
      l_r = 0;
    }
    else {  // 右
      j--;
      l_r = 1;
    }
  }

  // マスク パターン決定
  var mask;  // マスク パターン
  var min_penalty = 0x7fffffff;  // 最小失点
  var m;
  for(m = 0x0; m <= 0x7; m++) {
    masking(n_modules1, m);  // マスク

    // 失点計算
    var penalty = 0;  // 失点

    // 同色の隣接モジュール
    for(i = 0; i < n_modules1; i++) {
      // 行
      b1 = module2[i][0];
      n1 = 1;
      // 列
      b2 = module2[0][i];
      n2 = 1;
      for(j = 1; j < n_modules1; j++) {
        // 行
        if(module2[i][j] == b1) {
          n1++;
        }
        else {
          if(n1 >= 5)
            penalty += 3 + (n1 - 5);
          b1 = module2[i][j];
          n1 = 1;
        }
        // 列
        if(module2[j][i] == b2) {
          n2++;
        }
        else {
          if(n2 >= 5)
            penalty += 3 + (n2 - 5);
          b2 = module2[j][i];
          n2 = 1;
        }
      }
      // 行
      if(n1 >= 5)
        penalty += 3 + (n1 - 5);
      // 列
      if(n2 >= 5)
        penalty += 3 + (n2 - 5);
    }

    // 2×2 のモジュール ブロック
    for(i = 0; i < n_modules1 - 1; i++) {
      for(j = 0; j < n_modules1 - 1; j++) {
        b1 = module2[i][j];
        if(module2[i][j + 1] == b1 && module2[i + 1][j] == b1 && module2[i + 1][j + 1] == b1)
          penalty += 3;
      }
    }

    // 1:1:3:1:1 比率のパターン
    var cnt = new Array();
    cnt.length = 7;
    // 行
    for(i = 0; i < n_modules1; i++) {
      k = 0;
      for(j = 0; ; ) {
        // 同色モジュール数カウント
        for(; k < 7; k++) {
          x = j;
          for(; j < n_modules1; j++) {
            if(module2[i][j] ^ (k & 0x01))  // k = 0,2,4,6 -- 暗?,k = 1,3,5 -- 明?
              break;
          }
          cnt[k] = j - x;  // モジュール数
          if(j == n_modules1)
            break;
        }
        if(k >= 5) {
          if(k == 5)
            cnt[6] = 0;
          if(cnt[2] == cnt[1] && cnt[3] == cnt[1] * 3 && cnt[4] == cnt[1] && cnt[5] == cnt[1]
               && (cnt[0] >= cnt[1] * 4 || cnt[6] >= cnt[1] * 4)) {  // 1:1:3:1:1 & 4 以上の明
            penalty += 40;
            if(j < n_modules1) {  // 終端でない
              // 続きをチェック
              cnt[0] = cnt[4];
              cnt[1] = cnt[5];
              cnt[2] = cnt[6];
              k = 3;
              continue;
            }
          }
        }
        if(j == n_modules1)
          break;
        // 続きをチェック
        cnt[0] = cnt[2];
        cnt[1] = cnt[3];
        cnt[2] = cnt[4];
        cnt[3] = cnt[5];
        cnt[4] = cnt[6];
        k = 5;
      }
    }
    // 列
    for(j = 0; j < n_modules1; j++) {
      k = 0;
      for(i = 0; ; ) {
        // 同色モジュール数カウント
        for(; k < 7; k++) {
          y = i;
          for(; i < n_modules1; i++) {
            if(module2[i][j] ^ (k & 0x01))  // k = 0,2,4,6 -- 暗?,k = 1,3,5 -- 明?
              break;
          }
          cnt[k] = i - y;  // モジュール数
          if(i == n_modules1)
            break;
        }
        if(k >= 5) {
          if(k == 5)
            cnt[6] = 0;
          if(cnt[2] == cnt[1] && cnt[3] == cnt[1] * 3 && cnt[4] == cnt[1] && cnt[5] == cnt[1]
               && (cnt[0] >= cnt[1] * 4 || cnt[6] >= cnt[1] * 4)) {  // 1:1:3:1:1 & 4 以上の明
            penalty += 40;
            if(i < n_modules1) {  // 終端でない
              // 続きをチェック
              cnt[0] = cnt[4];
              cnt[1] = cnt[5];
              cnt[2] = cnt[6];
              k = 3;
              continue;
            }
          }
        }
        if(i == n_modules1)
          break;
        // 続きをチェック
        cnt[0] = cnt[2];
        cnt[1] = cnt[3];
        cnt[2] = cnt[4];
        cnt[3] = cnt[5];
        cnt[4] = cnt[6];
        k = 5;
      }
    }

    // 暗モジュール比率
    // 2004年改正 JIS X 0510 では「参考」にある例が「評価条件」と矛盾している.
    n1 = 0;
    for(i = 0; i < n_modules1; i++) {
      for(j = 0; j < n_modules1; j++) {
        if(module2[i][j])  // 暗
          n1++;
      }
    }
    n2 = n_modules1 * n_modules1;
    if((n1 = Math.floor((Math.abs(n1 * 2 - n2) * 20 + (n2 * 2) - 1) / (n2 * 2))) > 1)
      penalty += 10 * (n1 - 1);

    if(penalty < min_penalty) {
      mask = m;
      min_penalty = penalty;
    }
  }

  masking(n_modules1, mask);  // 採用したマスク パターンでマスク

  // 固定暗モジュール
  // 固定暗モジュール配置はマスク判定の前か後か?
  module2[n_modules1 - 8][8] = 1;
  // 形式情報
  code1 = format_info[level][mask];
  b1 = 0x4000;
  for(i = 0; i < 7; i++) {
    module2[8][(i < 6) ? i : i + 1] = module2[n_modules1 - 1 - i][8] = (code1 & b1) ? 1 : 0;
    b1 >>= 1;
  }
  for(i = 7; i >= 0; i--) {
    module2[(i < 6) ? i : i + 1][8] = module2[8][n_modules1 - 1 - i] = (code1 & b1) ? 1 : 0;
    b1 >>= 1;
  }
  // 型番情報
  if(version >= 7) {
    code1 = version_info[version - 7];
    b1 = 0x20000;
    for(i = 0; i < 18; i++) {
      y = n_modules1 - 9 - i % 3;
      x = 5 - Math.floor(i / 3);
      module2[y][x] = module2[x][y] = (code1 & b1) ? 1 : 0;
      b1 >>= 1;
    }
  }

  // 表示
  for(i = 0; i < n_modules1; i++) {
    for(j = 0; j < n_modules1; j++)
      document.getElementById(i.toString(16) + "_" + j.toString(16)).style.backgroundColor
        = (module2[i][j]) ? "black" : "white";
    for(; j < MAX_MOD; j++)
      document.getElementById(i.toString(16) + "_" + j.toString(16)).style.backgroundColor = "white";
  }
  for(; i < MAX_MOD; i++) {
    for(j = 0; j < MAX_MOD; j++)
      document.getElementById(i.toString(16) + "_" + j.toString(16)).style.backgroundColor = "white";
  }
}

// データ コード語数
function get_data_cws(version, level) {
  var n_modules;
  var n;

  n_modules = 21 + (version - 1) * 4;  // 1 辺のモジュール数
  n_modules = n_modules * n_modules  // 総モジュール数
                - 3 * (8 * 8)              // 位置検出パターン & 分離パターン
                - 2 * (n_modules - 2 * 8)  // タイミング パターン
                - 1                        // 固定暗モジュール
                - 2 * 15;                  // 形式情報
  // 位置合せパターン
  n = align_pos[version - 1].length;
  if(n) {  // n > 0
    n_modules -= (n * n - 3) * (5 * 5);
    if(n > 2)
      n_modules += 2 * (n - 2) * 5;  // タイミング パターンと重なる分
  }
  // 型番情報
  if(version >= 7)
    n_modules -= 2 * 18;

  return (n_modules >> 3) - rs_blocks[version - 1][level] * ec_codewords[version - 1][level];
}

// コード登録
function put_code(code1, code1_bits) {
  reg = (reg << code1_bits) | code1;
  reg_bits += code1_bits;
  while(reg_bits >= 8) {
    code[i_code++] = (reg >> (reg_bits - 8)) & 0xff;
    reg_bits -= 8;
  }
}

// 英数字モード 文字値
function alpha_val(c) {
  switch(c) {
  case " ":
    return 36;
  case "$":
    return 37;
  case "%":
    return 38;
  case "*":
    return 39;
  case "+":
    return 40;
  case "-":
    return 41;
  case ".":
    return 42;
  case "/":
    return 43;
  case ":":
    return 44;
  }
  if(c <= "9")
    return c.charCodeAt(0) - "0".charCodeAt(0);
  return c.charCodeAt(0) - "A".charCodeAt(0) + 10;
}

// マスク処理
function masking(n_modules1, mask) {
  var i, j;

  for(i = 0; i < n_modules1; i++) {
    for(j = 0; j < n_modules1; j++) {
      module2[i][j] = module1[i][j] & 0x1;
      if(!(module1[i][j] & 0xc0)) {  // 機能パターン,形式情報,型番情報を除く
        switch(mask) {
        case 0:  // (i+j)mod 2=0
          if((i + j) % 2)
            continue;
          break;
        case 1:  // i mod 2=0
          if(i % 2)
            continue;
          break;
        case 2:  // j mod 3=0
          if(j % 3)
            continue;
          break;
        case 3:  // (i+j)mod 3=0
          if((i + j) % 3)
            continue;
          break;
        case 4:  // ((i div 2)+(j div 3))mod 2=0
          if((Math.floor(i / 2) + Math.floor(j / 3)) % 2)
            continue;
          break;
        case 5:  // (i j)mod 2+(i j)mod 3=0
          if(i * j % 2 + i * j % 3)
            continue;
          break;
        case 6:  // ((i j)mod 2+(i j)mod 3)mod 2=0
          if((i * j % 2 + i * j % 3) % 2)
            continue;
          break;
        case 7:  // ((i j)mod 3+(i+j)mod 2)mod 2=0
          if((i * j % 3 + (i + j) % 2) % 2)
            continue;
          break;
        }
        module2[i][j] ^= 1;  // 反転
      }
    }
  }
}

// シフト JIS 変換初期化
function shift_jis_init() {
  unicode_sjis = new Map();
  var dec = new TextDecoder("shift_jis");
  var sjis = new Uint8Array(2);

  for(var b1 = 0x81, b2 = 0x40; b1 < 0xeb || b2 <=  0xbf; ) {
    sjis[0] = b1;
    sjis[1] = b2;
    var unicode = dec.decode(sjis);
    if(unicode.charCodeAt(0) != 0xfffd) {  // REPLACEMENT CHARACTER 以外
      if(!unicode_sjis.has(unicode))
        unicode_sjis.set(unicode, (b1 << 8) | b2);
    }

    if     (b2 == 0x7e) {
      b2 = 0x80;
    }
    else if(b2 == 0xfc) {
      if(b1 == 0x9f)
        b1 = 0xe0;
      else
        b1++;
      b2 = 0x40;
    }
    else {
      b2++;
    }
  }
}

//----------------------------------------------------------

  code = new Array();  // コード語作成ワーク
  code.length = 3706;
  var i_code;  // コード語インデックス
  var reg;
  var reg_bits;

  // 誤り訂正コード語数
  ec_codewords = [
  // 誤り訂正レベル
  // L   M   Q   H       型番
    [ 7, 10, 13, 17],  //  1
    [10, 16, 22, 28],  //  2
    [15, 26, 18, 22],  //  3
    [20, 18, 26, 16],  //  4
    [26, 24, 18, 22],  //  5
    [18, 16, 24, 28],  //  6
    [20, 18, 18, 26],  //  7
    [24, 22, 22, 26],  //  8
    [30, 22, 20, 24],  //  9
    [18, 26, 24, 28],  // 10
    [20, 30, 28, 24],  // 11
    [24, 22, 26, 28],  // 12
    [26, 22, 24, 22],  // 13
    [30, 24, 20, 24],  // 14
    [22, 24, 30, 24],  // 15
    [24, 28, 24, 30],  // 16
    [28, 28, 28, 28],  // 17
    [30, 26, 28, 28],  // 18
    [28, 26, 26, 26],  // 19
    [28, 26, 30, 28],  // 20
    [28, 26, 28, 30],  // 21
    [28, 28, 30, 24],  // 22
    [30, 28, 30, 30],  // 23
    [30, 28, 30, 30],  // 24
    [26, 28, 30, 30],  // 25
    [28, 28, 28, 30],  // 26
    [30, 28, 30, 30],  // 27
    [30, 28, 30, 30],  // 28
    [30, 28, 30, 30],  // 29
    [30, 28, 30, 30],  // 30
    [30, 28, 30, 30],  // 31
    [30, 28, 30, 30],  // 32
    [30, 28, 30, 30],  // 33
    [30, 28, 30, 30],  // 34
    [30, 28, 30, 30],  // 35
    [30, 28, 30, 30],  // 36
    [30, 28, 30, 30],  // 37
    [30, 28, 30, 30],  // 38
    [30, 28, 30, 30],  // 39
    [30, 28, 30, 30]   // 40
  ];

  // RS ブロック数
  rs_blocks = [
  // 誤り訂正レベル
  // L   M   Q   H       型番
    [ 1,  1,  1,  1],  //  1
    [ 1,  1,  1,  1],  //  2
    [ 1,  1,  2,  2],  //  3
    [ 1,  2,  2,  4],  //  4
    [ 1,  2,  4,  4],  //  5
    [ 2,  4,  4,  4],  //  6
    [ 2,  4,  6,  5],  //  7
    [ 2,  4,  6,  6],  //  8
    [ 2,  5,  8,  8],  //  9
    [ 4,  5,  8,  8],  // 10
    [ 4,  5,  8, 11],  // 11
    [ 4,  8, 10, 11],  // 12
    [ 4,  9, 12, 16],  // 13
    [ 4,  9, 16, 16],  // 14
    [ 6, 10, 12, 18],  // 15
    [ 6, 10, 17, 16],  // 16
    [ 6, 11, 16, 19],  // 17
    [ 6, 13, 18, 21],  // 18
    [ 7, 14, 21, 25],  // 19
    [ 8, 16, 20, 25],  // 20
    [ 8, 17, 23, 25],  // 21
    [ 9, 17, 23, 34],  // 22
    [ 9, 18, 25, 30],  // 23
    [10, 20, 27, 32],  // 24
    [12, 21, 29, 35],  // 25
    [12, 23, 34, 37],  // 26
    [12, 25, 34, 40],  // 27
    [13, 26, 35, 42],  // 28
    [14, 28, 38, 45],  // 29
    [15, 29, 40, 48],  // 30
    [16, 31, 43, 51],  // 31
    [17, 33, 45, 54],  // 32
    [18, 35, 48, 57],  // 33
    [19, 37, 51, 60],  // 34
    [19, 38, 53, 63],  // 35
    [20, 40, 56, 66],  // 36
    [21, 43, 59, 70],  // 37
    [22, 45, 62, 74],  // 38
    [24, 47, 65, 77],  // 39
    [25, 49, 68, 81]   // 40
  ];

  // 誤り訂正コード 生成多項式係数 α指数
  g_exp_t = new Array();
  g_exp_t.length = 30;
  g_exp_t[ 6] = [87, 229, 146, 149, 238, 102, 21];
  g_exp_t[ 9] = [251, 67, 46, 61, 118, 70, 64, 94, 32, 45];
  g_exp_t[12] = [74, 152, 176, 100, 86, 100, 106, 104, 130, 218, 206, 140, 78];
  g_exp_t[14] = [8, 183, 61, 91, 202, 37, 51, 58, 58, 237, 140, 124, 5, 99, 105];
  g_exp_t[15] = [120, 104, 107, 109, 102, 161, 76, 3, 91, 191, 147, 169, 182, 194, 225, 120];
  g_exp_t[16] = [43, 139, 206, 78, 43, 239, 123, 206, 214, 147, 24, 99, 150, 39, 243, 163, 136];
  g_exp_t[17] = [215, 234, 158, 94, 184, 97, 118, 170, 79, 187, 152, 148, 252, 179, 5, 98, 96, 153];
  g_exp_t[19] = [17, 60, 79, 50, 61, 163, 26, 187, 202, 180, 221, 225, 83, 239, 156, 164, 212, 212, 188, 190];
  g_exp_t[21] = [210, 171, 247, 242, 93, 230, 14, 109, 221, 53, 200, 74, 8, 172, 98, 80, 219, 134, 160, 105, 165, 231];
  g_exp_t[23] = [229, 121, 135, 48, 211, 117, 251, 126, 159, 180, 169, 152, 192, 226, 228, 218, 111, 0, 117, 232, 87, 96, 227, 21];
  g_exp_t[25] = [173, 125, 158, 2, 103, 182, 118, 17, 145, 201, 111, 28, 165, 53,161, 21, 245, 142, 13, 102, 48, 227, 153, 145, 218, 70];
  g_exp_t[27] = [168, 223, 200, 104, 224, 234, 108, 180, 110, 190, 195, 147, 205, 27, 232, 201, 21, 43, 245, 87, 42, 195, 212, 119, 242, 37, 9, 123];
  g_exp_t[29] = [41, 173, 145, 152, 216, 31, 179, 182, 50, 48, 110, 86, 239, 96, 222, 125, 42, 173, 226, 193, 224, 130, 156, 37, 251, 216, 238, 40, 192, 180];

  // 位置検出パターン & 分離パターン & 形式情報位置予約(一部)& 固定暗モジュール用データ
  finder_pat = [
//  [0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41],
    [0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x40],
    [0x80, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0x40],
    [0x80, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x80, 0x40],
    [0x80, 0x81, 0x80, 0x81, 0x81, 0x81, 0x80, 0x81, 0x80, 0x40],
    [0x80, 0x81, 0x80, 0x81, 0x81, 0x81, 0x80, 0x81, 0x80, 0x40],
    [0x80, 0x81, 0x80, 0x81, 0x81, 0x81, 0x80, 0x81, 0x80, 0x40],
    [0x80, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x80, 0x40],
    [0x80, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0x40],
    [0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x40]
  ];

  // 位置合せパターン座標
  align_pos = [
  //                                        型番
    [],                                   //  1
    [  6,  18],                           //  2
    [  6,  22],                           //  3
    [  6,  26],                           //  4
    [  6,  30],                           //  5
    [  6,  34],                           //  6
    [  6,  22,  38],                      //  7
    [  6,  24,  42],                      //  8
    [  6,  26,  46],                      //  9
    [  6,  28,  50],                      // 10
    [  6,  30,  54],                      // 11
    [  6,  32,  58],                      // 12
    [  6,  34,  62],                      // 13
    [  6,  26,  46,  66],                 // 14
    [  6,  26,  48,  70],                 // 15
    [  6,  26,  50,  74],                 // 16
    [  6,  30,  54,  78],                 // 17
    [  6,  30,  56,  82],                 // 18
    [  6,  30,  58,  86],                 // 19
    [  6,  34,  62,  90],                 // 20
    [  6,  28,  50,  72,  94],            // 21
    [  6,  26,  50,  74,  98],            // 22
    [  6,  30,  54,  78, 102],            // 23
    [  6,  28,  54,  80, 106],            // 24
    [  6,  32,  58,  84, 110],            // 25
    [  6,  30,  58,  86, 114],            // 26
    [  6,  34,  62,  90, 118],            // 27
    [  6,  26,  50,  74,  98, 122],       // 28
    [  6,  30,  54,  78, 102, 126],       // 29
    [  6,  26,  52,  78, 104, 130],       // 30
    [  6,  30,  56,  82, 108, 134],       // 31
    [  6,  34,  60,  86, 112, 138],       // 32
    [  6,  30,  58,  86, 114, 142],       // 33
    [  6,  34,  62,  90, 118, 146],       // 34
    [  6,  30,  54,  78, 102, 126, 150],  // 35
    [  6,  24,  50,  76, 102, 128, 154],  // 36
    [  6,  28,  54,  80, 106, 132, 158],  // 37
    [  6,  32,  58,  84, 110, 136, 162],  // 38
    [  6,  26,  54,  82, 110, 138, 166],  // 39
    [  6,  30,  58,  86, 114, 142, 170]   // 40
  ];

  // 形式情報
  format_info = [
  //          Level + Mask BCH 符号(マスク前)
    [0x77c4,   // L + 000  0x23d6
     0x72f3,   // L + 001  0x26e1
     0x7daa,   // L + 010  0x29b8
     0x789d,   // L + 011  0x2c8f
     0x662f,   // L + 100  0x323d
     0x6318,   // L + 101  0x370a
     0x6c41,   // L + 110  0x3853
     0x6976],  // L + 111  0x3d64
    [0x5412,   // M + 000  0x0000
     0x5125,   // M + 001  0x0537
     0x5e7c,   // M + 010  0x0a6e
     0x5b4b,   // M + 011  0x0f59
     0x45f9,   // M + 100  0x11eb
     0x40ce,   // M + 101  0x14dc
     0x4f97,   // M + 110  0x1b85
     0x4aa0],  // M + 111  0x1eb2
    [0x355f,   // Q + 000  0x614d
     0x3068,   // Q + 001  0x647a
     0x3f31,   // Q + 010  0x6b23
     0x3a06,   // Q + 011  0x6e14
     0x24b4,   // Q + 100  0x70a6
     0x2183,   // Q + 101  0x7591
     0x2eda,   // Q + 110  0x7ac8
     0x2bed],  // Q + 111  0x7fff
    [0x1689,   // H + 000  0x429b
     0x13be,   // H + 001  0x47ac
     0x1ce7,   // H + 010  0x48f5
     0x19d0,   // H + 011  0x4dc2
     0x0762,   // H + 100  0x5370
     0x0255,   // H + 101  0x5647
     0x0d0c,   // H + 110  0x591e
     0x083b]   // H + 111  0x5c29
  ];

  // 型番情報
  //                           型番
  version_info = [0x07c94,   //  7
                  0x085bc,   //  8
                  0x09a99,   //  9
                  0x0a4d3,   // 10
                  0x0bbf6,   // 11
                  0x0c762,   // 12
                  0x0d847,   // 13
                  0x0e60d,   // 14
                  0x0f928,   // 15
                  0x10b78,   // 16
                  0x1145d,   // 17
                  0x12a17,   // 18
                  0x13532,   // 19
                  0x149a6,   // 20
                  0x15683,   // 21
                  0x168c9,   // 22
                  0x177ec,   // 23
                  0x18ec4,   // 24
                  0x191e1,   // 25
                  0x1afab,   // 26
                  0x1b08e,   // 27
                  0x1cc1a,   // 28
                  0x1d33f,   // 29
                  0x1ed75,   // 30
                  0x1f250,   // 31
                  0x209d5,   // 32
                  0x216f0,   // 33
                  0x228ba,   // 34
                  0x2379f,   // 35
                  0x24b0b,   // 36
                  0x2542e,   // 37
                  0x26a64,   // 38
                  0x27541,   // 39
                  0x28c69];  // 40

  exp_n = new Array();  // α指数 → 数値 変換テーブル
  exp_n.length = 255;
  n_exp = new Array();  // 数値 → α指数 変換テーブル([0] は使用しない)
  n_exp.length = 256;
  // α指数 ― 数値 変換テーブル作成
  n = 0x01;
  for(i = 0; i < 255; i++) {
    exp_n[i] = n;
    n_exp[n] = i;

    n <<= 1;
    if(n & 0x100)
      n = n & 0xff ^ 0x1d;
  }

  module1 = new Array();  // シンボル領域
  module1.length = MAX_MOD;
  module2 = new Array();  // マスク後シンボル領域
  module2.length = MAX_MOD;
  for(i = 0; i < MAX_MOD; i++) {
    module1[i] = new Array();
    module1[i].length = MAX_MOD;
    module2[i] = new Array();
    module2[i].length = MAX_MOD;
  }

//-->
</SCRIPT>

</BODY>

</HTML>