let QRCode = {};
(function () {
/**
* 获取单个字符的utf8编码
* unicode BMP平面约65535个字符
* @param {num} code
* return {array}
*/
function unicodeFormat8(code) {
// 1 byte
var c0, c1, c2;
if (code < 128) {
return [code];
// 2 bytes
} else if (code < 2048) {
c0 = 192 + (code >> 6);
c1 = 128 + (code & 63);
return [c0, c1];
// 3 bytes
} else {
c0 = 224 + (code >> 12);
c1 = 128 + (code >> 6 & 63);
c2 = 128 + (code & 63);
return [c0, c1, c2];
}
}
/**
* 获取字符串的utf8编码字节串
* @param {string} string
* @return {array}
*/
function getUTF8Bytes(string) {
var utf8codes = [];
for (var i = 0; i < string.length; i++) {
var code = string.charCodeAt(i);
var utf8 = unicodeFormat8(code);
for (var j = 0; j < utf8.length; j++) {
utf8codes.push(utf8[j]);
}
}
return utf8codes;
}
/**
* 二维码算法实现
* @param {string} data 要编码的信息字符串
* @param {num} errorCorrectLevel 纠错等级
*/
function QRCodeAlg(data, errorCorrectLevel) {
this.typeNumber = -1; //版本
this.errorCorrectLevel = errorCorrectLevel;
this.modules = null; //二维矩阵,存放最终结果
this.moduleCount = 0; //矩阵大小
this.dataCache = null; //数据缓存
this.rsBlocks = null; //版本数据信息
this.totalDataCount = -1; //可使用的数据量
this.data = data;
this.utf8bytes = getUTF8Bytes(data);
this.make();
}
QRCodeAlg.prototype = {
constructor: QRCodeAlg,
/**
* 获取二维码矩阵大小
* @return {num} 矩阵大小
*/
getModuleCount: function () {
return this.moduleCount;
},
/**
* 编码
*/
make: function () {
this.getRightType();
this.dataCache = this.createData();
this.createQrcode();
},
/**
* 设置二位矩阵功能图形
* @param {bool} test 表示是否在寻找最好掩膜阶段
* @param {num} maskPattern 掩膜的版本
*/
makeImpl: function (maskPattern) {
this.moduleCount = this.typeNumber * 4 + 17;
this.modules = new Array(this.moduleCount);
for (var row = 0; row < this.moduleCount; row++) {
this.modules[row] = new Array(this.moduleCount);
}
this.setupPositionProbePattern(0, 0);
this.setupPositionProbePattern(this.moduleCount - 7, 0);
this.setupPositionProbePattern(0, this.moduleCount - 7);
this.setupPositionAdjustPattern();
this.setupTimingPattern();
this.setupTypeInfo(true, maskPattern);
if (this.typeNumber >= 7) {
this.setupTypeNumber(true);
}
this.mapData(this.dataCache, maskPattern);
},
/**
* 设置二维码的位置探测图形
* @param {num} row 探测图形的中心横坐标
* @param {num} col 探测图形的中心纵坐标
*/
setupPositionProbePattern: function (row, col) {
for (var r = -1; r <= 7; r++) {
if (row + r <= -1 || this.moduleCount <= row + r) continue;
for (var c = -1; c <= 7; c++) {
if (col + c <= -1 || this.moduleCount <= col + c) continue;
if ((0 <= r && r <= 6 && (c == 0 || c == 6)) || (0 <= c && c <= 6 && (r == 0 || r == 6)) || (2 <= r && r <= 4 && 2 <= c && c <= 4)) {
this.modules[row + r][col + c] = true;
} else {
this.modules[row + r][col + c] = false;
}
}
}
},
/**
* 创建二维码
* @return {[type]} [description]
*/
createQrcode: function () {
var minLostPoint = 0;
var pattern = 0;
var bestModules = null;
for (var i = 0; i < 8; i++) {
this.makeImpl(i);
var lostPoint = QRUtil.getLostPoint(this);
if (i == 0 || minLostPoint > lostPoint) {
minLostPoint = lostPoint;
pattern = i;
bestModules = this.modules;
}
}
this.modules = bestModules;
this.setupTypeInfo(false, pattern);
if (this.typeNumber >= 7) {
this.setupTypeNumber(false);
}
},
/**
* 设置定位图形
* @return {[type]} [description]
*/
setupTimingPattern: function () {
for (var r = 8; r < this.moduleCount - 8; r++) {
if (this.modules[r][6] != null) {
continue;
}
this.modules[r][6] = (r % 2 == 0);
if (this.modules[6][r] != null) {
continue;
}
this.modules[6][r] = (r % 2 == 0);
}
},
/**
* 设置矫正图形
* @return {[type]} [description]
*/
setupPositionAdjustPattern: function () {
var pos = QRUtil.getPatternPosition(this.typeNumber);
for (var i = 0; i < pos.length; i++) {
for (var j = 0; j < pos.length; j++) {
var row = pos[i];
var col = pos[j];
if (this.modules[row][col] != null) {
continue;
}
for (var r = -2; r <= 2; r++) {
for (var c = -2; c <= 2; c++) {
if (r == -2 || r == 2 || c == -2 || c == 2 || (r == 0 && c == 0)) {
this.modules[row + r][col + c] = true;
} else {
this.modules[row + r][col + c] = false;
}
}
}
}
}
},
/**
* 设置版本信息(7以上版本才有)
* @param {bool} test 是否处于判断最佳掩膜阶段
* @return {[type]} [description]
*/
setupTypeNumber: function (test) {
var bits = QRUtil.getBCHTypeNumber(this.typeNumber);
for (var i = 0; i < 18; i++) {
var mod = (!test && ((bits >> i) & 1) == 1);
this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod;
this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
}
},
/**
* 设置格式信息(纠错等级和掩膜版本)
* @param {bool} test
* @param {num} maskPattern 掩膜版本
* @return {}
*/
setupTypeInfo: function (test, maskPattern) {
var data = (QRErrorCorrectLevel[this.errorCorrectLevel] << 3) | maskPattern;
var bits = QRUtil.getBCHTypeInfo(data);
// vertical
for (var i = 0; i < 15; i++) {
var mod = (!test && ((bits >> i) & 1) == 1);
if (i < 6) {
this.modules[i][8] = mod;
} else if (i < 8) {
this.modules[i + 1][8] = mod;
} else {
this.modules[this.moduleCount - 15 + i][8] = mod;
评论0