├── .gitignore
├── README.md
├── style.css
├── halftoneQR.html
├── halftoneqr.js
└── qrcode.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .AppleDouble
3 | .LSOverride
4 |
5 | # Icon must end with two \r
6 | Icon
7 |
8 | # Thumbnails
9 | ._*
10 |
11 | # Files that might appear on external disk
12 | .Spotlight-V100
13 | .Trashes
14 |
15 | # Directories potentially created on remote AFP share
16 | .AppleDB
17 | .AppleDesktop
18 | Network Trash Folder
19 | Temporary Items
20 | .apdisk
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Halftone-QRCode-Generator
2 | Halftone QR Code Generator by Lachlan Arthur
3 |
4 | from http://jsfiddle.net/lachlan/r8qWV/
5 |
6 | More about halftone QRCode:
7 |
8 | http://vecg.cs.ucl.ac.uk/Projects/SmartGeometry/halftone_QR/halftoneQR_sigga13.html
9 | http://www.jianshu.com/p/46a4e210a542
10 | http://spacekid.me/halftone-qr-code-generator/
11 | https://zhuanlan.zhihu.com/p/20728355
12 |
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 |
2 | html, body {
3 | height: 100%;
4 | margin: 0;
5 | }
6 |
7 | body {
8 | position: relative;
9 | }
10 |
11 | h1, h2 {
12 | margin: 0;
13 | }
14 |
15 | #overlay {
16 | display: none;
17 | position: fixed;
18 | top: 0;
19 | left: 0;
20 | width: 100%;
21 | height: 100%;
22 | background-color: rgba(0,0,0,0.5);
23 | z-index: 10;
24 | font-size: 100px;
25 | color: white;
26 | text-align: center;
27 | }
28 |
29 | body.hover #overlay {
30 | display: block;
31 | }
32 |
33 | canvas {
34 | margin: 5px;
35 | box-shadow: 0 0 5px black;
36 | }
37 |
38 | /* Hidden for now */
39 | #imagePixel {
40 | display: none;
41 | }
42 |
43 | #output {
44 | background-color: grey;
45 | }
46 |
--------------------------------------------------------------------------------
/halftoneQR.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Halftone QR Code Generator
6 |
7 |
8 |
9 |
10 |
11 |
12 | Halftone QR Code Generator
13 | Drop an image into your browser, then click generate.
14 | QR content:
15 |
16 | Redundancy (error correction level):
17 |
23 | QR size:
24 | (6 gives the largest blank square area)
37 | Background Type:
38 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | By Lachlan
50 |
51 | Cat photo by Cayambe [CC-BY-SA-3.0 or GFDL], via Wikimedia Commons
52 |
53 | Drop image
54 |
55 |
--------------------------------------------------------------------------------
/halftoneqr.js:
--------------------------------------------------------------------------------
1 | var pixelSize = 2;
2 | var blockSize = (3*pixelSize);
3 | var image;
4 | var has_image = false;
5 |
6 | function halftoneQR(QRBytes, controlBytes, image) {
7 |
8 | var canvas = $('#output').get(0);
9 | canvas.width = canvas.height = QRBytes.length * (3*pixelSize);
10 | var ctx = canvas.getContext('2d');
11 | var background = $('#background').val();
12 |
13 | $('#imageColour, #imageThreshold, #imagePixel').attr({
14 | width: canvas.width,
15 | height: canvas.height
16 | });
17 | if (has_image) {
18 | // Re-draw image (incase size changed)
19 | drawImage();
20 | }
21 |
22 | ctx.clearRect(0, 0, canvas.width, canvas.height);
23 |
24 | var canvasThreshold = $('#imageThreshold').get(0);
25 | var ctxThreshold = canvasThreshold.getContext('2d');
26 |
27 | if (has_image && background === 'image') {
28 | ctx.drawImage(canvasThreshold, 0, 0, canvas.width, canvas.height);
29 | }
30 |
31 | for (var byteRow = 0; byteRow < QRBytes.length; byteRow++) {
32 | for (var byteCell = 0; byteCell < QRBytes[byteRow].length; byteCell++) {
33 |
34 | if ((background === 'image' && !has_image) || background === 'noise') {
35 | // Draw random bytes
36 | ctx.fillStyle = 'black';
37 | for (var subRow = 0; subRow < 3; subRow++) {
38 | for (var subCell = 0; subCell < 3; subCell++) {
39 | ctx.fillStyle = 'black';
40 | if (Math.random() < 0.5) {
41 | ctx.fillStyle = 'white';
42 | }
43 | ctx.fillRect(byteRow * blockSize + (subRow * pixelSize), byteCell * blockSize + (subCell * pixelSize), pixelSize, pixelSize);
44 | }
45 | }
46 | }
47 |
48 | // Middle Cell
49 | ctx.fillStyle = QRBytes[byteRow][byteCell] ? 'black' : 'white';
50 | ctx.fillRect(byteRow * blockSize + pixelSize, byteCell * blockSize + pixelSize, pixelSize, pixelSize);
51 | }
52 | }
53 |
54 | // Re-draw control bytes
55 | for (var byteRow = 0; byteRow < controlBytes.length; byteRow++) {
56 | for (var byteCell = 0; byteCell < controlBytes[byteRow].length; byteCell++) {
57 | if (controlBytes[byteRow][byteCell] !== null) {
58 | if (controlBytes[byteRow][byteCell] === true) {
59 | ctx.fillStyle = 'black';
60 | } else {
61 | ctx.fillStyle = 'white';
62 | }
63 | ctx.fillRect(byteRow * blockSize, byteCell * blockSize, blockSize, blockSize);
64 | }
65 | };
66 | };
67 |
68 | $('#download').attr('href', $('#output').get(0).toDataURL());
69 |
70 | }
71 |
72 | function drawImage() {
73 | var canvasColour = $('#imageColour').get(0);
74 | var ctxColour = canvasColour.getContext('2d');
75 |
76 | ctxColour.clearRect(0,0,canvasColour.width, canvasColour.height);
77 | ctxColour.drawImage(image, 0, 0, canvasColour.width, canvasColour.height);
78 |
79 | drawPixel();
80 | }
81 |
82 | function drawPixel() {
83 | var canvasColour = $('#imageColour').get(0);
84 | var canvasPixel = $('#imagePixel').get(0);
85 | var ctxPixel = canvasPixel.getContext('2d');
86 | var canvasTemp = document.createElement('canvas');
87 | canvasTemp.width = canvasTemp.height = (canvasPixel.width / pixelSize);
88 | var ctxTemp = canvasTemp.getContext('2d');
89 |
90 | ctxPixel.imageSmoothingEnabled =
91 | ctxPixel.mozImageSmoothingEnabled =
92 | ctxPixel.msImageSmoothingEnabled =
93 | ctxPixel.webkitImageSmoothingEnabled =
94 | ctxTemp.imageSmoothingEnabled =
95 | ctxTemp.mozImageSmoothingEnabled =
96 | ctxTemp.msImageSmoothingEnabled =
97 | ctxTemp.webkitImageSmoothingEnabled = false;
98 |
99 | ctxTemp.drawImage(canvasColour, 0, 0, canvasTemp.width, canvasTemp.height);
100 | ctxPixel.drawImage(canvasTemp, 0, 0, canvasPixel.width, canvasPixel.height);
101 |
102 | drawThreshold();
103 | }
104 |
105 | function drawThreshold() {
106 | var canvasPixel = $('#imagePixel').get(0);
107 | var ctxPixel = canvasPixel.getContext('2d');
108 | var canvasThreshold = $('#imageThreshold').get(0);
109 | var ctxThreshold = canvasThreshold.getContext('2d');
110 |
111 | var pixels = ctxPixel.getImageData(0,0,canvasPixel.width,canvasPixel.height);
112 | var d = pixels.data;
113 | var width = Math.sqrt(d.length / 4) / pixelSize;
114 | for (var i=0; i= 127) ? 255 : 0;
120 | //d[i] = d[i+1] = d[i+2] = v;
121 | d[i] = d[i+1] = d[i+2] = grey;
122 | }
123 |
124 | for (var i=0; i= 127) ? 255 : 0;
127 |
128 | // Dithering
129 | var error = (grey - v) / 8;
130 | var i2 = i / 4;
131 | var row = Math.floor(i2 / width);
132 | var cell = i2 % width;
133 |
134 | d[i] = d[i+1] = d[i+2] = v;
135 |
136 | d[(((row + 0) * width) + (cell + 1)) * 4] = d[(((row + 0) * width) + (cell + 1)) * 4 + 1] = d[(((row + 0) * width) + (cell + 1)) * 4 + 2] = d[(((row + 0) * width) + (cell + 1)) * 4] + error;
137 | d[(((row + 0) * width) + (cell + 2)) * 4] = d[(((row + 0) * width) + (cell + 2)) * 4 + 1] = d[(((row + 0) * width) + (cell + 2)) * 4 + 2] = d[(((row + 0) * width) + (cell + 2)) * 4] + error;
138 | d[(((row + 1) * width) + (cell - 1)) * 4] = d[(((row + 1) * width) + (cell - 1)) * 4 + 1] = d[(((row + 1) * width) + (cell - 1)) * 4 + 2] = d[(((row + 1) * width) + (cell - 1)) * 4] + error;
139 | d[(((row + 1) * width) + (cell + 0)) * 4] = d[(((row + 1) * width) + (cell + 0)) * 4 + 1] = d[(((row + 1) * width) + (cell + 0)) * 4 + 2] = d[(((row + 1) * width) + (cell + 0)) * 4] + error;
140 | d[(((row + 1) * width) + (cell + 1)) * 4] = d[(((row + 1) * width) + (cell + 1)) * 4 + 1] = d[(((row + 1) * width) + (cell + 1)) * 4 + 2] = d[(((row + 1) * width) + (cell + 1)) * 4] + error;
141 | d[(((row + 2) * width) + (cell + 0)) * 4] = d[(((row + 2) * width) + (cell + 0)) * 4 + 1] = d[(((row + 2) * width) + (cell + 0)) * 4 + 2] = d[(((row + 2) * width) + (cell + 0)) * 4] + error;
142 | }
143 | ctxThreshold.putImageData(pixels, 0, 0);
144 | }
145 | $(function(){
146 | $('body').on('dragover', function(e) {
147 | e.preventDefault();
148 | $('body').addClass('hover');
149 | });
150 | $('#overlay').on('dragend dragleave', function(e) {
151 | e.preventDefault();
152 | $('body').removeClass('hover');
153 | });
154 | $('#overlay').on('drop', function(e) {
155 | e.preventDefault();
156 | $('body').removeClass('hover');
157 |
158 | var file = e.originalEvent.dataTransfer.files[0],
159 | reader = new FileReader();
160 | reader.onload = function(event) {
161 | //event.target.result;
162 | var imageColour = new Image();
163 | imageColour.onload = function() {
164 | has_image = true;
165 | image = this;
166 | drawImage();
167 | }
168 | imageColour.src = event.target.result;
169 | };
170 | reader.readAsDataURL(file);
171 |
172 | return false;
173 | });
174 |
175 | $(function() {
176 |
177 | $('#go').on('click', function() {
178 | var text = $('#input').val();
179 |
180 | var errorLevel = $('#error_level').val();
181 |
182 | var sizes = {
183 | L: [152, 272, 440, 640, 864, 1088, 1248, 1552, 1856, 1240],
184 | M: [128, 224, 352, 512, 688, 864, 992, 700, 700, 524],
185 | Q: [104, 176, 272, 384, 286, 608, 508, 376, 608, 434],
186 | H: [72, 128, 208, 288, 214, 480, 164, 296, 464, 346]
187 | };
188 |
189 | var userSize = parseInt($('#size').val());
190 | var QRsize = -1;
191 | if (userSize === 0) {
192 | for (var i = 0; i < sizes[errorLevel].length; i++) {
193 | if (text.length < sizes[errorLevel][i]) {
194 | QRsize = i + 1;
195 | break;
196 | }
197 | };
198 | } else {
199 | if (text.length < sizes[errorLevel][userSize - 1]) {
200 | QRsize = userSize;
201 | }
202 | }
203 | if (QRsize == -1) {
204 | if (userSize === 0) {
205 | if (errorLevel === 'H') {
206 | alert('Too much text.');
207 | } else {
208 | alert('Too much text. Try decreasing the error level.');
209 | }
210 | } else {
211 | alert('Too much text. Try decreasing the error level or increasing the size.');
212 | }
213 | return;
214 | }
215 |
216 | var qr = qrcode(QRsize, errorLevel);
217 | qr.addData(text);
218 | qr.make();
219 |
220 | var controls = qrcode(QRsize, errorLevel);
221 | controls.addData(text);
222 | controls.make(true);
223 |
224 | halftoneQR(qr.returnByteArray(), controls.returnByteArray());
225 |
226 | });
227 |
228 | // First load (cat)
229 | var imageColour = new Image();
230 | imageColour.onload = function() {
231 | has_image = true;
232 | image = this;
233 | $('#go').triggerHandler('click');
234 | }
235 | imageColour.src = 'data:image/jpeg;base64,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';
236 |
237 | });
238 | })
239 |
240 |
--------------------------------------------------------------------------------
/qrcode.js:
--------------------------------------------------------------------------------
1 | //---------------------------------------------------------------------
2 | //
3 | // QR Code Generator for JavaScript
4 | //
5 | // Copyright (c) 2009 Kazuhiko Arase
6 | //
7 | // URL: http://www.d-project.com/
8 | //
9 | // Licensed under the MIT license:
10 | // http://www.opensource.org/licenses/mit-license.php
11 | //
12 | // The word 'QR Code' is registered trademark of
13 | // DENSO WAVE INCORPORATED
14 | // http://www.denso-wave.com/qrcode/faqpatent-e.html
15 | //
16 | //---------------------------------------------------------------------
17 |
18 | var qrcode = function() {
19 |
20 | //---------------------------------------------------------------------
21 | // qrcode
22 | //---------------------------------------------------------------------
23 |
24 | /**
25 | * qrcode
26 | * @param typeNumber 1 to 10
27 | * @param errorCorrectLevel 'L','M','Q','H'
28 | */
29 | var qrcode = function(typeNumber, errorCorrectLevel) {
30 |
31 | var PAD0 = 0xEC;
32 | var PAD1 = 0x11;
33 |
34 | var _typeNumber = typeNumber;
35 | var _errorCorrectLevel = QRErrorCorrectLevel[errorCorrectLevel];
36 | var _modules = null;
37 | var _moduleCount = 0;
38 | var _dataCache = null;
39 | var _dataList = new Array();
40 |
41 | var _this = {};
42 |
43 | var makeImpl = function(test, maskPattern, onlyControl) {
44 |
45 | onlyControl = onlyControl || false;
46 | _moduleCount = _typeNumber * 4 + 17;
47 | _modules = function(moduleCount) {
48 | var modules = new Array(moduleCount);
49 | for (var row = 0; row < moduleCount; row += 1) {
50 | modules[row] = new Array(moduleCount);
51 | for (var col = 0; col < moduleCount; col += 1) {
52 | modules[row][col] = null;
53 | }
54 | }
55 | return modules;
56 | }(_moduleCount);
57 |
58 | setupPositionProbePattern(0, 0);
59 | setupPositionProbePattern(_moduleCount - 7, 0);
60 | setupPositionProbePattern(0, _moduleCount - 7);
61 | setupPositionAdjustPattern();
62 | setupTimingPattern();
63 | setupTypeInfo(test, maskPattern);
64 |
65 | if (_typeNumber >= 7) {
66 | setupTypeNumber(test);
67 | }
68 |
69 | if (!onlyControl) {
70 | if (_dataCache == null) {
71 | _dataCache = createData(_typeNumber, _errorCorrectLevel, _dataList);
72 | }
73 |
74 | mapData(_dataCache, maskPattern);
75 | }
76 | };
77 |
78 | var setupPositionProbePattern = function(row, col) {
79 |
80 | for (var r = -1; r <= 7; r += 1) {
81 |
82 | if (row + r <= -1 || _moduleCount <= row + r) continue;
83 |
84 | for (var c = -1; c <= 7; c += 1) {
85 |
86 | if (col + c <= -1 || _moduleCount <= col + c) continue;
87 |
88 | if ( (0 <= r && r <= 6 && (c == 0 || c == 6) )
89 | || (0 <= c && c <= 6 && (r == 0 || r == 6) )
90 | || (2 <= r && r <= 4 && 2 <= c && c <= 4) ) {
91 | _modules[row + r][col + c] = true;
92 | } else {
93 | _modules[row + r][col + c] = false;
94 | }
95 | }
96 | }
97 | };
98 |
99 | var getBestMaskPattern = function() {
100 |
101 | var minLostPoint = 0;
102 | var pattern = 0;
103 |
104 | for (var i = 0; i < 8; i += 1) {
105 |
106 | makeImpl(true, i);
107 |
108 | var lostPoint = QRUtil.getLostPoint(_this);
109 |
110 | if (i == 0 || minLostPoint > lostPoint) {
111 | minLostPoint = lostPoint;
112 | pattern = i;
113 | }
114 | }
115 |
116 | return pattern;
117 | };
118 |
119 | var setupTimingPattern = function() {
120 |
121 | for (var r = 8; r < _moduleCount - 8; r += 1) {
122 | if (_modules[r][6] != null) {
123 | continue;
124 | }
125 | _modules[r][6] = (r % 2 == 0);
126 | }
127 |
128 | for (var c = 8; c < _moduleCount - 8; c += 1) {
129 | if (_modules[6][c] != null) {
130 | continue;
131 | }
132 | _modules[6][c] = (c % 2 == 0);
133 | }
134 | };
135 |
136 | var setupPositionAdjustPattern = function() {
137 |
138 | var pos = QRUtil.getPatternPosition(_typeNumber);
139 |
140 | for (var i = 0; i < pos.length; i += 1) {
141 |
142 | for (var j = 0; j < pos.length; j += 1) {
143 |
144 | var row = pos[i];
145 | var col = pos[j];
146 |
147 | if (_modules[row][col] != null) {
148 | continue;
149 | }
150 |
151 | for (var r = -2; r <= 2; r += 1) {
152 |
153 | for (var c = -2; c <= 2; c += 1) {
154 |
155 | if (r == -2 || r == 2 || c == -2 || c == 2
156 | || (r == 0 && c == 0) ) {
157 | _modules[row + r][col + c] = true;
158 | } else {
159 | _modules[row + r][col + c] = false;
160 | }
161 | }
162 | }
163 | }
164 | }
165 | };
166 |
167 | var setupTypeNumber = function(test) {
168 |
169 | var bits = QRUtil.getBCHTypeNumber(_typeNumber);
170 |
171 | for (var i = 0; i < 18; i += 1) {
172 | var mod = (!test && ( (bits >> i) & 1) == 1);
173 | _modules[Math.floor(i / 3)][i % 3 + _moduleCount - 8 - 3] = mod;
174 | }
175 |
176 | for (var i = 0; i < 18; i += 1) {
177 | var mod = (!test && ( (bits >> i) & 1) == 1);
178 | _modules[i % 3 + _moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
179 | }
180 | };
181 |
182 | var setupTypeInfo = function(test, maskPattern) {
183 |
184 | var data = (_errorCorrectLevel << 3) | maskPattern;
185 | var bits = QRUtil.getBCHTypeInfo(data);
186 |
187 | // vertical
188 | for (var i = 0; i < 15; i += 1) {
189 |
190 | var mod = (!test && ( (bits >> i) & 1) == 1);
191 |
192 | if (i < 6) {
193 | _modules[i][8] = mod;
194 | } else if (i < 8) {
195 | _modules[i + 1][8] = mod;
196 | } else {
197 | _modules[_moduleCount - 15 + i][8] = mod;
198 | }
199 | }
200 |
201 | // horizontal
202 | for (var i = 0; i < 15; i += 1) {
203 |
204 | var mod = (!test && ( (bits >> i) & 1) == 1);
205 |
206 | if (i < 8) {
207 | _modules[8][_moduleCount - i - 1] = mod;
208 | } else if (i < 9) {
209 | _modules[8][15 - i - 1 + 1] = mod;
210 | } else {
211 | _modules[8][15 - i - 1] = mod;
212 | }
213 | }
214 |
215 | // fixed module
216 | _modules[_moduleCount - 8][8] = (!test);
217 | };
218 |
219 | var mapData = function(data, maskPattern) {
220 |
221 | var inc = -1;
222 | var row = _moduleCount - 1;
223 | var bitIndex = 7;
224 | var byteIndex = 0;
225 | var maskFunc = QRUtil.getMaskFunction(maskPattern);
226 |
227 | for (var col = _moduleCount - 1; col > 0; col -= 2) {
228 |
229 | if (col == 6) col -= 1;
230 |
231 | while (true) {
232 |
233 | for (var c = 0; c < 2; c += 1) {
234 |
235 | if (_modules[row][col - c] == null) {
236 |
237 | var dark = false;
238 |
239 | if (byteIndex < data.length) {
240 | dark = ( ( (data[byteIndex] >>> bitIndex) & 1) == 1);
241 | }
242 |
243 | var mask = maskFunc(row, col - c);
244 |
245 | if (mask) {
246 | dark = !dark;
247 | }
248 |
249 | _modules[row][col - c] = dark;
250 | bitIndex -= 1;
251 |
252 | if (bitIndex == -1) {
253 | byteIndex += 1;
254 | bitIndex = 7;
255 | }
256 | }
257 | }
258 |
259 | row += inc;
260 |
261 | if (row < 0 || _moduleCount <= row) {
262 | row -= inc;
263 | inc = -inc;
264 | break;
265 | }
266 | }
267 | }
268 | };
269 |
270 | var createBytes = function(buffer, rsBlocks) {
271 |
272 | var offset = 0;
273 |
274 | var maxDcCount = 0;
275 | var maxEcCount = 0;
276 |
277 | var dcdata = new Array(rsBlocks.length);
278 | var ecdata = new Array(rsBlocks.length);
279 |
280 | for (var r = 0; r < rsBlocks.length; r += 1) {
281 |
282 | var dcCount = rsBlocks[r].dataCount;
283 | var ecCount = rsBlocks[r].totalCount - dcCount;
284 |
285 | maxDcCount = Math.max(maxDcCount, dcCount);
286 | maxEcCount = Math.max(maxEcCount, ecCount);
287 |
288 | dcdata[r] = new Array(dcCount);
289 |
290 | for (var i = 0; i < dcdata[r].length; i += 1) {
291 | dcdata[r][i] = 0xff & buffer.getBuffer()[i + offset];
292 | }
293 | offset += dcCount;
294 |
295 | var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
296 | var rawPoly = qrPolynomial(dcdata[r], rsPoly.getLength() - 1);
297 |
298 | var modPoly = rawPoly.mod(rsPoly);
299 | ecdata[r] = new Array(rsPoly.getLength() - 1);
300 | for (var i = 0; i < ecdata[r].length; i += 1) {
301 | var modIndex = i + modPoly.getLength() - ecdata[r].length;
302 | ecdata[r][i] = (modIndex >= 0)? modPoly.getAt(modIndex) : 0;
303 | }
304 | }
305 |
306 | var totalCodeCount = 0;
307 | for (var i = 0; i < rsBlocks.length; i += 1) {
308 | totalCodeCount += rsBlocks[i].totalCount;
309 | }
310 |
311 | var data = new Array(totalCodeCount);
312 | var index = 0;
313 |
314 | for (var i = 0; i < maxDcCount; i += 1) {
315 | for (var r = 0; r < rsBlocks.length; r += 1) {
316 | if (i < dcdata[r].length) {
317 | data[index] = dcdata[r][i];
318 | index += 1;
319 | }
320 | }
321 | }
322 |
323 | for (var i = 0; i < maxEcCount; i += 1) {
324 | for (var r = 0; r < rsBlocks.length; r += 1) {
325 | if (i < ecdata[r].length) {
326 | data[index] = ecdata[r][i];
327 | index += 1;
328 | }
329 | }
330 | }
331 |
332 | return data;
333 | };
334 |
335 | var createData = function(typeNumber, errorCorrectLevel, dataList) {
336 |
337 | var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel);
338 |
339 | var buffer = qrBitBuffer();
340 |
341 | for (var i = 0; i < dataList.length; i += 1) {
342 | var data = dataList[i];
343 | buffer.put(data.getMode(), 4);
344 | buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber) );
345 | data.write(buffer);
346 | }
347 |
348 | // calc num max data.
349 | var totalDataCount = 0;
350 | for (var i = 0; i < rsBlocks.length; i += 1) {
351 | totalDataCount += rsBlocks[i].dataCount;
352 | }
353 |
354 | if (buffer.getLengthInBits() > totalDataCount * 8) {
355 | throw new Error('code length overflow. ('
356 | + buffer.getLengthInBits()
357 | + '>'
358 | + totalDataCount * 8
359 | + ')');
360 | }
361 |
362 | // end code
363 | if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {
364 | buffer.put(0, 4);
365 | }
366 |
367 | // padding
368 | while (buffer.getLengthInBits() % 8 != 0) {
369 | buffer.putBit(false);
370 | }
371 |
372 | // padding
373 | while (true) {
374 |
375 | if (buffer.getLengthInBits() >= totalDataCount * 8) {
376 | break;
377 | }
378 | buffer.put(PAD0, 8);
379 |
380 | if (buffer.getLengthInBits() >= totalDataCount * 8) {
381 | break;
382 | }
383 | buffer.put(PAD1, 8);
384 | }
385 |
386 | return createBytes(buffer, rsBlocks);
387 | };
388 |
389 | _this.addData = function(data) {
390 | var newData = qr8BitByte(data);
391 | _dataList.push(newData);
392 | _dataCache = null;
393 | };
394 |
395 | _this.isDark = function(row, col) {
396 | if (row < 0 || _moduleCount <= row || col < 0 || _moduleCount <= col) {
397 | throw new Error(row + ',' + col);
398 | }
399 | return _modules[row][col];
400 | };
401 |
402 | _this.getModuleCount = function() {
403 | return _moduleCount;
404 | };
405 |
406 | _this.make = function(onlyControl) {
407 | makeImpl(false, getBestMaskPattern(), onlyControl);
408 | };
409 |
410 | _this.createTableTag = function(cellSize, margin) {
411 |
412 | cellSize = cellSize || 2;
413 | margin = (typeof margin == 'undefined')? cellSize * 4 : margin;
414 |
415 | var qrHtml = '';
416 |
417 | qrHtml += '';
422 | qrHtml += '';
423 |
424 | for (var r = 0; r < _this.getModuleCount(); r += 1) {
425 |
426 | qrHtml += '';
427 |
428 | for (var c = 0; c < _this.getModuleCount(); c += 1) {
429 | qrHtml += ' | ';
439 | }
440 |
441 | qrHtml += '
';
442 | }
443 |
444 | qrHtml += '';
445 | qrHtml += '
';
446 |
447 | return qrHtml;
448 | };
449 |
450 | _this.returnByteArray = function() {
451 |
452 | return _modules;
453 | }
454 |
455 | _this.createImgTag = function(cellSize, margin) {
456 |
457 | cellSize = cellSize || 2;
458 | margin = (typeof margin == 'undefined')? cellSize * 4 : margin;
459 |
460 | var size = _this.getModuleCount() * cellSize + margin * 2;
461 | var min = margin;
462 | var max = size - margin;
463 |
464 | return createImgTag(size, size, function(x, y) {
465 | if (min <= x && x < max && min <= y && y < max) {
466 | var c = Math.floor( (x - min) / cellSize);
467 | var r = Math.floor( (y - min) / cellSize);
468 | return _this.isDark(r, c)? 0 : 1;
469 | } else {
470 | return 1;
471 | }
472 | } );
473 | };
474 |
475 | return _this;
476 | };
477 |
478 | //---------------------------------------------------------------------
479 | // qrcode.stringToBytes
480 | //---------------------------------------------------------------------
481 |
482 | qrcode.stringToBytes = function(s) {
483 | var bytes = new Array();
484 | for (var i = 0; i < s.length; i += 1) {
485 | var c = s.charCodeAt(i);
486 | bytes.push(c & 0xff);
487 | }
488 | return bytes;
489 | };
490 |
491 | //---------------------------------------------------------------------
492 | // qrcode.createStringToBytes
493 | //---------------------------------------------------------------------
494 |
495 | /**
496 | * @param unicodeData base64 string of byte array.
497 | * [16bit Unicode],[16bit Bytes], ...
498 | * @param numChars
499 | */
500 | qrcode.createStringToBytes = function(unicodeData, numChars) {
501 |
502 | // create conversion map.
503 |
504 | var unicodeMap = function() {
505 |
506 | var bin = base64DecodeInputStream(unicodeData);
507 | var read = function() {
508 | var b = bin.read();
509 | if (b == -1) throw new Error();
510 | return b;
511 | };
512 |
513 | var count = 0;
514 | var unicodeMap = {};
515 | while (true) {
516 | var b0 = bin.read();
517 | if (b0 == -1) break;
518 | var b1 = read();
519 | var b2 = read();
520 | var b3 = read();
521 | var k = String.fromCharCode( (b0 << 8) | b1);
522 | var v = (b2 << 8) | b3;
523 | unicodeMap[k] = v;
524 | count += 1;
525 | }
526 | if (count != numChars) {
527 | throw new Error(count + ' != ' + numChars);
528 | }
529 |
530 | return unicodeMap;
531 | }();
532 |
533 | var unknownChar = '?'.charCodeAt(0);
534 |
535 | return function(s) {
536 | var bytes = new Array();
537 | for (var i = 0; i < s.length; i += 1) {
538 | var c = s.charCodeAt(i);
539 | if (c < 128) {
540 | bytes.push(c);
541 | } else {
542 | var b = unicodeMap[s.charAt(i)];
543 | if (typeof b == 'number') {
544 | if ( (b & 0xff) == b) {
545 | // 1byte
546 | bytes.push(b);
547 | } else {
548 | // 2bytes
549 | bytes.push(b >>> 8);
550 | bytes.push(b & 0xff);
551 | }
552 | } else {
553 | bytes.push(unknownChar);
554 | }
555 | }
556 | }
557 | return bytes;
558 | };
559 | };
560 |
561 | //---------------------------------------------------------------------
562 | // QRMode
563 | //---------------------------------------------------------------------
564 |
565 | var QRMode = {
566 | MODE_NUMBER : 1 << 0,
567 | MODE_ALPHA_NUM : 1 << 1,
568 | MODE_8BIT_BYTE : 1 << 2,
569 | MODE_KANJI : 1 << 3
570 | };
571 | qrcode.QRMode = QRMode;
572 |
573 | //---------------------------------------------------------------------
574 | // QRErrorCorrectLevel
575 | //---------------------------------------------------------------------
576 |
577 | var QRErrorCorrectLevel = {
578 | L : 1,
579 | M : 0,
580 | Q : 3,
581 | H : 2
582 | };
583 | qrcode.QRErrorCorrectLevel = QRErrorCorrectLevel;
584 |
585 | //---------------------------------------------------------------------
586 | // QRMaskPattern
587 | //---------------------------------------------------------------------
588 |
589 | var QRMaskPattern = {
590 | PATTERN000 : 0,
591 | PATTERN001 : 1,
592 | PATTERN010 : 2,
593 | PATTERN011 : 3,
594 | PATTERN100 : 4,
595 | PATTERN101 : 5,
596 | PATTERN110 : 6,
597 | PATTERN111 : 7
598 | };
599 | qrcode.QRMaskPattern = QRMaskPattern;
600 |
601 | //---------------------------------------------------------------------
602 | // QRUtil
603 | //---------------------------------------------------------------------
604 |
605 | var QRUtil = function() {
606 |
607 | var PATTERN_POSITION_TABLE = [
608 | [],
609 | [6, 18],
610 | [6, 22],
611 | [6, 26],
612 | [6, 30],
613 | [6, 34],
614 | [6, 22, 38],
615 | [6, 24, 42],
616 | [6, 26, 46],
617 | [6, 28, 50],
618 | [6, 30, 54],
619 | [6, 32, 58],
620 | [6, 34, 62],
621 | [6, 26, 46, 66],
622 | [6, 26, 48, 70],
623 | [6, 26, 50, 74],
624 | [6, 30, 54, 78],
625 | [6, 30, 56, 82],
626 | [6, 30, 58, 86],
627 | [6, 34, 62, 90],
628 | [6, 28, 50, 72, 94],
629 | [6, 26, 50, 74, 98],
630 | [6, 30, 54, 78, 102],
631 | [6, 28, 54, 80, 106],
632 | [6, 32, 58, 84, 110],
633 | [6, 30, 58, 86, 114],
634 | [6, 34, 62, 90, 118],
635 | [6, 26, 50, 74, 98, 122],
636 | [6, 30, 54, 78, 102, 126],
637 | [6, 26, 52, 78, 104, 130],
638 | [6, 30, 56, 82, 108, 134],
639 | [6, 34, 60, 86, 112, 138],
640 | [6, 30, 58, 86, 114, 142],
641 | [6, 34, 62, 90, 118, 146],
642 | [6, 30, 54, 78, 102, 126, 150],
643 | [6, 24, 50, 76, 102, 128, 154],
644 | [6, 28, 54, 80, 106, 132, 158],
645 | [6, 32, 58, 84, 110, 136, 162],
646 | [6, 26, 54, 82, 110, 138, 166],
647 | [6, 30, 58, 86, 114, 142, 170]
648 | ];
649 | var G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0);
650 | var G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0);
651 | var G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1);
652 |
653 | var _this = {};
654 |
655 | var getBCHDigit = function(data) {
656 | var digit = 0;
657 | while (data != 0) {
658 | digit += 1;
659 | data >>>= 1;
660 | }
661 | return digit;
662 | };
663 |
664 | _this.getBCHTypeInfo = function(data) {
665 | var d = data << 10;
666 | while (getBCHDigit(d) - getBCHDigit(G15) >= 0) {
667 | d ^= (G15 << (getBCHDigit(d) - getBCHDigit(G15) ) );
668 | }
669 | return ( (data << 10) | d) ^ G15_MASK;
670 | };
671 |
672 | _this.getBCHTypeNumber = function(data) {
673 | var d = data << 12;
674 | while (getBCHDigit(d) - getBCHDigit(G18) >= 0) {
675 | d ^= (G18 << (getBCHDigit(d) - getBCHDigit(G18) ) );
676 | }
677 | return (data << 12) | d;
678 | };
679 |
680 | _this.getPatternPosition = function(typeNumber) {
681 | return PATTERN_POSITION_TABLE[typeNumber - 1];
682 | };
683 |
684 | _this.getMaskFunction = function(maskPattern) {
685 |
686 | switch (maskPattern) {
687 |
688 | case QRMaskPattern.PATTERN000 :
689 | return function(i, j) { return (i + j) % 2 == 0; };
690 | case QRMaskPattern.PATTERN001 :
691 | return function(i, j) { return i % 2 == 0; };
692 | case QRMaskPattern.PATTERN010 :
693 | return function(i, j) { return j % 3 == 0; };
694 | case QRMaskPattern.PATTERN011 :
695 | return function(i, j) { return (i + j) % 3 == 0; };
696 | case QRMaskPattern.PATTERN100 :
697 | return function(i, j) { return (Math.floor(i / 2) + Math.floor(j / 3) ) % 2 == 0; };
698 | case QRMaskPattern.PATTERN101 :
699 | return function(i, j) { return (i * j) % 2 + (i * j) % 3 == 0; };
700 | case QRMaskPattern.PATTERN110 :
701 | return function(i, j) { return ( (i * j) % 2 + (i * j) % 3) % 2 == 0; };
702 | case QRMaskPattern.PATTERN111 :
703 | return function(i, j) { return ( (i * j) % 3 + (i + j) % 2) % 2 == 0; };
704 |
705 | default :
706 | throw new Error('bad maskPattern:' + maskPattern);
707 | }
708 | };
709 |
710 | _this.getErrorCorrectPolynomial = function(errorCorrectLength) {
711 | var a = qrPolynomial([1], 0);
712 | for (var i = 0; i < errorCorrectLength; i += 1) {
713 | a = a.multiply(qrPolynomial([1, QRMath.gexp(i)], 0) );
714 | }
715 | return a;
716 | };
717 |
718 | _this.getLengthInBits = function(mode, type) {
719 |
720 | if (1 <= type && type < 10) {
721 |
722 | // 1 - 9
723 |
724 | switch(mode) {
725 | case QRMode.MODE_NUMBER : return 10;
726 | case QRMode.MODE_ALPHA_NUM : return 9;
727 | case QRMode.MODE_8BIT_BYTE : return 8;
728 | case QRMode.MODE_KANJI : return 8;
729 | default :
730 | throw new Error('mode:' + mode);
731 | }
732 |
733 | } else if (type < 27) {
734 |
735 | // 10 - 26
736 |
737 | switch(mode) {
738 | case QRMode.MODE_NUMBER : return 12;
739 | case QRMode.MODE_ALPHA_NUM : return 11;
740 | case QRMode.MODE_8BIT_BYTE : return 16;
741 | case QRMode.MODE_KANJI : return 10;
742 | default :
743 | throw new Error('mode:' + mode);
744 | }
745 |
746 | } else if (type < 41) {
747 |
748 | // 27 - 40
749 |
750 | switch(mode) {
751 | case QRMode.MODE_NUMBER : return 14;
752 | case QRMode.MODE_ALPHA_NUM : return 13;
753 | case QRMode.MODE_8BIT_BYTE : return 16;
754 | case QRMode.MODE_KANJI : return 12;
755 | default :
756 | throw new Error('mode:' + mode);
757 | }
758 |
759 | } else {
760 | throw new Error('type:' + type);
761 | }
762 | };
763 |
764 | _this.getLostPoint = function(qrcode) {
765 |
766 | var moduleCount = qrcode.getModuleCount();
767 |
768 | var lostPoint = 0;
769 |
770 | // LEVEL1
771 |
772 | for (var row = 0; row < moduleCount; row += 1) {
773 | for (var col = 0; col < moduleCount; col += 1) {
774 |
775 | var sameCount = 0;
776 | var dark = qrcode.isDark(row, col);
777 |
778 | for (var r = -1; r <= 1; r += 1) {
779 |
780 | if (row + r < 0 || moduleCount <= row + r) {
781 | continue;
782 | }
783 |
784 | for (var c = -1; c <= 1; c += 1) {
785 |
786 | if (col + c < 0 || moduleCount <= col + c) {
787 | continue;
788 | }
789 |
790 | if (r == 0 && c == 0) {
791 | continue;
792 | }
793 |
794 | if (dark == qrcode.isDark(row + r, col + c) ) {
795 | sameCount += 1;
796 | }
797 | }
798 | }
799 |
800 | if (sameCount > 5) {
801 | lostPoint += (3 + sameCount - 5);
802 | }
803 | }
804 | };
805 |
806 | // LEVEL2
807 |
808 | for (var row = 0; row < moduleCount - 1; row += 1) {
809 | for (var col = 0; col < moduleCount - 1; col += 1) {
810 | var count = 0;
811 | if (qrcode.isDark(row, col) ) count += 1;
812 | if (qrcode.isDark(row + 1, col) ) count += 1;
813 | if (qrcode.isDark(row, col + 1) ) count += 1;
814 | if (qrcode.isDark(row + 1, col + 1) ) count += 1;
815 | if (count == 0 || count == 4) {
816 | lostPoint += 3;
817 | }
818 | }
819 | }
820 |
821 | // LEVEL3
822 |
823 | for (var row = 0; row < moduleCount; row += 1) {
824 | for (var col = 0; col < moduleCount - 6; col += 1) {
825 | if (qrcode.isDark(row, col)
826 | && !qrcode.isDark(row, col + 1)
827 | && qrcode.isDark(row, col + 2)
828 | && qrcode.isDark(row, col + 3)
829 | && qrcode.isDark(row, col + 4)
830 | && !qrcode.isDark(row, col + 5)
831 | && qrcode.isDark(row, col + 6) ) {
832 | lostPoint += 40;
833 | }
834 | }
835 | }
836 |
837 | for (var col = 0; col < moduleCount; col += 1) {
838 | for (var row = 0; row < moduleCount - 6; row += 1) {
839 | if (qrcode.isDark(row, col)
840 | && !qrcode.isDark(row + 1, col)
841 | && qrcode.isDark(row + 2, col)
842 | && qrcode.isDark(row + 3, col)
843 | && qrcode.isDark(row + 4, col)
844 | && !qrcode.isDark(row + 5, col)
845 | && qrcode.isDark(row + 6, col) ) {
846 | lostPoint += 40;
847 | }
848 | }
849 | }
850 |
851 | // LEVEL4
852 |
853 | var darkCount = 0;
854 |
855 | for (var col = 0; col < moduleCount; col += 1) {
856 | for (var row = 0; row < moduleCount; row += 1) {
857 | if (qrcode.isDark(row, col) ) {
858 | darkCount += 1;
859 | }
860 | }
861 | }
862 |
863 | var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
864 | lostPoint += ratio * 10;
865 |
866 | return lostPoint;
867 | };
868 |
869 | return _this;
870 | }();
871 | qrcode.QRUtil = QRUtil;
872 |
873 | //---------------------------------------------------------------------
874 | // QRMath
875 | //---------------------------------------------------------------------
876 |
877 | var QRMath = function() {
878 |
879 | var EXP_TABLE = new Array(256);
880 | var LOG_TABLE = new Array(256);
881 |
882 | // initialize tables
883 | for (var i = 0; i < 8; i += 1) {
884 | EXP_TABLE[i] = 1 << i;
885 | }
886 | for (var i = 8; i < 256; i += 1) {
887 | EXP_TABLE[i] = EXP_TABLE[i - 4]
888 | ^ EXP_TABLE[i - 5]
889 | ^ EXP_TABLE[i - 6]
890 | ^ EXP_TABLE[i - 8];
891 | }
892 | for (var i = 0; i < 255; i += 1) {
893 | LOG_TABLE[EXP_TABLE[i] ] = i;
894 | }
895 |
896 | var _this = {};
897 |
898 | _this.glog = function(n) {
899 |
900 | if (n < 1) {
901 | throw new Error('glog(' + n + ')');
902 | }
903 |
904 | return LOG_TABLE[n];
905 | };
906 |
907 | _this.gexp = function(n) {
908 |
909 | while (n < 0) {
910 | n += 255;
911 | }
912 |
913 | while (n >= 256) {
914 | n -= 255;
915 | }
916 |
917 | return EXP_TABLE[n];
918 | };
919 |
920 | return _this;
921 | }();
922 |
923 | //---------------------------------------------------------------------
924 | // qrPolynomial
925 | //---------------------------------------------------------------------
926 |
927 | function qrPolynomial(num, shift) {
928 |
929 | if (typeof num.length == 'undefined') {
930 | throw new Error(num.length + '/' + shift);
931 | }
932 |
933 | var _num = function() {
934 | var offset = 0;
935 | while (offset < num.length && num[offset] == 0) {
936 | offset += 1;
937 | }
938 | var _num = new Array(num.length - offset + shift);
939 | for (var i = 0; i < num.length - offset; i += 1) {
940 | _num[i] = num[i + offset];
941 | }
942 | return _num;
943 | }();
944 |
945 | var _this = {};
946 |
947 | _this.getAt = function(index) {
948 | return _num[index];
949 | };
950 |
951 | _this.getLength = function() {
952 | return _num.length;
953 | };
954 |
955 | _this.multiply = function(e) {
956 |
957 | var num = new Array(_this.getLength() + e.getLength() - 1);
958 |
959 | for (var i = 0; i < _this.getLength(); i += 1) {
960 | for (var j = 0; j < e.getLength(); j += 1) {
961 | num[i + j] ^= QRMath.gexp(QRMath.glog(_this.getAt(i) ) + QRMath.glog(e.getAt(j) ) );
962 | }
963 | }
964 |
965 | return qrPolynomial(num, 0);
966 | };
967 |
968 | _this.mod = function(e) {
969 |
970 | if (_this.getLength() - e.getLength() < 0) {
971 | return _this;
972 | }
973 |
974 | var ratio = QRMath.glog(_this.getAt(0) ) - QRMath.glog(e.getAt(0) );
975 |
976 | var num = new Array(_this.getLength() );
977 | for (var i = 0; i < _this.getLength(); i += 1) {
978 | num[i] = _this.getAt(i);
979 | }
980 |
981 | for (var i = 0; i < e.getLength(); i += 1) {
982 | num[i] ^= QRMath.gexp(QRMath.glog(e.getAt(i) ) + ratio);
983 | }
984 |
985 | // recursive call
986 | return qrPolynomial(num, 0).mod(e);
987 | };
988 |
989 | return _this;
990 | };
991 |
992 | //---------------------------------------------------------------------
993 | // QRRSBlock
994 | //---------------------------------------------------------------------
995 |
996 | var QRRSBlock = function() {
997 |
998 | var _this = {};
999 |
1000 | var RS_BLOCK_TABLE = [
1001 |
1002 | // L
1003 | // M
1004 | // Q
1005 | // H
1006 |
1007 | // 1
1008 | [1, 26, 19],
1009 | [1, 26, 16],
1010 | [1, 26, 13],
1011 | [1, 26, 9],
1012 |
1013 | // 2
1014 | [1, 44, 34],
1015 | [1, 44, 28],
1016 | [1, 44, 22],
1017 | [1, 44, 16],
1018 |
1019 | // 3
1020 | [1, 70, 55],
1021 | [1, 70, 44],
1022 | [2, 35, 17],
1023 | [2, 35, 13],
1024 |
1025 | // 4
1026 | [1, 100, 80],
1027 | [2, 50, 32],
1028 | [2, 50, 24],
1029 | [4, 25, 9],
1030 |
1031 | // 5
1032 | [1, 134, 108],
1033 | [2, 67, 43],
1034 | [2, 33, 15, 2, 34, 16],
1035 | [2, 33, 11, 2, 34, 12],
1036 |
1037 | // 6
1038 | [2, 86, 68],
1039 | [4, 43, 27],
1040 | [4, 43, 19],
1041 | [4, 43, 15],
1042 |
1043 | // 7
1044 | [2, 98, 78],
1045 | [4, 49, 31],
1046 | [2, 32, 14, 4, 33, 15],
1047 | [4, 39, 13, 1, 40, 14],
1048 |
1049 | // 8
1050 | [2, 121, 97],
1051 | [2, 60, 38, 2, 61, 39],
1052 | [4, 40, 18, 2, 41, 19],
1053 | [4, 40, 14, 2, 41, 15],
1054 |
1055 | // 9
1056 | [2, 146, 116],
1057 | [3, 58, 36, 2, 59, 37],
1058 | [4, 36, 16, 4, 37, 17],
1059 | [4, 36, 12, 4, 37, 13],
1060 |
1061 | // 10
1062 | [2, 86, 68, 2, 87, 69],
1063 | [4, 69, 43, 1, 70, 44],
1064 | [6, 43, 19, 2, 44, 20],
1065 | [6, 43, 15, 2, 44, 16]
1066 | ];
1067 | _this.RS_BLOCK_TABLE = RS_BLOCK_TABLE;
1068 |
1069 | var qrRSBlock = function(totalCount, dataCount) {
1070 | var _this = {};
1071 | _this.totalCount = totalCount;
1072 | _this.dataCount = dataCount;
1073 | return _this;
1074 | };
1075 |
1076 | var getRsBlockTable = function(typeNumber, errorCorrectLevel) {
1077 |
1078 | switch(errorCorrectLevel) {
1079 | case QRErrorCorrectLevel.L :
1080 | return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
1081 | case QRErrorCorrectLevel.M :
1082 | return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
1083 | case QRErrorCorrectLevel.Q :
1084 | return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
1085 | case QRErrorCorrectLevel.H :
1086 | return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
1087 | default :
1088 | return undefined;
1089 | }
1090 | };
1091 |
1092 | _this.getRSBlocks = function(typeNumber, errorCorrectLevel) {
1093 |
1094 | var rsBlock = getRsBlockTable(typeNumber, errorCorrectLevel);
1095 |
1096 | if (typeof rsBlock == 'undefined') {
1097 | throw new Error('bad rs block @ typeNumber:' + typeNumber +
1098 | '/errorCorrectLevel:' + errorCorrectLevel);
1099 | }
1100 |
1101 | var length = rsBlock.length / 3;
1102 |
1103 | var list = new Array();
1104 |
1105 | for (var i = 0; i < length; i += 1) {
1106 |
1107 | var count = rsBlock[i * 3 + 0];
1108 | var totalCount = rsBlock[i * 3 + 1];
1109 | var dataCount = rsBlock[i * 3 + 2];
1110 |
1111 | for (var j = 0; j < count; j += 1) {
1112 | list.push(qrRSBlock(totalCount, dataCount) );
1113 | }
1114 | }
1115 |
1116 | return list;
1117 | };
1118 |
1119 | return _this;
1120 | }();
1121 | qrcode.QRRSBlock = QRRSBlock;
1122 |
1123 | //---------------------------------------------------------------------
1124 | // qrBitBuffer
1125 | //---------------------------------------------------------------------
1126 |
1127 | var qrBitBuffer = function() {
1128 |
1129 | var _buffer = new Array();
1130 | var _length = 0;
1131 |
1132 | var _this = {};
1133 |
1134 | _this.getBuffer = function() {
1135 | return _buffer;
1136 | };
1137 |
1138 | _this.getAt = function(index) {
1139 | var bufIndex = Math.floor(index / 8);
1140 | return ( (_buffer[bufIndex] >>> (7 - index % 8) ) & 1) == 1;
1141 | };
1142 |
1143 | _this.put = function(num, length) {
1144 | for (var i = 0; i < length; i += 1) {
1145 | _this.putBit( ( (num >>> (length - i - 1) ) & 1) == 1);
1146 | }
1147 | };
1148 |
1149 | _this.getLengthInBits = function() {
1150 | return _length;
1151 | };
1152 |
1153 | _this.putBit = function(bit) {
1154 |
1155 | var bufIndex = Math.floor(_length / 8);
1156 | if (_buffer.length <= bufIndex) {
1157 | _buffer.push(0);
1158 | }
1159 |
1160 | if (bit) {
1161 | _buffer[bufIndex] |= (0x80 >>> (_length % 8) );
1162 | }
1163 |
1164 | _length += 1;
1165 | };
1166 |
1167 | return _this;
1168 | };
1169 |
1170 | //---------------------------------------------------------------------
1171 | // qr8BitByte
1172 | //---------------------------------------------------------------------
1173 |
1174 | var qr8BitByte = function(data) {
1175 |
1176 | var _mode = QRMode.MODE_8BIT_BYTE;
1177 | var _data = data;
1178 | var _bytes = qrcode.stringToBytes(data);
1179 |
1180 | var _this = {};
1181 |
1182 | _this.getMode = function() {
1183 | return _mode;
1184 | };
1185 |
1186 | _this.getLength = function(buffer) {
1187 | return _bytes.length;
1188 | };
1189 |
1190 | _this.write = function(buffer) {
1191 | for (var i = 0; i < _bytes.length; i += 1) {
1192 | buffer.put(_bytes[i], 8);
1193 | }
1194 | };
1195 |
1196 | return _this;
1197 | };
1198 |
1199 | //=====================================================================
1200 | // GIF Support etc.
1201 | //
1202 |
1203 | //---------------------------------------------------------------------
1204 | // byteArrayOutputStream
1205 | //---------------------------------------------------------------------
1206 |
1207 | var byteArrayOutputStream = function() {
1208 |
1209 | var _bytes = new Array();
1210 |
1211 | var _this = {};
1212 |
1213 | _this.writeByte = function(b) {
1214 | _bytes.push(b & 0xff);
1215 | };
1216 |
1217 | _this.writeShort = function(i) {
1218 | _this.writeByte(i);
1219 | _this.writeByte(i >>> 8);
1220 | };
1221 |
1222 | _this.writeBytes = function(b, off, len) {
1223 | off = off || 0;
1224 | len = len || b.length;
1225 | for (var i = 0; i < len; i += 1) {
1226 | _this.writeByte(b[i + off]);
1227 | }
1228 | };
1229 |
1230 | _this.writeString = function(s) {
1231 | for (var i = 0; i < s.length; i += 1) {
1232 | _this.writeByte(s.charCodeAt(i) );
1233 | }
1234 | };
1235 |
1236 | _this.toByteArray = function() {
1237 | return _bytes;
1238 | };
1239 |
1240 | _this.toString = function() {
1241 | var s = '';
1242 | s += '[';
1243 | for (var i = 0; i < _bytes.length; i += 1) {
1244 | if (i > 0) {
1245 | s += ',';
1246 | }
1247 | s += _bytes[i];
1248 | }
1249 | s += ']';
1250 | return s;
1251 | };
1252 |
1253 | return _this;
1254 | };
1255 |
1256 | //---------------------------------------------------------------------
1257 | // base64EncodeOutputStream
1258 | //---------------------------------------------------------------------
1259 |
1260 | var base64EncodeOutputStream = function() {
1261 |
1262 | var _buffer = 0;
1263 | var _buflen = 0;
1264 | var _length = 0;
1265 | var _base64 = '';
1266 |
1267 | var _this = {};
1268 |
1269 | var writeEncoded = function(b) {
1270 | _base64 += String.fromCharCode(encode(b & 0x3f) );
1271 | };
1272 |
1273 | var encode = function(n) {
1274 | if (n < 0) {
1275 | // error.
1276 | } else if (n < 26) {
1277 | return 0x41 + n;
1278 | } else if (n < 52) {
1279 | return 0x61 + (n - 26);
1280 | } else if (n < 62) {
1281 | return 0x30 + (n - 52);
1282 | } else if (n == 62) {
1283 | return 0x2b;
1284 | } else if (n == 63) {
1285 | return 0x2f;
1286 | }
1287 | throw new Error('n:' + n);
1288 | };
1289 |
1290 | _this.writeByte = function(n) {
1291 |
1292 | _buffer = (_buffer << 8) | (n & 0xff);
1293 | _buflen += 8;
1294 | _length += 1;
1295 |
1296 | while (_buflen >= 6) {
1297 | writeEncoded(_buffer >>> (_buflen - 6) );
1298 | _buflen -= 6;
1299 | }
1300 | };
1301 |
1302 | _this.flush = function() {
1303 |
1304 | if (_buflen > 0) {
1305 | writeEncoded(_buffer << (6 - _buflen) );
1306 | _buffer = 0;
1307 | _buflen = 0;
1308 | }
1309 |
1310 | if (_length % 3 != 0) {
1311 | // padding
1312 | var padlen = 3 - _length % 3;
1313 | for (var i = 0; i < padlen; i += 1) {
1314 | _base64 += '=';
1315 | }
1316 | }
1317 | };
1318 |
1319 | _this.toString = function() {
1320 | return _base64;
1321 | };
1322 |
1323 | return _this;
1324 | };
1325 |
1326 | //---------------------------------------------------------------------
1327 | // base64DecodeInputStream
1328 | //---------------------------------------------------------------------
1329 |
1330 | var base64DecodeInputStream = function(str) {
1331 |
1332 | var _str = str;
1333 | var _pos = 0;
1334 | var _buffer = 0;
1335 | var _buflen = 0;
1336 |
1337 | var _this = {};
1338 |
1339 | _this.read = function() {
1340 |
1341 | while (_buflen < 8) {
1342 |
1343 | if (_pos >= _str.length) {
1344 | if (_buflen == 0) {
1345 | return -1;
1346 | }
1347 | throw new Error('unexpected end of file./' + _buflen);
1348 | }
1349 |
1350 | var c = _str.charAt(_pos);
1351 | _pos += 1;
1352 |
1353 | if (c == '=') {
1354 | _buflen = 0;
1355 | return -1;
1356 | } else if (c.match(/^\s$/) ) {
1357 | // ignore if whitespace.
1358 | continue;
1359 | }
1360 |
1361 | _buffer = (_buffer << 6) | decode(c.charCodeAt(0) );
1362 | _buflen += 6;
1363 | }
1364 |
1365 | var n = (_buffer >>> (_buflen - 8) ) & 0xff;
1366 | _buflen -= 8;
1367 | return n;
1368 | };
1369 |
1370 | var decode = function(c) {
1371 | if (0x41 <= c && c <= 0x5a) {
1372 | return c - 0x41;
1373 | } else if (0x61 <= c && c <= 0x7a) {
1374 | return c - 0x61 + 26;
1375 | } else if (0x30 <= c && c <= 0x39) {
1376 | return c - 0x30 + 52;
1377 | } else if (c == 0x2b) {
1378 | return 62;
1379 | } else if (c == 0x2f) {
1380 | return 63;
1381 | } else {
1382 | throw new Error('c:' + c);
1383 | }
1384 | };
1385 |
1386 | return _this;
1387 | };
1388 |
1389 | //---------------------------------------------------------------------
1390 | // gifImage (B/W)
1391 | //---------------------------------------------------------------------
1392 |
1393 | var gifImage = function(width, height) {
1394 |
1395 | var _width = width;
1396 | var _height = height;
1397 | var _data = new Array(width * height);
1398 |
1399 | var _this = {};
1400 |
1401 | _this.setPixel = function(x, y, pixel) {
1402 | _data[y * _width + x] = pixel;
1403 | };
1404 |
1405 | _this.write = function(out) {
1406 |
1407 | //---------------------------------
1408 | // GIF Signature
1409 |
1410 | out.writeString('GIF87a');
1411 |
1412 | //---------------------------------
1413 | // Screen Descriptor
1414 |
1415 | out.writeShort(_width);
1416 | out.writeShort(_height);
1417 |
1418 | out.writeByte(0x80); // 2bit
1419 | out.writeByte(0);
1420 | out.writeByte(0);
1421 |
1422 | //---------------------------------
1423 | // Global Color Map
1424 |
1425 | // black
1426 | out.writeByte(0x00);
1427 | out.writeByte(0x00);
1428 | out.writeByte(0x00);
1429 |
1430 | // white
1431 | out.writeByte(0xff);
1432 | out.writeByte(0xff);
1433 | out.writeByte(0xff);
1434 |
1435 | //---------------------------------
1436 | // Image Descriptor
1437 |
1438 | out.writeString(',');
1439 | out.writeShort(0);
1440 | out.writeShort(0);
1441 | out.writeShort(_width);
1442 | out.writeShort(_height);
1443 | out.writeByte(0);
1444 |
1445 | //---------------------------------
1446 | // Local Color Map
1447 |
1448 | //---------------------------------
1449 | // Raster Data
1450 |
1451 | var lzwMinCodeSize = 2;
1452 | var raster = getLZWRaster(lzwMinCodeSize);
1453 |
1454 | out.writeByte(lzwMinCodeSize);
1455 |
1456 | var offset = 0;
1457 |
1458 | while (raster.length - offset > 255) {
1459 | out.writeByte(255);
1460 | out.writeBytes(raster, offset, 255);
1461 | offset += 255;
1462 | }
1463 |
1464 | out.writeByte(raster.length - offset);
1465 | out.writeBytes(raster, offset, raster.length - offset);
1466 | out.writeByte(0x00);
1467 |
1468 | //---------------------------------
1469 | // GIF Terminator
1470 | out.writeString(';');
1471 | };
1472 |
1473 | var bitOutputStream = function(out) {
1474 |
1475 | var _out = out;
1476 | var _bitLength = 0;
1477 | var _bitBuffer = 0;
1478 |
1479 | var _this = {};
1480 |
1481 | _this.write = function(data, length) {
1482 |
1483 | if ( (data >>> length) != 0) {
1484 | throw new Error('length over');
1485 | }
1486 |
1487 | while (_bitLength + length >= 8) {
1488 | _out.writeByte(0xff & ( (data << _bitLength) | _bitBuffer) );
1489 | length -= (8 - _bitLength);
1490 | data >>>= (8 - _bitLength);
1491 | _bitBuffer = 0;
1492 | _bitLength = 0;
1493 | }
1494 |
1495 | _bitBuffer = (data << _bitLength) | _bitBuffer;
1496 | _bitLength = _bitLength + length;
1497 | };
1498 |
1499 | _this.flush = function() {
1500 | if (_bitLength > 0) {
1501 | _out.writeByte(_bitBuffer);
1502 | }
1503 | };
1504 |
1505 | return _this;
1506 | };
1507 |
1508 | var getLZWRaster = function(lzwMinCodeSize) {
1509 |
1510 | var clearCode = 1 << lzwMinCodeSize;
1511 | var endCode = (1 << lzwMinCodeSize) + 1;
1512 | var bitLength = lzwMinCodeSize + 1;
1513 |
1514 | // Setup LZWTable
1515 | var table = lzwTable();
1516 |
1517 | for (var i = 0; i < clearCode; i += 1) {
1518 | table.add(String.fromCharCode(i) );
1519 | }
1520 | table.add(String.fromCharCode(clearCode) );
1521 | table.add(String.fromCharCode(endCode) );
1522 |
1523 | var byteOut = byteArrayOutputStream();
1524 | var bitOut = bitOutputStream(byteOut);
1525 |
1526 | // clear code
1527 | bitOut.write(clearCode, bitLength);
1528 |
1529 | var dataIndex = 0;
1530 |
1531 | var s = String.fromCharCode(_data[dataIndex]);
1532 | dataIndex += 1;
1533 |
1534 | while (dataIndex < _data.length) {
1535 |
1536 | var c = String.fromCharCode(_data[dataIndex]);
1537 | dataIndex += 1;
1538 |
1539 | if (table.contains(s + c) ) {
1540 |
1541 | s = s + c;
1542 |
1543 | } else {
1544 |
1545 | bitOut.write(table.indexOf(s), bitLength);
1546 |
1547 | if (table.size() < 0xfff) {
1548 |
1549 | if (table.size() == (1 << bitLength) ) {
1550 | bitLength += 1;
1551 | }
1552 |
1553 | table.add(s + c);
1554 | }
1555 |
1556 | s = c;
1557 | }
1558 | }
1559 |
1560 | bitOut.write(table.indexOf(s), bitLength);
1561 |
1562 | // end code
1563 | bitOut.write(endCode, bitLength);
1564 |
1565 | bitOut.flush();
1566 |
1567 | return byteOut.toByteArray();
1568 | };
1569 |
1570 | var lzwTable = function() {
1571 |
1572 | var _map = {};
1573 | var _size = 0;
1574 |
1575 | var _this = {};
1576 |
1577 | _this.add = function(key) {
1578 | if (_this.contains(key) ) {
1579 | throw new Error('dup key:' + key);
1580 | }
1581 | _map[key] = _size;
1582 | _size += 1;
1583 | };
1584 |
1585 | _this.size = function() {
1586 | return _size;
1587 | };
1588 |
1589 | _this.indexOf = function(key) {
1590 | return _map[key];
1591 | };
1592 |
1593 | _this.contains = function(key) {
1594 | return typeof _map[key] != 'undefined';
1595 | };
1596 |
1597 | return _this;
1598 | };
1599 |
1600 | return _this;
1601 | };
1602 |
1603 | var createImgTag = function(width, height, getPixel, alt) {
1604 |
1605 | var gif = gifImage(width, height);
1606 | for (var y = 0; y < height; y += 1) {
1607 | for (var x = 0; x < width; x += 1) {
1608 | gif.setPixel(x, y, getPixel(x, y) );
1609 | }
1610 | }
1611 |
1612 | var b = byteArrayOutputStream();
1613 | gif.write(b);
1614 |
1615 | var base64 = base64EncodeOutputStream();
1616 | var bytes = b.toByteArray();
1617 | for (var i = 0; i < bytes.length; i += 1) {
1618 | base64.writeByte(bytes[i]);
1619 | }
1620 | base64.flush();
1621 |
1622 | var img = '';
1623 | img += '
';
1640 |
1641 | return img;
1642 | };
1643 |
1644 | //---------------------------------------------------------------------
1645 | // returns qrcode function.
1646 |
1647 | return qrcode;
1648 | }();
1649 |
1650 |
--------------------------------------------------------------------------------