1 | var QRMode = require('./QRMode');
|
2 | var QRPolynomial = require('./QRPolynomial');
|
3 | var QRMath = require('./QRMath');
|
4 | var QRMaskPattern = require('./QRMaskPattern');
|
5 |
|
6 | var QRUtil = {
|
7 |
|
8 | PATTERN_POSITION_TABLE : [
|
9 | [],
|
10 | [6, 18],
|
11 | [6, 22],
|
12 | [6, 26],
|
13 | [6, 30],
|
14 | [6, 34],
|
15 | [6, 22, 38],
|
16 | [6, 24, 42],
|
17 | [6, 26, 46],
|
18 | [6, 28, 50],
|
19 | [6, 30, 54],
|
20 | [6, 32, 58],
|
21 | [6, 34, 62],
|
22 | [6, 26, 46, 66],
|
23 | [6, 26, 48, 70],
|
24 | [6, 26, 50, 74],
|
25 | [6, 30, 54, 78],
|
26 | [6, 30, 56, 82],
|
27 | [6, 30, 58, 86],
|
28 | [6, 34, 62, 90],
|
29 | [6, 28, 50, 72, 94],
|
30 | [6, 26, 50, 74, 98],
|
31 | [6, 30, 54, 78, 102],
|
32 | [6, 28, 54, 80, 106],
|
33 | [6, 32, 58, 84, 110],
|
34 | [6, 30, 58, 86, 114],
|
35 | [6, 34, 62, 90, 118],
|
36 | [6, 26, 50, 74, 98, 122],
|
37 | [6, 30, 54, 78, 102, 126],
|
38 | [6, 26, 52, 78, 104, 130],
|
39 | [6, 30, 56, 82, 108, 134],
|
40 | [6, 34, 60, 86, 112, 138],
|
41 | [6, 30, 58, 86, 114, 142],
|
42 | [6, 34, 62, 90, 118, 146],
|
43 | [6, 30, 54, 78, 102, 126, 150],
|
44 | [6, 24, 50, 76, 102, 128, 154],
|
45 | [6, 28, 54, 80, 106, 132, 158],
|
46 | [6, 32, 58, 84, 110, 136, 162],
|
47 | [6, 26, 54, 82, 110, 138, 166],
|
48 | [6, 30, 58, 86, 114, 142, 170]
|
49 | ],
|
50 |
|
51 | G15 : (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0),
|
52 | G18 : (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0),
|
53 | G15_MASK : (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1),
|
54 |
|
55 | getBCHTypeInfo : function(data) {
|
56 | var d = data << 10;
|
57 | while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) {
|
58 | d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) ) );
|
59 | }
|
60 | return ( (data << 10) | d) ^ QRUtil.G15_MASK;
|
61 | },
|
62 |
|
63 | getBCHTypeNumber : function(data) {
|
64 | var d = data << 12;
|
65 | while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) {
|
66 | d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) ) );
|
67 | }
|
68 | return (data << 12) | d;
|
69 | },
|
70 |
|
71 | getBCHDigit : function(data) {
|
72 |
|
73 | var digit = 0;
|
74 |
|
75 | while (data != 0) {
|
76 | digit++;
|
77 | data >>>= 1;
|
78 | }
|
79 |
|
80 | return digit;
|
81 | },
|
82 |
|
83 | getPatternPosition : function(typeNumber) {
|
84 | return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1];
|
85 | },
|
86 |
|
87 | getMask : function(maskPattern, i, j) {
|
88 |
|
89 | switch (maskPattern) {
|
90 |
|
91 | case QRMaskPattern.PATTERN000 : return (i + j) % 2 == 0;
|
92 | case QRMaskPattern.PATTERN001 : return i % 2 == 0;
|
93 | case QRMaskPattern.PATTERN010 : return j % 3 == 0;
|
94 | case QRMaskPattern.PATTERN011 : return (i + j) % 3 == 0;
|
95 | case QRMaskPattern.PATTERN100 : return (Math.floor(i / 2) + Math.floor(j / 3) ) % 2 == 0;
|
96 | case QRMaskPattern.PATTERN101 : return (i * j) % 2 + (i * j) % 3 == 0;
|
97 | case QRMaskPattern.PATTERN110 : return ( (i * j) % 2 + (i * j) % 3) % 2 == 0;
|
98 | case QRMaskPattern.PATTERN111 : return ( (i * j) % 3 + (i + j) % 2) % 2 == 0;
|
99 |
|
100 | default :
|
101 | throw new Error("bad maskPattern:" + maskPattern);
|
102 | }
|
103 | },
|
104 |
|
105 | getErrorCorrectPolynomial : function(errorCorrectLength) {
|
106 |
|
107 | var a = new QRPolynomial([1], 0);
|
108 |
|
109 | for (var i = 0; i < errorCorrectLength; i++) {
|
110 | a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0) );
|
111 | }
|
112 |
|
113 | return a;
|
114 | },
|
115 |
|
116 | getLengthInBits : function(mode, type) {
|
117 |
|
118 | if (1 <= type && type < 10) {
|
119 |
|
120 |
|
121 |
|
122 | switch(mode) {
|
123 | case QRMode.MODE_NUMBER : return 10;
|
124 | case QRMode.MODE_ALPHA_NUM : return 9;
|
125 | case QRMode.MODE_8BIT_BYTE : return 8;
|
126 | case QRMode.MODE_KANJI : return 8;
|
127 | default :
|
128 | throw new Error("mode:" + mode);
|
129 | }
|
130 |
|
131 | } else if (type < 27) {
|
132 |
|
133 |
|
134 |
|
135 | switch(mode) {
|
136 | case QRMode.MODE_NUMBER : return 12;
|
137 | case QRMode.MODE_ALPHA_NUM : return 11;
|
138 | case QRMode.MODE_8BIT_BYTE : return 16;
|
139 | case QRMode.MODE_KANJI : return 10;
|
140 | default :
|
141 | throw new Error("mode:" + mode);
|
142 | }
|
143 |
|
144 | } else if (type < 41) {
|
145 |
|
146 |
|
147 |
|
148 | switch(mode) {
|
149 | case QRMode.MODE_NUMBER : return 14;
|
150 | case QRMode.MODE_ALPHA_NUM : return 13;
|
151 | case QRMode.MODE_8BIT_BYTE : return 16;
|
152 | case QRMode.MODE_KANJI : return 12;
|
153 | default :
|
154 | throw new Error("mode:" + mode);
|
155 | }
|
156 |
|
157 | } else {
|
158 | throw new Error("type:" + type);
|
159 | }
|
160 | },
|
161 |
|
162 | getLostPoint : function(qrCode) {
|
163 |
|
164 | var moduleCount = qrCode.getModuleCount();
|
165 |
|
166 | var lostPoint = 0;
|
167 |
|
168 |
|
169 |
|
170 | for (var row = 0; row < moduleCount; row++) {
|
171 |
|
172 | for (var col = 0; col < moduleCount; col++) {
|
173 |
|
174 | var sameCount = 0;
|
175 | var dark = qrCode.isDark(row, col);
|
176 |
|
177 | for (var r = -1; r <= 1; r++) {
|
178 |
|
179 | if (row + r < 0 || moduleCount <= row + r) {
|
180 | continue;
|
181 | }
|
182 |
|
183 | for (var c = -1; c <= 1; c++) {
|
184 |
|
185 | if (col + c < 0 || moduleCount <= col + c) {
|
186 | continue;
|
187 | }
|
188 |
|
189 | if (r == 0 && c == 0) {
|
190 | continue;
|
191 | }
|
192 |
|
193 | if (dark == qrCode.isDark(row + r, col + c) ) {
|
194 | sameCount++;
|
195 | }
|
196 | }
|
197 | }
|
198 |
|
199 | if (sameCount > 5) {
|
200 | lostPoint += (3 + sameCount - 5);
|
201 | }
|
202 | }
|
203 | }
|
204 |
|
205 |
|
206 |
|
207 | for (var row = 0; row < moduleCount - 1; row++) {
|
208 | for (var col = 0; col < moduleCount - 1; col++) {
|
209 | var count = 0;
|
210 | if (qrCode.isDark(row, col ) ) count++;
|
211 | if (qrCode.isDark(row + 1, col ) ) count++;
|
212 | if (qrCode.isDark(row, col + 1) ) count++;
|
213 | if (qrCode.isDark(row + 1, col + 1) ) count++;
|
214 | if (count == 0 || count == 4) {
|
215 | lostPoint += 3;
|
216 | }
|
217 | }
|
218 | }
|
219 |
|
220 |
|
221 |
|
222 | for (var row = 0; row < moduleCount; row++) {
|
223 | for (var col = 0; col < moduleCount - 6; col++) {
|
224 | if (qrCode.isDark(row, col)
|
225 | && !qrCode.isDark(row, col + 1)
|
226 | && qrCode.isDark(row, col + 2)
|
227 | && qrCode.isDark(row, col + 3)
|
228 | && qrCode.isDark(row, col + 4)
|
229 | && !qrCode.isDark(row, col + 5)
|
230 | && qrCode.isDark(row, col + 6) ) {
|
231 | lostPoint += 40;
|
232 | }
|
233 | }
|
234 | }
|
235 |
|
236 | for (var col = 0; col < moduleCount; col++) {
|
237 | for (var row = 0; row < moduleCount - 6; row++) {
|
238 | if (qrCode.isDark(row, col)
|
239 | && !qrCode.isDark(row + 1, col)
|
240 | && qrCode.isDark(row + 2, col)
|
241 | && qrCode.isDark(row + 3, col)
|
242 | && qrCode.isDark(row + 4, col)
|
243 | && !qrCode.isDark(row + 5, col)
|
244 | && qrCode.isDark(row + 6, col) ) {
|
245 | lostPoint += 40;
|
246 | }
|
247 | }
|
248 | }
|
249 |
|
250 |
|
251 |
|
252 | var darkCount = 0;
|
253 |
|
254 | for (var col = 0; col < moduleCount; col++) {
|
255 | for (var row = 0; row < moduleCount; row++) {
|
256 | if (qrCode.isDark(row, col) ) {
|
257 | darkCount++;
|
258 | }
|
259 | }
|
260 | }
|
261 |
|
262 | var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
|
263 | lostPoint += ratio * 10;
|
264 |
|
265 | return lostPoint;
|
266 | }
|
267 |
|
268 | };
|
269 |
|
270 | module.exports = QRUtil;
|