1bd793673eb7af48cb7700da414b63a5de38431d3def90b00ef58b7553e9442e.json raw

   1  {"ast":null,"code":"/**\n * Data mask pattern reference\n * @type {Object}\n */\nexports.Patterns = {\n  PATTERN000: 0,\n  PATTERN001: 1,\n  PATTERN010: 2,\n  PATTERN011: 3,\n  PATTERN100: 4,\n  PATTERN101: 5,\n  PATTERN110: 6,\n  PATTERN111: 7\n};\n\n/**\n * Weighted penalty scores for the undesirable features\n * @type {Object}\n */\nconst PenaltyScores = {\n  N1: 3,\n  N2: 3,\n  N3: 40,\n  N4: 10\n};\n\n/**\n * Check if mask pattern value is valid\n *\n * @param  {Number}  mask    Mask pattern\n * @return {Boolean}         true if valid, false otherwise\n */\nexports.isValid = function isValid(mask) {\n  return mask != null && mask !== '' && !isNaN(mask) && mask >= 0 && mask <= 7;\n};\n\n/**\n * Returns mask pattern from a value.\n * If value is not valid, returns undefined\n *\n * @param  {Number|String} value        Mask pattern value\n * @return {Number}                     Valid mask pattern or undefined\n */\nexports.from = function from(value) {\n  return exports.isValid(value) ? parseInt(value, 10) : undefined;\n};\n\n/**\n* Find adjacent modules in row/column with the same color\n* and assign a penalty value.\n*\n* Points: N1 + i\n* i is the amount by which the number of adjacent modules of the same color exceeds 5\n*/\nexports.getPenaltyN1 = function getPenaltyN1(data) {\n  const size = data.size;\n  let points = 0;\n  let sameCountCol = 0;\n  let sameCountRow = 0;\n  let lastCol = null;\n  let lastRow = null;\n  for (let row = 0; row < size; row++) {\n    sameCountCol = sameCountRow = 0;\n    lastCol = lastRow = null;\n    for (let col = 0; col < size; col++) {\n      let module = data.get(row, col);\n      if (module === lastCol) {\n        sameCountCol++;\n      } else {\n        if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5);\n        lastCol = module;\n        sameCountCol = 1;\n      }\n      module = data.get(col, row);\n      if (module === lastRow) {\n        sameCountRow++;\n      } else {\n        if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5);\n        lastRow = module;\n        sameCountRow = 1;\n      }\n    }\n    if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5);\n    if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5);\n  }\n  return points;\n};\n\n/**\n * Find 2x2 blocks with the same color and assign a penalty value\n *\n * Points: N2 * (m - 1) * (n - 1)\n */\nexports.getPenaltyN2 = function getPenaltyN2(data) {\n  const size = data.size;\n  let points = 0;\n  for (let row = 0; row < size - 1; row++) {\n    for (let col = 0; col < size - 1; col++) {\n      const last = data.get(row, col) + data.get(row, col + 1) + data.get(row + 1, col) + data.get(row + 1, col + 1);\n      if (last === 4 || last === 0) points++;\n    }\n  }\n  return points * PenaltyScores.N2;\n};\n\n/**\n * Find 1:1:3:1:1 ratio (dark:light:dark:light:dark) pattern in row/column,\n * preceded or followed by light area 4 modules wide\n *\n * Points: N3 * number of pattern found\n */\nexports.getPenaltyN3 = function getPenaltyN3(data) {\n  const size = data.size;\n  let points = 0;\n  let bitsCol = 0;\n  let bitsRow = 0;\n  for (let row = 0; row < size; row++) {\n    bitsCol = bitsRow = 0;\n    for (let col = 0; col < size; col++) {\n      bitsCol = bitsCol << 1 & 0x7FF | data.get(row, col);\n      if (col >= 10 && (bitsCol === 0x5D0 || bitsCol === 0x05D)) points++;\n      bitsRow = bitsRow << 1 & 0x7FF | data.get(col, row);\n      if (col >= 10 && (bitsRow === 0x5D0 || bitsRow === 0x05D)) points++;\n    }\n  }\n  return points * PenaltyScores.N3;\n};\n\n/**\n * Calculate proportion of dark modules in entire symbol\n *\n * Points: N4 * k\n *\n * k is the rating of the deviation of the proportion of dark modules\n * in the symbol from 50% in steps of 5%\n */\nexports.getPenaltyN4 = function getPenaltyN4(data) {\n  let darkCount = 0;\n  const modulesCount = data.data.length;\n  for (let i = 0; i < modulesCount; i++) darkCount += data.data[i];\n  const k = Math.abs(Math.ceil(darkCount * 100 / modulesCount / 5) - 10);\n  return k * PenaltyScores.N4;\n};\n\n/**\n * Return mask value at given position\n *\n * @param  {Number} maskPattern Pattern reference value\n * @param  {Number} i           Row\n * @param  {Number} j           Column\n * @return {Boolean}            Mask value\n */\nfunction getMaskAt(maskPattern, i, j) {\n  switch (maskPattern) {\n    case exports.Patterns.PATTERN000:\n      return (i + j) % 2 === 0;\n    case exports.Patterns.PATTERN001:\n      return i % 2 === 0;\n    case exports.Patterns.PATTERN010:\n      return j % 3 === 0;\n    case exports.Patterns.PATTERN011:\n      return (i + j) % 3 === 0;\n    case exports.Patterns.PATTERN100:\n      return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 === 0;\n    case exports.Patterns.PATTERN101:\n      return i * j % 2 + i * j % 3 === 0;\n    case exports.Patterns.PATTERN110:\n      return (i * j % 2 + i * j % 3) % 2 === 0;\n    case exports.Patterns.PATTERN111:\n      return (i * j % 3 + (i + j) % 2) % 2 === 0;\n    default:\n      throw new Error('bad maskPattern:' + maskPattern);\n  }\n}\n\n/**\n * Apply a mask pattern to a BitMatrix\n *\n * @param  {Number}    pattern Pattern reference number\n * @param  {BitMatrix} data    BitMatrix data\n */\nexports.applyMask = function applyMask(pattern, data) {\n  const size = data.size;\n  for (let col = 0; col < size; col++) {\n    for (let row = 0; row < size; row++) {\n      if (data.isReserved(row, col)) continue;\n      data.xor(row, col, getMaskAt(pattern, row, col));\n    }\n  }\n};\n\n/**\n * Returns the best mask pattern for data\n *\n * @param  {BitMatrix} data\n * @return {Number} Mask pattern reference number\n */\nexports.getBestMask = function getBestMask(data, setupFormatFunc) {\n  const numPatterns = Object.keys(exports.Patterns).length;\n  let bestPattern = 0;\n  let lowerPenalty = Infinity;\n  for (let p = 0; p < numPatterns; p++) {\n    setupFormatFunc(p);\n    exports.applyMask(p, data);\n\n    // Calculate penalty\n    const penalty = exports.getPenaltyN1(data) + exports.getPenaltyN2(data) + exports.getPenaltyN3(data) + exports.getPenaltyN4(data);\n\n    // Undo previously applied mask\n    exports.applyMask(p, data);\n    if (penalty < lowerPenalty) {\n      lowerPenalty = penalty;\n      bestPattern = p;\n    }\n  }\n  return bestPattern;\n};","map":null,"metadata":{},"sourceType":"script","externalDependencies":[]}