UNPKG

qrcode-generator-ts

Version:

Typescript QR Code generator based on https://github.com/kazuhikoarase/qrcode-generator

292 lines (243 loc) 8.11 kB
import { Mode } from './Mode'; import { ErrorCorrectLevel } from './ErrorCorrectLevel'; import { Polynomial } from './Polynomial'; import { QRMath } from './QRMath'; import { MaskPattern } from './MaskPattern'; import { QRCode } from './QRCode'; 'use strict'; /** * QRUtil * @author Kazuhiko Arase */ export class QRUtil { constructor() { throw 'error'; } public static getPatternPosition(typeNumber: number): number[] { return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1]; } private static 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] ]; private static MAX_LENGTH = [ [[41, 25, 17, 10], [34, 20, 14, 8], [27, 16, 11, 7], [17, 10, 7, 4]], [[77, 47, 32, 20], [63, 38, 26, 16], [48, 29, 20, 12], [34, 20, 14, 8]], [[127, 77, 53, 32], [101, 61, 42, 26], [77, 47, 32, 20], [58, 35, 24, 15]], [[187, 114, 78, 48], [149, 90, 62, 38], [111, 67, 46, 28], [82, 50, 34, 21]], [[255, 154, 106, 65], [202, 122, 84, 52], [144, 87, 60, 37], [106, 64, 44, 27]], [[322, 195, 134, 82], [255, 154, 106, 65], [178, 108, 74, 45], [139, 84, 58, 36]], [[370, 224, 154, 95], [293, 178, 122, 75], [207, 125, 86, 53], [154, 93, 64, 39]], [[461, 279, 192, 118], [365, 221, 152, 93], [259, 157, 108, 66], [202, 122, 84, 52]], [[552, 335, 230, 141], [432, 262, 180, 111], [312, 189, 130, 80], [235, 143, 98, 60]], [[652, 395, 271, 167], [513, 311, 213, 131], [364, 221, 151, 93], [288, 174, 119, 74]] ]; public static getMaxLength( typeNumber: number, mode: Mode, errorCorrectLevel: ErrorCorrectLevel ): number { var t = typeNumber - 1; var e = 0; var m = 0; switch (errorCorrectLevel) { case ErrorCorrectLevel.L: e = 0; break; case ErrorCorrectLevel.M: e = 1; break; case ErrorCorrectLevel.Q: e = 2; break; case ErrorCorrectLevel.H: e = 3; break; default: throw 'e:' + errorCorrectLevel; } switch (mode) { case Mode.MODE_NUMBER: m = 0; break; case Mode.MODE_ALPHA_NUM: m = 1; break; case Mode.MODE_8BIT_BYTE: m = 2; break; case Mode.MODE_KANJI: m = 3; break; default: throw 'm:' + mode; } return QRUtil.MAX_LENGTH[t][e][m]; } public static getErrorCorrectPolynomial( errorCorrectLength: number): Polynomial { var a = new Polynomial([1]); for (var i = 0; i < errorCorrectLength; i += 1) { a = a.multiply(new Polynomial([1, QRMath.gexp(i)])); } return a; } public static getMaskFunc( maskPattern: number ): (i: number, j: number) => boolean { switch (maskPattern) { case MaskPattern.PATTERN000: return (i: number, j: number) => (i + j) % 2 == 0; case MaskPattern.PATTERN001: return (i: number, j: number) => i % 2 == 0; case MaskPattern.PATTERN010: return (i: number, j: number) => j % 3 == 0; case MaskPattern.PATTERN011: return (i: number, j: number) => (i + j) % 3 == 0; case MaskPattern.PATTERN100: return (i: number, j: number) => (~~(i / 2) + ~~(j / 3)) % 2 == 0; case MaskPattern.PATTERN101: return (i: number, j: number) => (i * j) % 2 + (i * j) % 3 == 0; case MaskPattern.PATTERN110: return (i: number, j: number) => ((i * j) % 2 + (i * j) % 3) % 2 == 0; case MaskPattern.PATTERN111: return (i: number, j: number) => ((i * j) % 3 + (i + j) % 2) % 2 == 0; default: throw 'mask:' + maskPattern; } } public static getLostPoint(qrCode: QRCode): number { var moduleCount = qrCode.getModuleCount(); var lostPoint = 0; // LEVEL1 for (var row = 0; row < moduleCount; row += 1) { for (var col = 0; col < moduleCount; col += 1) { var sameCount = 0; var dark = qrCode.isDark(row, col); for (var r = -1; r <= 1; r += 1) { if (row + r < 0 || moduleCount <= row + r) { continue; } for (var 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 (var row = 0; row < moduleCount - 1; row += 1) { for (var col = 0; col < moduleCount - 1; col += 1) { var 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 (var row = 0; row < moduleCount; row += 1) { for (var 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 (var col = 0; col < moduleCount; col += 1) { for (var 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 var darkCount = 0; for (var col = 0; col < moduleCount; col += 1) { for (var row = 0; row < moduleCount; row += 1) { if (qrCode.isDark(row, col)) { darkCount += 1; } } } var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5; lostPoint += ratio * 10; return lostPoint; } public static getBCHTypeInfo(data: number): number { var d = data << 10; while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) { d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15))); } return ((data << 10) | d) ^ QRUtil.G15_MASK; } public static getBCHTypeNumber(data: number): number { var d = data << 12; while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) { d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18))); } return (data << 12) | d; } private static G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0); private static G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0); private static G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1); private static getBCHDigit(data: number): number { var digit = 0; while (data != 0) { digit += 1; data >>>= 1; } return digit; } }