]>
git.immae.eu Git - github/shaarli/Shaarli.git/blob - plugins/qrcode/qr-1.1.3.js
1 // [qr.js](http://neocotic.com/qr.js)
2 // (c) 2014 Alasdair Mercer
3 // Licensed under the GPL Version 3 license.
4 // Based on [jsqrencode](http://code.google.com/p/jsqrencode/)
5 // (c) 2010 tz@execpc.com
6 // Licensed under the GPL Version 3 license.
7 // For all details and documentation:
8 // <http://neocotic.com/qr.js>
18 var ALIGNMENT_DELTA
= [
19 0, 11, 15, 19, 23, 27, 31,
20 16, 18, 20, 22, 24, 26, 28, 20, 22, 24, 24, 26, 28, 28, 22, 24, 24,
21 26, 26, 28, 28, 24, 24, 26, 26, 26, 28, 28, 24, 26, 26, 26, 28, 28
24 var DEFAULT_MIME
= 'image/png';
25 // MIME used to initiate a browser download prompt when `qr.save` is called.
26 var DOWNLOAD_MIME
= 'image/octet-stream';
27 // There are four elements per version. The first two indicate the number of blocks, then the
28 // data width, and finally the ECC width.
30 1, 0, 19, 7, 1, 0, 16, 10, 1, 0, 13, 13, 1, 0, 9, 17,
31 1, 0, 34, 10, 1, 0, 28, 16, 1, 0, 22, 22, 1, 0, 16, 28,
32 1, 0, 55, 15, 1, 0, 44, 26, 2, 0, 17, 18, 2, 0, 13, 22,
33 1, 0, 80, 20, 2, 0, 32, 18, 2, 0, 24, 26, 4, 0, 9, 16,
34 1, 0, 108, 26, 2, 0, 43, 24, 2, 2, 15, 18, 2, 2, 11, 22,
35 2, 0, 68, 18, 4, 0, 27, 16, 4, 0, 19, 24, 4, 0, 15, 28,
36 2, 0, 78, 20, 4, 0, 31, 18, 2, 4, 14, 18, 4, 1, 13, 26,
37 2, 0, 97, 24, 2, 2, 38, 22, 4, 2, 18, 22, 4, 2, 14, 26,
38 2, 0, 116, 30, 3, 2, 36, 22, 4, 4, 16, 20, 4, 4, 12, 24,
39 2, 2, 68, 18, 4, 1, 43, 26, 6, 2, 19, 24, 6, 2, 15, 28,
40 4, 0, 81, 20, 1, 4, 50, 30, 4, 4, 22, 28, 3, 8, 12, 24,
41 2, 2, 92, 24, 6, 2, 36, 22, 4, 6, 20, 26, 7, 4, 14, 28,
42 4, 0, 107, 26, 8, 1, 37, 22, 8, 4, 20, 24, 12, 4, 11, 22,
43 3, 1, 115, 30, 4, 5, 40, 24, 11, 5, 16, 20, 11, 5, 12, 24,
44 5, 1, 87, 22, 5, 5, 41, 24, 5, 7, 24, 30, 11, 7, 12, 24,
45 5, 1, 98, 24, 7, 3, 45, 28, 15, 2, 19, 24, 3, 13, 15, 30,
46 1, 5, 107, 28, 10, 1, 46, 28, 1, 15, 22, 28, 2, 17, 14, 28,
47 5, 1, 120, 30, 9, 4, 43, 26, 17, 1, 22, 28, 2, 19, 14, 28,
48 3, 4, 113, 28, 3, 11, 44, 26, 17, 4, 21, 26, 9, 16, 13, 26,
49 3, 5, 107, 28, 3, 13, 41, 26, 15, 5, 24, 30, 15, 10, 15, 28,
50 4, 4, 116, 28, 17, 0, 42, 26, 17, 6, 22, 28, 19, 6, 16, 30,
51 2, 7, 111, 28, 17, 0, 46, 28, 7, 16, 24, 30, 34, 0, 13, 24,
52 4, 5, 121, 30, 4, 14, 47, 28, 11, 14, 24, 30, 16, 14, 15, 30,
53 6, 4, 117, 30, 6, 14, 45, 28, 11, 16, 24, 30, 30, 2, 16, 30,
54 8, 4, 106, 26, 8, 13, 47, 28, 7, 22, 24, 30, 22, 13, 15, 30,
55 10, 2, 114, 28, 19, 4, 46, 28, 28, 6, 22, 28, 33, 4, 16, 30,
56 8, 4, 122, 30, 22, 3, 45, 28, 8, 26, 23, 30, 12, 28, 15, 30,
57 3, 10, 117, 30, 3, 23, 45, 28, 4, 31, 24, 30, 11, 31, 15, 30,
58 7, 7, 116, 30, 21, 7, 45, 28, 1, 37, 23, 30, 19, 26, 15, 30,
59 5, 10, 115, 30, 19, 10, 47, 28, 15, 25, 24, 30, 23, 25, 15, 30,
60 13, 3, 115, 30, 2, 29, 46, 28, 42, 1, 24, 30, 23, 28, 15, 30,
61 17, 0, 115, 30, 10, 23, 46, 28, 10, 35, 24, 30, 19, 35, 15, 30,
62 17, 1, 115, 30, 14, 21, 46, 28, 29, 19, 24, 30, 11, 46, 15, 30,
63 13, 6, 115, 30, 14, 23, 46, 28, 44, 7, 24, 30, 59, 1, 16, 30,
64 12, 7, 121, 30, 12, 26, 47, 28, 39, 14, 24, 30, 22, 41, 15, 30,
65 6, 14, 121, 30, 6, 34, 47, 28, 46, 10, 24, 30, 2, 64, 15, 30,
66 17, 4, 122, 30, 29, 14, 46, 28, 49, 10, 24, 30, 24, 46, 15, 30,
67 4, 18, 122, 30, 13, 32, 46, 28, 48, 14, 24, 30, 42, 32, 15, 30,
68 20, 4, 117, 30, 40, 7, 47, 28, 43, 22, 24, 30, 10, 67, 15, 30,
69 19, 6, 118, 30, 18, 31, 47, 28, 34, 34, 24, 30, 20, 61, 15, 30
71 // Map of human-readable ECC levels.
78 // Final format bits with mask (level << 3 | mask).
80 0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976, /* L */
81 0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, /* M */
82 0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed, /* Q */
83 0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b /* H */
85 // Galois field exponent table.
86 var GALOIS_EXPONENT
= [
87 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26,
88 0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0,
89 0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23,
90 0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1,
91 0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0,
92 0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2,
93 0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce,
94 0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc,
95 0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54,
96 0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73,
97 0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff,
98 0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41,
99 0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6,
100 0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09,
101 0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16,
102 0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x00
104 // Galois field log table.
106 0xff, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b,
107 0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71,
108 0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45,
109 0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6,
110 0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88,
111 0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40,
112 0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d,
113 0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57,
114 0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18,
115 0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e,
116 0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61,
117 0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2,
118 0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6,
119 0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a,
120 0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7,
121 0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf
123 // *Badness* coefficients.
129 var VERSION_BLOCK
= [
130 0xc94, 0x5bc, 0xa99, 0x4d3, 0xbf6, 0x762, 0x847, 0x60d, 0x928, 0xb78, 0x45d, 0xa17, 0x532,
131 0x9a6, 0x683, 0x8c9, 0x7ec, 0xec4, 0x1e1, 0xfab, 0x08e, 0xc1a, 0x33f, 0xd75, 0x250, 0x9d5,
132 0x6f0, 0x8ba, 0x79f, 0xb0b, 0x42e, 0xa64, 0x541, 0xc69
134 // Mode for node.js file system file writes.
135 var WRITE_MODE
= parseInt('0666', 8);
140 // Run lengths for badness.
142 // Constructor for `canvas` elements in the node.js environment.
146 // ECC data blocks and tables.
147 var eccBlock
, neccBlock1
, neccBlock2
;
150 // ECC level (defaults to **L**).
153 var frameBuffer
= [];
154 // Fixed part of the image.
156 // File system within the node.js environment.
158 // Constructor for `img` elements in the node.js environment.
160 // Indicates whether or not this script is running in node.js.
162 // Generator polynomial.
164 // Save the previous value of the `qr` variable.
165 var previousQr
= root
.qr
;
166 // Data input buffer.
167 var stringBuffer
= [];
168 // Version for the data.
170 // Data width is based on `version`.
176 // Create a new canvas using `document.createElement` unless script is running in node.js, in
177 // which case the `canvas` module is used.
178 function createCanvas() {
179 return inNode
? new Canvas() : root
.document
.createElement('canvas');
182 // Create a new image using `document.createElement` unless script is running in node.js, in
183 // which case the `canvas` module is used.
184 function createImage() {
185 return inNode
? new Image() : root
.document
.createElement('img');
188 // Force the canvas image to be downloaded in the browser.
189 // Optionally, a `callback` function can be specified which will be called upon completed. Since
190 // this is not an asynchronous operation, this is merely convenient and helps simplify the
192 function download(cvs
, data
, callback
) {
193 var mime
= data
.mime
|| DEFAULT_MIME
;
195 root
.location
.href
= cvs
.toDataURL(mime
).replace(mime
, DOWNLOAD_MIME
);
197 if (typeof callback
=== 'function') callback();
200 // Normalize the `data` that is provided to the main API.
201 function normalizeData(data
) {
202 if (typeof data
=== 'string') data
= { value: data
};
206 // Override the `qr` API methods that require HTML5 canvas support to throw a relevant error.
207 function overrideAPI(qr
) {
208 var methods
= [ 'canvas', 'image', 'save', 'saveSync', 'toDataURL' ];
211 function overrideMethod(name
) {
212 qr
[name
] = function () {
213 throw new Error(name
+ ' requires HTML5 canvas element support');
217 for (i
= 0; i
< methods
.length
; i
++) {
218 overrideMethod(methods
[i
]);
222 // Asynchronously write the data of the rendered canvas to a given file path.
223 function writeFile(cvs
, data
, callback
) {
224 if (typeof data
.path
!== 'string') {
225 return callback(new TypeError('Invalid path type: ' + typeof data
.path
));
230 // Write the buffer to the open file stream once both prerequisites are met.
231 function writeBuffer() {
232 fs
.write(fd
, buff
, 0, buff
.length
, 0, function (error
) {
239 // Create a buffer of the canvas' data.
240 cvs
.toBuffer(function (error
, _buff
) {
241 if (error
) return callback(error
);
249 // Open a stream for the file to be written.
250 fs
.open(data
.path
, 'w', WRITE_MODE
, function (error
, _fd
) {
251 if (error
) return callback(error
);
260 // Write the data of the rendered canvas to a given file path.
261 function writeFileSync(cvs
, data
) {
262 if (typeof data
.path
!== 'string') {
263 throw new TypeError('Invalid path type: ' + typeof data
.path
);
266 var buff
= cvs
.toBuffer();
267 var fd
= fs
.openSync(data
.path
, 'w', WRITE_MODE
);
270 fs
.writeSync(fd
, buff
, 0, buff
.length
, 0);
276 // Set bit to indicate cell in frame is immutable (symmetric around diagonal).
277 function setMask(x
, y
) {
295 // Enter alignment pattern. Foreground colour to frame, background to mask. Frame will be merged
297 function addAlignment(x
, y
) {
300 frameBuffer
[x
+ width
* y
] = 1;
302 for (i
= -2; i
< 2; i
++) {
303 frameBuffer
[(x
+ i
) + width
* (y
- 2)] = 1;
304 frameBuffer
[(x
- 2) + width
* (y
+ i
+ 1)] = 1;
305 frameBuffer
[(x
+ 2) + width
* (y
+ i
)] = 1;
306 frameBuffer
[(x
+ i
+ 1) + width
* (y
+ 2)] = 1;
309 for (i
= 0; i
< 2; i
++) {
310 setMask(x
- 1, y
+ i
);
311 setMask(x
+ 1, y
- i
);
312 setMask(x
- i
, y
- 1);
313 setMask(x
+ i
, y
+ 1);
317 // Exponentiation mod N.
321 x
= (x
>> 8) + (x
& 255);
327 // Calculate and append `ecc` data to the `data` block. If block is in the string buffer the
328 // indices to buffers are used.
329 function appendData(data
, dataLength
, ecc
, eccLength
) {
332 for (i
= 0; i
< eccLength
; i
++) {
333 stringBuffer
[ecc
+ i
] = 0;
336 for (i
= 0; i
< dataLength
; i
++) {
337 bit
= GALOIS_LOG
[stringBuffer
[data
+ i
] ^ stringBuffer
[ecc
]];
340 for (j
= 1; j
< eccLength
; j
++) {
341 stringBuffer
[ecc
+ j
- 1] = stringBuffer
[ecc
+ j
] ^
342 GALOIS_EXPONENT
[modN(bit
+ polynomial
[eccLength
- j
])];
345 for (j
= ecc
; j
< ecc
+ eccLength
; j
++) {
346 stringBuffer
[j
] = stringBuffer
[j
+ 1];
350 stringBuffer
[ecc
+ eccLength
- 1] = bit
=== 255 ? 0 :
351 GALOIS_EXPONENT
[modN(bit
+ polynomial
[0])];
355 // Check mask since symmetricals use half.
356 function isMasked(x
, y
) {
370 return frameMask
[bit
] === 1;
373 // Apply the selected mask out of the 8 options.
374 function applyMask(mask
) {
379 for (y
= 0; y
< width
; y
++) {
380 for (x
= 0; x
< width
; x
++) {
381 if (!((x
+ y
) & 1) && !isMasked(x
, y
)) {
382 frameBuffer
[x
+ y
* width
] ^= 1;
389 for (y
= 0; y
< width
; y
++) {
390 for (x
= 0; x
< width
; x
++) {
391 if (!(y
& 1) && !isMasked(x
, y
)) {
392 frameBuffer
[x
+ y
* width
] ^= 1;
399 for (y
= 0; y
< width
; y
++) {
400 for (r3x
= 0, x
= 0; x
< width
; x
++, r3x
++) {
401 if (r3x
=== 3) r3x
= 0;
403 if (!r3x
&& !isMasked(x
, y
)) {
404 frameBuffer
[x
+ y
* width
] ^= 1;
411 for (r3y
= 0, y
= 0; y
< width
; y
++, r3y
++) {
412 if (r3y
=== 3) r3y
= 0;
414 for (r3x
= r3y
, x
= 0; x
< width
; x
++, r3x
++) {
415 if (r3x
=== 3) r3x
= 0;
417 if (!r3x
&& !isMasked(x
, y
)) {
418 frameBuffer
[x
+ y
* width
] ^= 1;
425 for (y
= 0; y
< width
; y
++) {
426 for (r3x
= 0, r3y
= ((y
>> 1) & 1), x
= 0; x
< width
; x
++, r3x
++) {
432 if (!r3y
&& !isMasked(x
, y
)) {
433 frameBuffer
[x
+ y
* width
] ^= 1;
440 for (r3y
= 0, y
= 0; y
< width
; y
++, r3y
++) {
441 if (r3y
=== 3) r3y
= 0;
443 for (r3x
= 0, x
= 0; x
< width
; x
++, r3x
++) {
444 if (r3x
=== 3) r3x
= 0;
446 if (!((x
& y
& 1) + !(!r3x
| !r3y
)) && !isMasked(x
, y
)) {
447 frameBuffer
[x
+ y
* width
] ^= 1;
454 for (r3y
= 0, y
= 0; y
< width
; y
++, r3y
++) {
455 if (r3y
=== 3) r3y
= 0;
457 for (r3x
= 0, x
= 0; x
< width
; x
++, r3x
++) {
458 if (r3x
=== 3) r3x
= 0;
460 if (!(((x
& y
& 1) + (r3x
&& (r3x
=== r3y
))) & 1) && !isMasked(x
, y
)) {
461 frameBuffer
[x
+ y
* width
] ^= 1;
468 for (r3y
= 0, y
= 0; y
< width
; y
++, r3y
++) {
469 if (r3y
=== 3) r3y
= 0;
471 for (r3x
= 0, x
= 0; x
< width
; x
++, r3x
++) {
472 if (r3x
=== 3) r3x
= 0;
474 if (!(((r3x
&& (r3x
=== r3y
)) + ((x
+ y
) & 1)) & 1) && !isMasked(x
, y
)) {
475 frameBuffer
[x
+ y
* width
] ^= 1;
484 // Using the table for the length of each run, calculate the amount of bad image. Long runs or
485 // those that look like finders are called twice; once for X and Y.
486 function getBadRuns(length
) {
490 for (i
= 0; i
<= length
; i
++) {
491 if (badBuffer
[i
] >= 5) {
492 badRuns
+= N1
+ badBuffer
[i
] - 5;
496 // FBFFFBF as in finder.
497 for (i
= 3; i
< length
- 1; i
+= 2) {
498 if (badBuffer
[i
- 2] === badBuffer
[i
+ 2] &&
499 badBuffer
[i
+ 2] === badBuffer
[i
- 1] &&
500 badBuffer
[i
- 1] === badBuffer
[i
+ 1] &&
501 badBuffer
[i
- 1] * 3 === badBuffer
[i
] &&
502 // Background around the foreground pattern? Not part of the specs.
503 (badBuffer
[i
- 3] === 0 || i
+ 3 > length
||
504 badBuffer
[i
- 3] * 3 >= badBuffer
[i
] * 4 ||
505 badBuffer
[i
+ 3] * 3 >= badBuffer
[i
] * 4)) {
513 // Calculate how bad the masked image is (e.g. blocks, imbalance, runs, or finders).
514 function checkBadness() {
515 var b
, b1
, bad
, big
, bw
, count
, h
, x
, y
;
516 bad
= bw
= count
= 0;
518 // Blocks of same colour.
519 for (y
= 0; y
< width
- 1; y
++) {
520 for (x
= 0; x
< width
- 1; x
++) {
521 // All foreground colour.
522 if ((frameBuffer
[x
+ width
* y
] &&
523 frameBuffer
[(x
+ 1) + width
* y
] &&
524 frameBuffer
[x
+ width
* (y
+ 1)] &&
525 frameBuffer
[(x
+ 1) + width
* (y
+ 1)]) ||
526 // All background colour.
527 !(frameBuffer
[x
+ width
* y
] ||
528 frameBuffer
[(x
+ 1) + width
* y
] ||
529 frameBuffer
[x
+ width
* (y
+ 1)] ||
530 frameBuffer
[(x
+ 1) + width
* (y
+ 1)])) {
537 for (y
= 0; y
< width
; y
++) {
540 for (h
= b
= x
= 0; x
< width
; x
++) {
541 if ((b1
= frameBuffer
[x
+ width
* y
]) === b
) {
551 bad
+= getBadRuns(h
);
554 if (bw
< 0) bw
= -bw
;
560 while (big
> width
* width
) {
561 big
-= width
* width
;
568 for (x
= 0; x
< width
; x
++) {
571 for (h
= b
= y
= 0; y
< width
; y
++) {
572 if ((b1
= frameBuffer
[x
+ width
* y
]) === b
) {
581 bad
+= getBadRuns(h
);
587 // Generate the encoded QR image for the string provided.
588 function generateFrame(str
) {
589 var i
, j
, k
, m
, t
, v
, x
, y
;
591 // Find the smallest version that fits the string.
599 k
= (eccLevel
- 1) * 4 + (version
- 1) * 16;
601 neccBlock1
= ECC_BLOCKS
[k
++];
602 neccBlock2
= ECC_BLOCKS
[k
++];
603 dataBlock
= ECC_BLOCKS
[k
++];
604 eccBlock
= ECC_BLOCKS
[k
];
606 k
= dataBlock
* (neccBlock1
+ neccBlock2
) + neccBlock2
- 3 + (version
<= 9);
609 } while (version
< 40);
611 // FIXME: Ensure that it fits insted of being truncated.
612 width
= 17 + 4 * version
;
614 // Allocate, clear and setup data structures.
615 v
= dataBlock
+ (dataBlock
+ eccBlock
) * (neccBlock1
+ neccBlock2
) + neccBlock2
;
617 for (t
= 0; t
< v
; t
++) {
621 stringBuffer
= str
.slice(0);
623 for (t
= 0; t
< width
* width
; t
++) {
627 for (t
= 0; t
< (width
* (width
+ 1) + 1) / 2; t
++) {
631 // Insert finders: Foreground colour to frame and background to mask.
632 for (t
= 0; t
< 3; t
++) {
635 if (t
=== 1) k
= (width
- 7);
636 if (t
=== 2) y
= (width
- 7);
638 frameBuffer
[(y
+ 3) + width
* (k
+ 3)] = 1;
640 for (x
= 0; x
< 6; x
++) {
641 frameBuffer
[(y
+ x
) + width
* k
] = 1;
642 frameBuffer
[y
+ width
* (k
+ x
+ 1)] = 1;
643 frameBuffer
[(y
+ 6) + width
* (k
+ x
)] = 1;
644 frameBuffer
[(y
+ x
+ 1) + width
* (k
+ 6)] = 1;
647 for (x
= 1; x
< 5; x
++) {
648 setMask(y
+ x
, k
+ 1);
649 setMask(y
+ 1, k
+ x
+ 1);
650 setMask(y
+ 5, k
+ x
);
651 setMask(y
+ x
+ 1, k
+ 5);
654 for (x
= 2; x
< 4; x
++) {
655 frameBuffer
[(y
+ x
) + width
* (k
+ 2)] = 1;
656 frameBuffer
[(y
+ 2) + width
* (k
+ x
+ 1)] = 1;
657 frameBuffer
[(y
+ 4) + width
* (k
+ x
)] = 1;
658 frameBuffer
[(y
+ x
+ 1) + width
* (k
+ 4)] = 1;
664 t
= ALIGNMENT_DELTA
[version
];
678 if (y
<= t
+ 9) break;
687 // Single foreground cell.
688 frameBuffer
[8 + width
* (width
- 8)] = 1;
690 // Timing gap (mask only).
691 for (y
= 0; y
< 7; y
++) {
693 setMask(width
- 8, y
);
694 setMask(7, y
+ width
- 7);
697 for (x
= 0; x
< 8; x
++) {
699 setMask(x
+ width
- 8, 7);
700 setMask(x
, width
- 8);
703 // Reserve mask, format area.
704 for (x
= 0; x
< 9; x
++) {
708 for (x
= 0; x
< 8; x
++) {
709 setMask(x
+ width
- 8, 8);
713 for (y
= 0; y
< 7; y
++) {
714 setMask(8, y
+ width
- 7);
717 // Timing row/column.
718 for (x
= 0; x
< width
- 14; x
++) {
723 frameBuffer
[(8 + x
) + width
* 6] = 1;
724 frameBuffer
[6 + width
* (8 + x
)] = 1;
730 t
= VERSION_BLOCK
[version
- 7];
733 for (x
= 0; x
< 6; x
++) {
734 for (y
= 0; y
< 3; y
++, k
--) {
735 if (1 & (k
> 11 ? version
>> (k
- 12) : t
>> k
)) {
736 frameBuffer
[(5 - x
) + width
* (2 - y
+ width
- 11)] = 1;
737 frameBuffer
[(2 - y
+ width
- 11) + width
* (5 - x
)] = 1;
739 setMask(5 - x
, 2 - y
+ width
- 11);
740 setMask(2 - y
+ width
- 11, 5 - x
);
746 // Sync mask bits. Only set above for background cells, so now add the foreground.
747 for (y
= 0; y
< width
; y
++) {
748 for (x
= 0; x
<= y
; x
++) {
749 if (frameBuffer
[x
+ width
* y
]) {
755 // Convert string to bit stream. 8-bit data to QR-coded 8-bit data (numeric, alphanum, or kanji
757 v
= stringBuffer
.length
;
760 for (i
= 0; i
< v
; i
++) {
761 eccBuffer
[i
] = stringBuffer
.charCodeAt(i
);
764 stringBuffer
= eccBuffer
.slice(0);
766 // Calculate max string length.
767 x
= dataBlock
* (neccBlock1
+ neccBlock2
) + neccBlock2
;
772 if (version
> 9) v
--;
775 // Shift and re-pack to insert length prefix.
779 stringBuffer
[i
+ 2] = 0;
780 stringBuffer
[i
+ 3] = 0;
785 stringBuffer
[i
+ 3] |= 255 & (t
<< 4);
786 stringBuffer
[i
+ 2] = t
>> 4;
789 stringBuffer
[2] |= 255 & (v
<< 4);
790 stringBuffer
[1] = v
>> 4;
791 stringBuffer
[0] = 0x40 | (v
>> 12);
793 stringBuffer
[i
+ 1] = 0;
794 stringBuffer
[i
+ 2] = 0;
799 stringBuffer
[i
+ 2] |= 255 & (t
<< 4);
800 stringBuffer
[i
+ 1] = t
>> 4;
803 stringBuffer
[1] |= 255 & (v
<< 4);
804 stringBuffer
[0] = 0x40 | (v
>> 4);
807 // Fill to end with pad pattern.
808 i
= v
+ 3 - (version
< 10);
811 stringBuffer
[i
++] = 0xec;
812 stringBuffer
[i
++] = 0x11;
815 // Calculate generator polynomial.
818 for (i
= 0; i
< eccBlock
; i
++) {
819 polynomial
[i
+ 1] = 1;
821 for (j
= i
; j
> 0; j
--) {
822 polynomial
[j
] = polynomial
[j
] ? polynomial
[j
- 1] ^
823 GALOIS_EXPONENT
[modN(GALOIS_LOG
[polynomial
[j
]] + i
)] : polynomial
[j
- 1];
826 polynomial
[0] = GALOIS_EXPONENT
[modN(GALOIS_LOG
[polynomial
[0]] + i
)];
829 // Use logs for generator polynomial to save calculation step.
830 for (i
= 0; i
<= eccBlock
; i
++) {
831 polynomial
[i
] = GALOIS_LOG
[polynomial
[i
]];
834 // Append ECC to data buffer.
838 for (i
= 0; i
< neccBlock1
; i
++) {
839 appendData(y
, dataBlock
, k
, eccBlock
);
845 for (i
= 0; i
< neccBlock2
; i
++) {
846 appendData(y
, dataBlock
+ 1, k
, eccBlock
);
852 // Interleave blocks.
855 for (i
= 0; i
< dataBlock
; i
++) {
856 for (j
= 0; j
< neccBlock1
; j
++) {
857 eccBuffer
[y
++] = stringBuffer
[i
+ j
* dataBlock
];
860 for (j
= 0; j
< neccBlock2
; j
++) {
861 eccBuffer
[y
++] = stringBuffer
[(neccBlock1
* dataBlock
) + i
+ (j
* (dataBlock
+ 1))];
865 for (j
= 0; j
< neccBlock2
; j
++) {
866 eccBuffer
[y
++] = stringBuffer
[(neccBlock1
* dataBlock
) + i
+ (j
* (dataBlock
+ 1))];
869 for (i
= 0; i
< eccBlock
; i
++) {
870 for (j
= 0; j
< neccBlock1
+ neccBlock2
; j
++) {
871 eccBuffer
[y
++] = stringBuffer
[x
+ i
+ j
* eccBlock
];
875 stringBuffer
= eccBuffer
;
877 // Pack bits into frame avoiding masked area.
881 // inteleaved data and ECC codes.
882 m
= (dataBlock
+ eccBlock
) * (neccBlock1
+ neccBlock2
) + neccBlock2
;
884 for (i
= 0; i
< m
; i
++) {
887 for (j
= 0; j
< 8; j
++, t
<<= 1) {
889 frameBuffer
[x
+ width
* y
] = 1;
892 // Find next fill position.
912 if (y
!== width
- 1) {
927 } while (isMasked(x
, y
));
931 // Save pre-mask copy of frame.
932 stringBuffer
= frameBuffer
.slice(0);
937 // Using `for` instead of `while` since in original Arduino code if an early mask was *good
938 // enough* it wouldn't try for a better one since they get more complex and take longer.
939 for (k
= 0; k
< 8; k
++) {
940 // Returns foreground-background imbalance.
945 // Is current mask better than previous best?
951 // Don't increment `i` to a void redoing mask.
954 // Reset for next pass.
955 frameBuffer
= stringBuffer
.slice(0);
958 // Redo best mask as none were *good enough* (i.e. last wasn't `t`).
963 // Add in final mask/ECC level bytes.
964 y
= FINAL_FORMAT
[t
+ ((eccLevel
- 1) << 3)];
967 for (k
= 0; k
< 8; k
++, y
>>= 1) {
969 frameBuffer
[(width
- 1 - k
) + width
* 8] = 1;
972 frameBuffer
[8 + width
* k
] = 1;
974 frameBuffer
[8 + width
* (k
+ 1)] = 1;
980 for (k
= 0; k
< 7; k
++, y
>>= 1) {
982 frameBuffer
[8 + width
* (width
- 7 + k
)] = 1;
985 frameBuffer
[(6 - k
) + width
* 8] = 1;
987 frameBuffer
[7 + width
* 8] = 1;
992 // Finally, return the image data.
999 // Build the publicly exposed API.
1005 // Current version of `qr`.
1011 // Generate the QR code using the data provided and render it on to a `<canvas>` element.
1012 // If no `<canvas>` element is specified in the argument provided a new one will be created and
1014 // ECC (error correction capacity) determines how many intential errors are contained in the QR
1016 canvas: function(data
) {
1017 data
= normalizeData(data
);
1019 // Module size of the generated QR code (i.e. 1-10).
1020 var size
= data
.size
>= 1 && data
.size
<= 10 ? data
.size : 4;
1021 // Actual size of the QR code symbol and is scaled to 25 pixels (e.g. 1 = 25px, 3 = 75px).
1024 // `<canvas>` element used to render the QR code.
1025 var cvs
= data
.canvas
|| createCanvas();
1026 // Retreive the 2D context of the canvas.
1027 var c2d
= cvs
.getContext('2d');
1028 // Ensure the canvas has the correct dimensions.
1029 c2d
.canvas
.width
= size
;
1030 c2d
.canvas
.height
= size
;
1031 // Fill the canvas with the correct background colour.
1032 c2d
.fillStyle
= data
.background
|| '#fff';
1033 c2d
.fillRect(0, 0, size
, size
);
1035 // Determine the ECC level to be applied.
1036 eccLevel
= ECC_LEVELS
[(data
.level
&& data
.level
.toUpperCase()) || 'L'];
1038 // Generate the image frame for the given `value`.
1039 var frame
= generateFrame(data
.value
|| '');
1043 // Determine the *pixel* size.
1046 px
= Math
.floor(px
);
1048 // Draw the QR code.
1049 c2d
.clearRect(0, 0, size
, size
);
1050 c2d
.fillStyle
= data
.background
|| '#fff';
1051 c2d
.fillRect(0, 0, px
* (width
+ 8), px
* (width
+ 8));
1052 c2d
.fillStyle
= data
.foreground
|| '#000';
1056 for (i
= 0; i
< width
; i
++) {
1057 for (j
= 0; j
< width
; j
++) {
1058 if (frame
[j
* width
+ i
]) {
1059 c2d
.fillRect(px
* i
, px
* j
, px
, px
);
1067 // Generate the QR code using the data provided and render it on to a `<img>` element.
1068 // If no `<img>` element is specified in the argument provided a new one will be created and
1070 // ECC (error correction capacity) determines how many intential errors are contained in the QR
1072 image: function(data
) {
1073 data
= normalizeData(data
);
1075 // `<canvas>` element only which the QR code is rendered.
1076 var cvs
= this.canvas(data
);
1077 // `<img>` element used to display the QR code.
1078 var img
= data
.image
|| createImage();
1080 // Apply the QR code to `img`.
1081 img
.src
= cvs
.toDataURL(data
.mime
|| DEFAULT_MIME
);
1082 img
.height
= cvs
.height
;
1083 img
.width
= cvs
.width
;
1088 // Generate the QR code using the data provided and render it on to a `<canvas>` element and
1089 // save it as an image file.
1090 // If no `<canvas>` element is specified in the argument provided a new one will be created and
1092 // ECC (error correction capacity) determines how many intential errors are contained in the QR
1094 // If called in a browser the `path` property/argument is ignored and will simply prompt the
1095 // user to choose a location and file name. However, if called within node.js the file will be
1096 // saved to specified path.
1097 // A `callback` function must be provided which will be called once the saving process has
1098 // started. If an error occurs it will be passed as the first argument to this function,
1099 // otherwise this argument will be `null`.
1100 save: function(data
, path
, callback
) {
1101 data
= normalizeData(data
);
1103 switch (typeof path
) {
1113 // Callback function is required.
1114 if (typeof callback
!== 'function') {
1115 throw new TypeError('Invalid callback type: ' + typeof callback
);
1118 var completed
= false;
1119 // `<canvas>` element only which the QR code is rendered.
1120 var cvs
= this.canvas(data
);
1122 // Simple function to try and ensure that the `callback` function is only called once.
1123 function done(error
) {
1132 writeFile(cvs
, data
, done
);
1134 download(cvs
, data
, done
);
1138 // Generate the QR code using the data provided and render it on to a `<canvas>` element and
1139 // save it as an image file.
1140 // If no `<canvas>` element is specified in the argument provided a new one will be created and
1142 // ECC (error correction capacity) determines how many intential errors are contained in the QR
1144 // If called in a browser the `path` property/argument is ignored and will simply prompt the
1145 // user to choose a location and file name. However, if called within node.js the file will be
1146 // saved to specified path.
1147 saveSync: function(data
, path
) {
1148 data
= normalizeData(data
);
1150 if (typeof path
=== 'string') data
.path
= path
;
1152 // `<canvas>` element only which the QR code is rendered.
1153 var cvs
= this.canvas(data
);
1156 writeFileSync(cvs
, data
);
1158 download(cvs
, data
);
1162 // Generate the QR code using the data provided and render it on to a `<canvas>` element before
1163 // returning its data URI.
1164 // If no `<canvas>` element is specified in the argument provided a new one will be created and
1166 // ECC (error correction capacity) determines how many intential errors are contained in the QR
1168 toDataURL: function(data
) {
1169 data
= normalizeData(data
);
1171 return this.canvas(data
).toDataURL(data
.mime
|| DEFAULT_MIME
);
1174 // Utility functions
1175 // -----------------
1177 // Run qr.js in *noConflict* mode, returning the `qr` variable to its previous owner.
1178 // Returns a reference to `qr`.
1179 noConflict: function() {
1180 root
.qr
= previousQr
;
1189 // Export `qr` for node.js and CommonJS.
1190 if (typeof exports
!== 'undefined') {
1193 if (typeof module
!== 'undefined' && module
.exports
) {
1194 exports
= module
.exports
= qr
;
1198 // Import required node.js modules.
1199 Canvas
= require('canvas');
1200 Image
= Canvas
.Image
;
1202 } else if (typeof define
=== 'function' && define
.amd
) {
1203 define(function () {
1207 // In non-HTML5 browser so strip base functionality.
1208 if (!root
.HTMLCanvasElement
) {