UNPKG

qrcoder

Version:

QRCoder is *a pure browser qrcode generation* which is standalone. It is based on a <a href='http://www.d-project.com/qrcode/index.html'>library</a> which build qrcode in various language.

249 lines (234 loc) 7 kB
import { QRMaskPattern, QRMode } from './constant' import QRPolynomial from './qrpolynomial' import { QRMath } from './qrmath' const PATTERN_POSITION_TABLE = [ [], [6, 18], [6, 22], [6, 26], [6, 30], [6, 34], [6, 22, 38], [6, 24, 42], [6, 26, 46], [6, 28, 50], [6, 30, 54], [6, 32, 58], [6, 34, 62], [6, 26, 46, 66], [6, 26, 48, 70], [6, 26, 50, 74], [6, 30, 54, 78], [6, 30, 56, 82], [6, 30, 58, 86], [6, 34, 62, 90], [6, 28, 50, 72, 94], [6, 26, 50, 74, 98], [6, 30, 54, 78, 102], [6, 28, 54, 80, 106], [6, 32, 58, 84, 110], [6, 30, 58, 86, 114], [6, 34, 62, 90, 118], [6, 26, 50, 74, 98, 122], [6, 30, 54, 78, 102, 126], [6, 26, 52, 78, 104, 130], [6, 30, 56, 82, 108, 134], [6, 34, 60, 86, 112, 138], [6, 30, 58, 86, 114, 142], [6, 34, 62, 90, 118, 146], [6, 30, 54, 78, 102, 126, 150], [6, 24, 50, 76, 102, 128, 154], [6, 28, 54, 80, 106, 132, 158], [6, 32, 58, 84, 110, 136, 162], [6, 26, 54, 82, 110, 138, 166], [6, 30, 58, 86, 114, 142, 170] ] const G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0) const G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0) const G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1) function getBCHDigit (data) { var digit = 0 while (data !== 0) { digit += 1 data >>>= 1 } return digit } export const QRUtil = { getBCHTypeInfo: function (data) { let d = data << 10 while (getBCHDigit(d) - getBCHDigit(G15) >= 0) { d ^= (G15 << (getBCHDigit(d) - getBCHDigit(G15))) } return ((data << 10) | d) ^ G15_MASK }, getBCHTypeNumber: function (data) { let d = data << 12 while (getBCHDigit(d) - getBCHDigit(G18) >= 0) { d ^= (G18 << (getBCHDigit(d) - getBCHDigit(G18))) } return (data << 12) | d }, getPatternPosition: function (typeNumber) { return PATTERN_POSITION_TABLE[typeNumber - 1] }, getMaskFunction: function (maskPattern) { switch (maskPattern) { case QRMaskPattern.PATTERN000: return function (i, j) { return (i + j) % 2 === 0 } case QRMaskPattern.PATTERN001: return function (i) { return i % 2 === 0 } case QRMaskPattern.PATTERN010: return function (i, j) { return j % 3 === 0 } case QRMaskPattern.PATTERN011: return function (i, j) { return (i + j) % 3 === 0 } case QRMaskPattern.PATTERN100: return function (i, j) { return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 === 0 } case QRMaskPattern.PATTERN101: return function (i, j) { return (i * j) % 2 + (i * j) % 3 === 0 } case QRMaskPattern.PATTERN110: return function (i, j) { return ((i * j) % 2 + (i * j) % 3) % 2 === 0 } case QRMaskPattern.PATTERN111: return function (i, j) { return ((i * j) % 3 + (i + j) % 2) % 2 === 0 } default : throw new Error('bad maskPattern:' + maskPattern) } }, getErrorCorrectPolynomial: function (errorCorrectLength) { let a = new QRPolynomial([1], 0) for (let i = 0; i < errorCorrectLength; i += 1) { a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0)) } return a }, getLengthInBits: function (mode, type) { if (type >= 1 && type < 10) { // 1 - 9 switch (mode) { case QRMode.MODE_NUMBER: return 10 case QRMode.MODE_ALPHA_NUM: return 9 case QRMode.MODE_8BIT_BYTE: return 8 case QRMode.MODE_KANJI: return 8 default : throw new Error('mode:' + mode) } } else if (type < 27) { // 10 - 26 switch (mode) { case QRMode.MODE_NUMBER: return 12 case QRMode.MODE_ALPHA_NUM: return 11 case QRMode.MODE_8BIT_BYTE: return 16 case QRMode.MODE_KANJI: return 10 default : throw new Error('mode:' + mode) } } else if (type < 41) { // 27 - 40 switch (mode) { case QRMode.MODE_NUMBER: return 14 case QRMode.MODE_ALPHA_NUM: return 13 case QRMode.MODE_8BIT_BYTE: return 16 case QRMode.MODE_KANJI: return 12 default : throw new Error('mode:' + mode) } } else { throw new Error('type:' + type) } }, getLostPoint: function (qrcode) { let moduleCount = qrcode.getModuleCount() let lostPoint = 0 // LEVEL1 for (let row = 0; row < moduleCount; row += 1) { for (let col = 0; col < moduleCount; col += 1) { let sameCount = 0 let dark = qrcode.isDark(row, col) for (let r = -1; r <= 1; r += 1) { if (row + r < 0 || moduleCount <= row + r) { continue } for (let c = -1; c <= 1; c += 1) { if (col + c < 0 || moduleCount <= col + c) { continue } if (r === 0 && c === 0) { continue } if (dark === qrcode.isDark(row + r, col + c)) { sameCount += 1 } } } if (sameCount > 5) { lostPoint += (3 + sameCount - 5) } } } // LEVEL2 for (let row = 0; row < moduleCount - 1; row += 1) { for (let col = 0; col < moduleCount - 1; col += 1) { let count = 0 if (qrcode.isDark(row, col)) count += 1 if (qrcode.isDark(row + 1, col)) count += 1 if (qrcode.isDark(row, col + 1)) count += 1 if (qrcode.isDark(row + 1, col + 1)) count += 1 if (count === 0 || count === 4) { lostPoint += 3 } } } // LEVEL3 for (let row = 0; row < moduleCount; row += 1) { for (let col = 0; col < moduleCount - 6; col += 1) { if (qrcode.isDark(row, col) && !qrcode.isDark(row, col + 1) && qrcode.isDark(row, col + 2) && qrcode.isDark(row, col + 3) && qrcode.isDark(row, col + 4) && !qrcode.isDark(row, col + 5) && qrcode.isDark(row, col + 6)) { lostPoint += 40 } } } for (let col = 0; col < moduleCount; col += 1) { for (let row = 0; row < moduleCount - 6; row += 1) { if (qrcode.isDark(row, col) && !qrcode.isDark(row + 1, col) && qrcode.isDark(row + 2, col) && qrcode.isDark(row + 3, col) && qrcode.isDark(row + 4, col) && !qrcode.isDark(row + 5, col) && qrcode.isDark(row + 6, col)) { lostPoint += 40 } } } // LEVEL4 let darkCount = 0 for (let col = 0; col < moduleCount; col += 1) { for (let row = 0; row < moduleCount; row += 1) { if (qrcode.isDark(row, col)) { darkCount += 1 } } } let ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5 lostPoint += ratio * 10 return lostPoint } } export default QRUtil