qr-image
Version:
QR Code generator (png, svg, pdf, eps)
181 lines (159 loc) • 5.27 kB
JavaScript
"use strict";
var encode = require('./encode');
var calculateEC = require('./errorcode');
var matrix = require('./matrix');
function _deepCopy(obj) {
return JSON.parse(JSON.stringify(obj));
}
var EC_LEVELS = ['L', 'M', 'Q', 'H'];
// {{{1 Versions
var versions = [
[], // there is no version 0
// total number of codewords, (number of ec codewords, number of blocks) * ( L, M, Q, H )
[ ],
[ ],
[ ],
[ ],
[ ], // 5
[ ],
[ ],
[ ],
[ ],
[ ], // 10
[ ],
[ ],
[ ],
[ ],
[ ], // 15
[ ],
[ ],
[ ],
[ ],
[ ], // 20
[ ],
[ ],
[ ],
[ ],
[ ], // 25
[ ],
[ ],
[ ],
[ ],
[ ], // 30
[ ],
[ ],
[ ],
[ ],
[ ], // 35
[ ],
[ ],
[ ],
[ ],
[ ] // 40
];
versions = versions.map(function(v, index) {
if (!index) return {};
var res = {
}
for (var i = 1; i < 8; i += 2) {
var length = v[0] - v[i];
var num_template = v[i+1];
var ec_level = EC_LEVELS[(i/2)|0];
var level = {
version: index,
ec_level: ec_level,
data_len: length,
ec_len: v[i] / num_template,
blocks: [],
ec: []
}
for (var k = num_template, n = length; k > 0; k--) {
var block = (n / k)|0;
level.blocks.push(block);
n -= block;
}
res[ec_level] = level;
}
return res;
});
// {{{1 Get version template
function getTemplate(message, ec_level) {
var i = 1;
var len;
if (message.data1) {
len = Math.ceil(message.data1.length / 8);
} else {
i = 10;
}
for (/* i */; i < 10; i++) {
var version = versions[i][ec_level];
if (version.data_len >= len) {
return _deepCopy(version);
}
}
if (message.data10) {
len = Math.ceil(message.data10.length / 8);
} else {
i = 27;
}
for (/* i */; i < 27; i++) {
var version = versions[i][ec_level];
if (version.data_len >= len) {
return _deepCopy(version);
}
}
len = Math.ceil(message.data27.length / 8);
for (/* i */; i < 41; i++) {
var version = versions[i][ec_level];
if (version.data_len >= len) {
return _deepCopy(version);
}
}
throw new Error("Too much data");
}
// {{{1 Fill template
function fillTemplate(message, template) {
var blocks = new Buffer(template.data_len);
blocks.fill(0);
if (template.version < 10) {
message = message.data1;
} else if (template.version < 27) {
message = message.data10;
} else {
message = message.data27;
}
var len = message.length;
for (var i = 0; i < len; i += 8) {
var b = 0;
for (var j = 0; j < 8; j++) {
b = (b << 1) | (message[i + j] ? 1 : 0);
}
blocks[i / 8] = b;
}
var pad = 236;
for (var i = Math.ceil((len + 4) / 8); i < blocks.length; i++) {
blocks[i] = pad;
pad = (pad == 236) ? 17 : 236;
}
var offset = 0;
template.blocks = template.blocks.map(function(n) {
var b = blocks.slice(offset, offset + n);
offset += n;
template.ec.push(calculateEC(b, template.ec_len));
return b;
});
return template;
}
// {{{1 All-in-one
function QR(text, ec_level, parse_url) {
ec_level = EC_LEVELS.indexOf(ec_level) > -1 ? ec_level : 'M';
var message = encode(text, parse_url);
var data = fillTemplate(message, getTemplate(message, ec_level));
return matrix.getMatrix(data);
}
// {{{1 export functions
module.exports = {
QR: QR,
getTemplate: getTemplate,
fillTemplate: fillTemplate,
}