Last active
December 22, 2015 07:19
-
-
Save JohnWong/6437527 to your computer and use it in GitHub Desktop.
show book info of bupt library in douban book.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Show bupt library in douban | |
// @namespace http://bbs.byr.cn/ | |
// @description 在豆瓣读书页面显示该图书在北邮图书馆的信息 | |
// @include http://book.douban.com/subject/* | |
// @version 1.1 | |
// @author joest([email protected]) | |
// @author John Wong([email protected]) | |
// ==/UserScript== | |
var baseUrl = 'http://211.68.68.197/opac_two/search2/'; | |
var searchUrl = baseUrl + 'searchout.jsp?search_no_type=Y&snumber_type=Y&suchen_type=5&suchen_match=jq&recordtype=all&library_id=all&show_type=wenzi&suchen_word='; | |
var templete = '<div class="gray_ad" id="buptinfo" style="display:none;">\ | |
<h2 style="width: 150px;">北京邮电大学图书馆</h2>\ | |
<ul id="infoul" style="float: left; width: 150px;" class="bs more-after">\ | |
</ul>\ | |
<div style="width: 96px; height: 96px;margin-top: -24px;float: right; right: 10px; position: relative;" id="qrcontainer"></div>\ | |
<div class="clearfix"></div>\ | |
<div class="ft pl">\ | |
<a class="rr" id="gotolib" target="_blank" href="#">> 详细信息</a>\ | |
去图书馆找找看?\ | |
</div>\ | |
</div>'; | |
var info = '<li style="border: none">索书号: ${sn}</li>\ | |
<li style="border: none">馆藏数: ${total}</li>\ | |
<li style="border: none">可借数: ${left}</li>'; | |
function sendRequest(isbn){ | |
setTimeout(function() {GM_xmlhttpRequest({ | |
method: 'GET', | |
url: searchUrl + isbn, | |
onload: function(responseDetails) { | |
var response = responseDetails.responseText; | |
var matcher = response.match(/class='td_color_1'[\s\S"]*?<\/tr>/); | |
if(matcher != null){ | |
var content = matcher[0]; | |
var tds = content.split("<td>"); | |
var linkMatch = tds[1].match(/href="(.*?)"/); | |
var link = linkMatch == null? "": baseUrl + linkMatch[1]; | |
var snMatch = tds[6].match(/<br>(.*)<br>/); | |
var sn = snMatch == null? "": snMatch[1]; | |
var numbers = tds[7].split("<br>"); | |
var totalMatch = numbers[1].match(/\d+/); | |
var total = totalMatch == null? "": totalMatch[0]; | |
var leftMatch = numbers[3].match(/\d+/); | |
var left = leftMatch == null? "": leftMatch[0]; | |
showBook({link: link, sn: sn, total: total, left: left}); | |
} | |
} | |
})}, 0); | |
} | |
function showBook(data){ | |
var content = info.replace("${sn}", data.sn).replace("${total}", data.total).replace("${left}", data.left); | |
document.getElementById("infoul").innerHTML = content; | |
document.getElementById("gotolib").href = data.link; | |
var canvas = createCanvas(data.link); | |
document.getElementById("qrcontainer").appendChild(canvas); | |
document.getElementById("buptinfo").style["display"] = "block"; | |
} | |
(function onLoad(event) { | |
var info = info = document.getElementById("info"); | |
var matcher = info.innerHTML.match(/<span class="pl">ISBN:<\/span> (\d+)<br>/) | |
if(matcher != null){ | |
var isbn = matcher[1]; | |
sendRequest(isbn); | |
var parent = document.getElementById("buyinfo"); | |
parent = parent.parentNode; | |
parent.innerHTML = templete + parent.innerHTML; | |
} | |
})(); | |
function createCanvas(text){ | |
var options = { | |
width : 96, | |
height : 96, | |
typeNumber : -1, | |
correctLevel : QRErrorCorrectLevel.H, | |
background : "#ffffff", | |
foreground : "#000000" | |
}; | |
// create the qrcode itself | |
var qrcode = new QRCode(options.typeNumber, options.correctLevel); | |
qrcode.addData(text); | |
qrcode.make(); | |
// create canvas element | |
var canvas = document.createElement('canvas'); | |
canvas.width = options.width; | |
canvas.height = options.height; | |
var ctx = canvas.getContext('2d'); | |
// compute tileW/tileH based on options.width/options.height | |
var tileW = options.width / qrcode.getModuleCount(); | |
var tileH = options.height / qrcode.getModuleCount(); | |
// draw in the canvas | |
for( var row = 0; row < qrcode.getModuleCount(); row++ ){ | |
for( var col = 0; col < qrcode.getModuleCount(); col++ ){ | |
ctx.fillStyle = qrcode.isDark(row, col) ? options.foreground : options.background; | |
var w = (Math.ceil((col+1)*tileW) - Math.floor(col*tileW)); | |
var h = (Math.ceil((row+1)*tileW) - Math.floor(row*tileW)); | |
ctx.fillRect(Math.round(col*tileW),Math.round(row*tileH), w, h); | |
} | |
} | |
// return just built canvas | |
return canvas; | |
} | |
//--------------------------------------------------------------------- | |
// QRCode for JavaScript | |
// | |
// Copyright (c) 2009 Kazuhiko Arase | |
// | |
// URL: http://www.d-project.com/ | |
// | |
// Licensed under the MIT license: | |
// http://www.opensource.org/licenses/mit-license.php | |
// | |
// The word "QR Code" is registered trademark of | |
// DENSO WAVE INCORPORATED | |
// http://www.denso-wave.com/qrcode/faqpatent-e.html | |
// | |
//--------------------------------------------------------------------- | |
//--------------------------------------------------------------------- | |
// QR8bitByte | |
//--------------------------------------------------------------------- | |
function QR8bitByte(data) { | |
this.mode = QRMode.MODE_8BIT_BYTE; | |
this.data = data; | |
} | |
QR8bitByte.prototype = { | |
getLength : function(buffer) { | |
return this.data.length; | |
}, | |
write : function(buffer) { | |
for (var i = 0; i < this.data.length; i++) { | |
// not JIS ... | |
buffer.put(this.data.charCodeAt(i), 8); | |
} | |
} | |
}; | |
//--------------------------------------------------------------------- | |
// QRCode | |
//--------------------------------------------------------------------- | |
function QRCode(typeNumber, errorCorrectLevel) { | |
this.typeNumber = typeNumber; | |
this.errorCorrectLevel = errorCorrectLevel; | |
this.modules = null; | |
this.moduleCount = 0; | |
this.dataCache = null; | |
this.dataList = new Array(); | |
} | |
QRCode.prototype = { | |
addData : function(data) { | |
var newData = new QR8bitByte(data); | |
this.dataList.push(newData); | |
this.dataCache = null; | |
}, | |
isDark : function(row, col) { | |
if (row < 0 || this.moduleCount <= row || col < 0 || this.moduleCount <= col) { | |
throw new Error(row + "," + col); | |
} | |
return this.modules[row][col]; | |
}, | |
getModuleCount : function() { | |
return this.moduleCount; | |
}, | |
make : function() { | |
// Calculate automatically typeNumber if provided is < 1 | |
if (this.typeNumber < 1 ){ | |
var typeNumber = 1; | |
for (typeNumber = 1; typeNumber < 40; typeNumber++) { | |
var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, this.errorCorrectLevel); | |
var buffer = new QRBitBuffer(); | |
var totalDataCount = 0; | |
for (var i = 0; i < rsBlocks.length; i++) { | |
totalDataCount += rsBlocks[i].dataCount; | |
} | |
for (var i = 0; i < this.dataList.length; i++) { | |
var data = this.dataList[i]; | |
buffer.put(data.mode, 4); | |
buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber) ); | |
data.write(buffer); | |
} | |
if (buffer.getLengthInBits() <= totalDataCount * 8) | |
break; | |
} | |
this.typeNumber = typeNumber; | |
} | |
this.makeImpl(false, this.getBestMaskPattern() ); | |
}, | |
makeImpl : function(test, 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); | |
for (var col = 0; col < this.moduleCount; col++) { | |
this.modules[row][col] = null;//(col + row) % 3; | |
} | |
} | |
this.setupPositionProbePattern(0, 0); | |
this.setupPositionProbePattern(this.moduleCount - 7, 0); | |
this.setupPositionProbePattern(0, this.moduleCount - 7); | |
this.setupPositionAdjustPattern(); | |
this.setupTimingPattern(); | |
this.setupTypeInfo(test, maskPattern); | |
if (this.typeNumber >= 7) { | |
this.setupTypeNumber(test); | |
} | |
if (this.dataCache == null) { | |
this.dataCache = QRCode.createData(this.typeNumber, this.errorCorrectLevel, this.dataList); | |
} | |
this.mapData(this.dataCache, maskPattern); | |
}, | |
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; | |
} | |
} | |
} | |
}, | |
getBestMaskPattern : function() { | |
var minLostPoint = 0; | |
var pattern = 0; | |
for (var i = 0; i < 8; i++) { | |
this.makeImpl(true, i); | |
var lostPoint = QRUtil.getLostPoint(this); | |
if (i == 0 || minLostPoint > lostPoint) { | |
minLostPoint = lostPoint; | |
pattern = i; | |
} | |
} | |
return pattern; | |
}, | |
createMovieClip : function(target_mc, instance_name, depth) { | |
var qr_mc = target_mc.createEmptyMovieClip(instance_name, depth); | |
var cs = 1; | |
this.make(); | |
for (var row = 0; row < this.modules.length; row++) { | |
var y = row * cs; | |
for (var col = 0; col < this.modules[row].length; col++) { | |
var x = col * cs; | |
var dark = this.modules[row][col]; | |
if (dark) { | |
qr_mc.beginFill(0, 100); | |
qr_mc.moveTo(x, y); | |
qr_mc.lineTo(x + cs, y); | |
qr_mc.lineTo(x + cs, y + cs); | |
qr_mc.lineTo(x, y + cs); | |
qr_mc.endFill(); | |
} | |
} | |
} | |
return qr_mc; | |
}, | |
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); | |
} | |
for (var c = 8; c < this.moduleCount - 8; c++) { | |
if (this.modules[6][c] != null) { | |
continue; | |
} | |
this.modules[6][c] = (c % 2 == 0); | |
} | |
}, | |
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; | |
} | |
} | |
} | |
} | |
} | |
}, | |
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; | |
} | |
for (var i = 0; i < 18; i++) { | |
var mod = (!test && ( (bits >> i) & 1) == 1); | |
this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod; | |
} | |
}, | |
setupTypeInfo : function(test, maskPattern) { | |
var data = (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; | |
} | |
} | |
// horizontal | |
for (var i = 0; i < 15; i++) { | |
var mod = (!test && ( (bits >> i) & 1) == 1); | |
if (i < 8) { | |
this.modules[8][this.moduleCount - i - 1] = mod; | |
} else if (i < 9) { | |
this.modules[8][15 - i - 1 + 1] = mod; | |
} else { | |
this.modules[8][15 - i - 1] = mod; | |
} | |
} | |
// fixed module | |
this.modules[this.moduleCount - 8][8] = (!test); | |
}, | |
mapData : function(data, maskPattern) { | |
var inc = -1; | |
var row = this.moduleCount - 1; | |
var bitIndex = 7; | |
var byteIndex = 0; | |
for (var col = this.moduleCount - 1; col > 0; col -= 2) { | |
if (col == 6) col--; | |
while (true) { | |
for (var c = 0; c < 2; c++) { | |
if (this.modules[row][col - c] == null) { | |
var dark = false; | |
if (byteIndex < data.length) { | |
dark = ( ( (data[byteIndex] >>> bitIndex) & 1) == 1); | |
} | |
var mask = QRUtil.getMask(maskPattern, row, col - c); | |
if (mask) { | |
dark = !dark; | |
} | |
this.modules[row][col - c] = dark; | |
bitIndex--; | |
if (bitIndex == -1) { | |
byteIndex++; | |
bitIndex = 7; | |
} | |
} | |
} | |
row += inc; | |
if (row < 0 || this.moduleCount <= row) { | |
row -= inc; | |
inc = -inc; | |
break; | |
} | |
} | |
} | |
} | |
}; | |
QRCode.PAD0 = 0xEC; | |
QRCode.PAD1 = 0x11; | |
QRCode.createData = function(typeNumber, errorCorrectLevel, dataList) { | |
var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel); | |
var buffer = new QRBitBuffer(); | |
for (var i = 0; i < dataList.length; i++) { | |
var data = dataList[i]; | |
buffer.put(data.mode, 4); | |
buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber) ); | |
data.write(buffer); | |
} | |
// calc num max data. | |
var totalDataCount = 0; | |
for (var i = 0; i < rsBlocks.length; i++) { | |
totalDataCount += rsBlocks[i].dataCount; | |
} | |
if (buffer.getLengthInBits() > totalDataCount * 8) { | |
throw new Error("code length overflow. (" | |
+ buffer.getLengthInBits() | |
+ ">" | |
+ totalDataCount * 8 | |
+ ")"); | |
} | |
// end code | |
if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) { | |
buffer.put(0, 4); | |
} | |
// padding | |
while (buffer.getLengthInBits() % 8 != 0) { | |
buffer.putBit(false); | |
} | |
// padding | |
while (true) { | |
if (buffer.getLengthInBits() >= totalDataCount * 8) { | |
break; | |
} | |
buffer.put(QRCode.PAD0, 8); | |
if (buffer.getLengthInBits() >= totalDataCount * 8) { | |
break; | |
} | |
buffer.put(QRCode.PAD1, 8); | |
} | |
return QRCode.createBytes(buffer, rsBlocks); | |
} | |
QRCode.createBytes = function(buffer, rsBlocks) { | |
var offset = 0; | |
var maxDcCount = 0; | |
var maxEcCount = 0; | |
var dcdata = new Array(rsBlocks.length); | |
var ecdata = new Array(rsBlocks.length); | |
for (var r = 0; r < rsBlocks.length; r++) { | |
var dcCount = rsBlocks[r].dataCount; | |
var ecCount = rsBlocks[r].totalCount - dcCount; | |
maxDcCount = Math.max(maxDcCount, dcCount); | |
maxEcCount = Math.max(maxEcCount, ecCount); | |
dcdata[r] = new Array(dcCount); | |
for (var i = 0; i < dcdata[r].length; i++) { | |
dcdata[r][i] = 0xff & buffer.buffer[i + offset]; | |
} | |
offset += dcCount; | |
var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount); | |
var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1); | |
var modPoly = rawPoly.mod(rsPoly); | |
ecdata[r] = new Array(rsPoly.getLength() - 1); | |
for (var i = 0; i < ecdata[r].length; i++) { | |
var modIndex = i + modPoly.getLength() - ecdata[r].length; | |
ecdata[r][i] = (modIndex >= 0)? modPoly.get(modIndex) : 0; | |
} | |
} | |
var totalCodeCount = 0; | |
for (var i = 0; i < rsBlocks.length; i++) { | |
totalCodeCount += rsBlocks[i].totalCount; | |
} | |
var data = new Array(totalCodeCount); | |
var index = 0; | |
for (var i = 0; i < maxDcCount; i++) { | |
for (var r = 0; r < rsBlocks.length; r++) { | |
if (i < dcdata[r].length) { | |
data[index++] = dcdata[r][i]; | |
} | |
} | |
} | |
for (var i = 0; i < maxEcCount; i++) { | |
for (var r = 0; r < rsBlocks.length; r++) { | |
if (i < ecdata[r].length) { | |
data[index++] = ecdata[r][i]; | |
} | |
} | |
} | |
return data; | |
} | |
//--------------------------------------------------------------------- | |
// QRMode | |
//--------------------------------------------------------------------- | |
var QRMode = { | |
MODE_NUMBER : 1 << 0, | |
MODE_ALPHA_NUM : 1 << 1, | |
MODE_8BIT_BYTE : 1 << 2, | |
MODE_KANJI : 1 << 3 | |
}; | |
//--------------------------------------------------------------------- | |
// QRErrorCorrectLevel | |
//--------------------------------------------------------------------- | |
var QRErrorCorrectLevel = { | |
L : 1, | |
M : 0, | |
Q : 3, | |
H : 2 | |
}; | |
//--------------------------------------------------------------------- | |
// QRMaskPattern | |
//--------------------------------------------------------------------- | |
var QRMaskPattern = { | |
PATTERN000 : 0, | |
PATTERN001 : 1, | |
PATTERN010 : 2, | |
PATTERN011 : 3, | |
PATTERN100 : 4, | |
PATTERN101 : 5, | |
PATTERN110 : 6, | |
PATTERN111 : 7 | |
}; | |
//--------------------------------------------------------------------- | |
// QRUtil | |
//--------------------------------------------------------------------- | |
var QRUtil = { | |
PATTERN_POSITION_TABLE : [ | |
[], | |
[6, 18], | |
[6, 22], | |
[6, 26], | |
[6, 30], | |
[6, 34], | |
[6, 22, 38], | |
[6, 24, 42], | |
[6, 26, 46], | |
[6, 28, 50], | |
[6, 30, 54], | |
[6, 32, 58], | |
[6, 34, 62], | |
[6, 26, 46, 66], | |
[6, 26, 48, 70], | |
[6, 26, 50, 74], | |
[6, 30, 54, 78], | |
[6, 30, 56, 82], | |
[6, 30, 58, 86], | |
[6, 34, 62, 90], | |
[6, 28, 50, 72, 94], | |
[6, 26, 50, 74, 98], | |
[6, 30, 54, 78, 102], | |
[6, 28, 54, 80, 106], | |
[6, 32, 58, 84, 110], | |
[6, 30, 58, 86, 114], | |
[6, 34, 62, 90, 118], | |
[6, 26, 50, 74, 98, 122], | |
[6, 30, 54, 78, 102, 126], | |
[6, 26, 52, 78, 104, 130], | |
[6, 30, 56, 82, 108, 134], | |
[6, 34, 60, 86, 112, 138], | |
[6, 30, 58, 86, 114, 142], | |
[6, 34, 62, 90, 118, 146], | |
[6, 30, 54, 78, 102, 126, 150], | |
[6, 24, 50, 76, 102, 128, 154], | |
[6, 28, 54, 80, 106, 132, 158], | |
[6, 32, 58, 84, 110, 136, 162], | |
[6, 26, 54, 82, 110, 138, 166], | |
[6, 30, 58, 86, 114, 142, 170] | |
], | |
G15 : (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0), | |
G18 : (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0), | |
G15_MASK : (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1), | |
getBCHTypeInfo : function(data) { | |
var d = data << 10; | |
while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) { | |
d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) ) ); | |
} | |
return ( (data << 10) | d) ^ QRUtil.G15_MASK; | |
}, | |
getBCHTypeNumber : function(data) { | |
var d = data << 12; | |
while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) { | |
d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) ) ); | |
} | |
return (data << 12) | d; | |
}, | |
getBCHDigit : function(data) { | |
var digit = 0; | |
while (data != 0) { | |
digit++; | |
data >>>= 1; | |
} | |
return digit; | |
}, | |
getPatternPosition : function(typeNumber) { | |
return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1]; | |
}, | |
getMask : function(maskPattern, i, j) { | |
switch (maskPattern) { | |
case QRMaskPattern.PATTERN000 : return (i + j) % 2 == 0; | |
case QRMaskPattern.PATTERN001 : return i % 2 == 0; | |
case QRMaskPattern.PATTERN010 : return j % 3 == 0; | |
case QRMaskPattern.PATTERN011 : return (i + j) % 3 == 0; | |
case QRMaskPattern.PATTERN100 : return (Math.floor(i / 2) + Math.floor(j / 3) ) % 2 == 0; | |
case QRMaskPattern.PATTERN101 : return (i * j) % 2 + (i * j) % 3 == 0; | |
case QRMaskPattern.PATTERN110 : return ( (i * j) % 2 + (i * j) % 3) % 2 == 0; | |
case QRMaskPattern.PATTERN111 : return ( (i * j) % 3 + (i + j) % 2) % 2 == 0; | |
default : | |
throw new Error("bad maskPattern:" + maskPattern); | |
} | |
}, | |
getErrorCorrectPolynomial : function(errorCorrectLength) { | |
var a = new QRPolynomial([1], 0); | |
for (var i = 0; i < errorCorrectLength; i++) { | |
a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0) ); | |
} | |
return a; | |
}, | |
getLengthInBits : function(mode, type) { | |
if (1 <= type && type < 10) { | |
// 1 - 9 | |
switch(mode) { | |
case QRMode.MODE_NUMBER : return 10; | |
case QRMode.MODE_ALPHA_NUM : return 9; | |
case QRMode.MODE_8BIT_BYTE : return 8; | |
case QRMode.MODE_KANJI : return 8; | |
default : | |
throw new Error("mode:" + mode); | |
} | |
} else if (type < 27) { | |
// 10 - 26 | |
switch(mode) { | |
case QRMode.MODE_NUMBER : return 12; | |
case QRMode.MODE_ALPHA_NUM : return 11; | |
case QRMode.MODE_8BIT_BYTE : return 16; | |
case QRMode.MODE_KANJI : return 10; | |
default : | |
throw new Error("mode:" + mode); | |
} | |
} else if (type < 41) { | |
// 27 - 40 | |
switch(mode) { | |
case QRMode.MODE_NUMBER : return 14; | |
case QRMode.MODE_ALPHA_NUM : return 13; | |
case QRMode.MODE_8BIT_BYTE : return 16; | |
case QRMode.MODE_KANJI : return 12; | |
default : | |
throw new Error("mode:" + mode); | |
} | |
} else { | |
throw new Error("type:" + type); | |
} | |
}, | |
getLostPoint : function(qrCode) { | |
var moduleCount = qrCode.getModuleCount(); | |
var lostPoint = 0; | |
// LEVEL1 | |
for (var row = 0; row < moduleCount; row++) { | |
for (var col = 0; col < moduleCount; col++) { | |
var sameCount = 0; | |
var dark = qrCode.isDark(row, col); | |
for (var r = -1; r <= 1; r++) { | |
if (row + r < 0 || moduleCount <= row + r) { | |
continue; | |
} | |
for (var c = -1; c <= 1; c++) { | |
if (col + c < 0 || moduleCount <= col + c) { | |
continue; | |
} | |
if (r == 0 && c == 0) { | |
continue; | |
} | |
if (dark == qrCode.isDark(row + r, col + c) ) { | |
sameCount++; | |
} | |
} | |
} | |
if (sameCount > 5) { | |
lostPoint += (3 + sameCount - 5); | |
} | |
} | |
} | |
// LEVEL2 | |
for (var row = 0; row < moduleCount - 1; row++) { | |
for (var col = 0; col < moduleCount - 1; col++) { | |
var count = 0; | |
if (qrCode.isDark(row, col ) ) count++; | |
if (qrCode.isDark(row + 1, col ) ) count++; | |
if (qrCode.isDark(row, col + 1) ) count++; | |
if (qrCode.isDark(row + 1, col + 1) ) count++; | |
if (count == 0 || count == 4) { | |
lostPoint += 3; | |
} | |
} | |
} | |
// LEVEL3 | |
for (var row = 0; row < moduleCount; row++) { | |
for (var col = 0; col < moduleCount - 6; col++) { | |
if (qrCode.isDark(row, col) | |
&& !qrCode.isDark(row, col + 1) | |
&& qrCode.isDark(row, col + 2) | |
&& qrCode.isDark(row, col + 3) | |
&& qrCode.isDark(row, col + 4) | |
&& !qrCode.isDark(row, col + 5) | |
&& qrCode.isDark(row, col + 6) ) { | |
lostPoint += 40; | |
} | |
} | |
} | |
for (var col = 0; col < moduleCount; col++) { | |
for (var row = 0; row < moduleCount - 6; row++) { | |
if (qrCode.isDark(row, col) | |
&& !qrCode.isDark(row + 1, col) | |
&& qrCode.isDark(row + 2, col) | |
&& qrCode.isDark(row + 3, col) | |
&& qrCode.isDark(row + 4, col) | |
&& !qrCode.isDark(row + 5, col) | |
&& qrCode.isDark(row + 6, col) ) { | |
lostPoint += 40; | |
} | |
} | |
} | |
// LEVEL4 | |
var darkCount = 0; | |
for (var col = 0; col < moduleCount; col++) { | |
for (var row = 0; row < moduleCount; row++) { | |
if (qrCode.isDark(row, col) ) { | |
darkCount++; | |
} | |
} | |
} | |
var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5; | |
lostPoint += ratio * 10; | |
return lostPoint; | |
} | |
}; | |
//--------------------------------------------------------------------- | |
// QRMath | |
//--------------------------------------------------------------------- | |
var QRMath = { | |
glog : function(n) { | |
if (n < 1) { | |
throw new Error("glog(" + n + ")"); | |
} | |
return QRMath.LOG_TABLE[n]; | |
}, | |
gexp : function(n) { | |
while (n < 0) { | |
n += 255; | |
} | |
while (n >= 256) { | |
n -= 255; | |
} | |
return QRMath.EXP_TABLE[n]; | |
}, | |
EXP_TABLE : new Array(256), | |
LOG_TABLE : new Array(256) | |
}; | |
for (var i = 0; i < 8; i++) { | |
QRMath.EXP_TABLE[i] = 1 << i; | |
} | |
for (var i = 8; i < 256; i++) { | |
QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] | |
^ QRMath.EXP_TABLE[i - 5] | |
^ QRMath.EXP_TABLE[i - 6] | |
^ QRMath.EXP_TABLE[i - 8]; | |
} | |
for (var i = 0; i < 255; i++) { | |
QRMath.LOG_TABLE[QRMath.EXP_TABLE[i] ] = i; | |
} | |
//--------------------------------------------------------------------- | |
// QRPolynomial | |
//--------------------------------------------------------------------- | |
function QRPolynomial(num, shift) { | |
if (num.length == undefined) { | |
throw new Error(num.length + "/" + shift); | |
} | |
var offset = 0; | |
while (offset < num.length && num[offset] == 0) { | |
offset++; | |
} | |
this.num = new Array(num.length - offset + shift); | |
for (var i = 0; i < num.length - offset; i++) { | |
this.num[i] = num[i + offset]; | |
} | |
} | |
QRPolynomial.prototype = { | |
get : function(index) { | |
return this.num[index]; | |
}, | |
getLength : function() { | |
return this.num.length; | |
}, | |
multiply : function(e) { | |
var num = new Array(this.getLength() + e.getLength() - 1); | |
for (var i = 0; i < this.getLength(); i++) { | |
for (var j = 0; j < e.getLength(); j++) { | |
num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i) ) + QRMath.glog(e.get(j) ) ); | |
} | |
} | |
return new QRPolynomial(num, 0); | |
}, | |
mod : function(e) { | |
if (this.getLength() - e.getLength() < 0) { | |
return this; | |
} | |
var ratio = QRMath.glog(this.get(0) ) - QRMath.glog(e.get(0) ); | |
var num = new Array(this.getLength() ); | |
for (var i = 0; i < this.getLength(); i++) { | |
num[i] = this.get(i); | |
} | |
for (var i = 0; i < e.getLength(); i++) { | |
num[i] ^= QRMath.gexp(QRMath.glog(e.get(i) ) + ratio); | |
} | |
// recursive call | |
return new QRPolynomial(num, 0).mod(e); | |
} | |
}; | |
//--------------------------------------------------------------------- | |
// QRRSBlock | |
//--------------------------------------------------------------------- | |
function QRRSBlock(totalCount, dataCount) { | |
this.totalCount = totalCount; | |
this.dataCount = dataCount; | |
} | |
QRRSBlock.RS_BLOCK_TABLE = [ | |
// L | |
// M | |
// Q | |
// H | |
// 1 | |
[1, 26, 19], | |
[1, 26, 16], | |
[1, 26, 13], | |
[1, 26, 9], | |
// 2 | |
[1, 44, 34], | |
[1, 44, 28], | |
[1, 44, 22], | |
[1, 44, 16], | |
// 3 | |
[1, 70, 55], | |
[1, 70, 44], | |
[2, 35, 17], | |
[2, 35, 13], | |
// 4 | |
[1, 100, 80], | |
[2, 50, 32], | |
[2, 50, 24], | |
[4, 25, 9], | |
// 5 | |
[1, 134, 108], | |
[2, 67, 43], | |
[2, 33, 15, 2, 34, 16], | |
[2, 33, 11, 2, 34, 12], | |
// 6 | |
[2, 86, 68], | |
[4, 43, 27], | |
[4, 43, 19], | |
[4, 43, 15], | |
// 7 | |
[2, 98, 78], | |
[4, 49, 31], | |
[2, 32, 14, 4, 33, 15], | |
[4, 39, 13, 1, 40, 14], | |
// 8 | |
[2, 121, 97], | |
[2, 60, 38, 2, 61, 39], | |
[4, 40, 18, 2, 41, 19], | |
[4, 40, 14, 2, 41, 15], | |
// 9 | |
[2, 146, 116], | |
[3, 58, 36, 2, 59, 37], | |
[4, 36, 16, 4, 37, 17], | |
[4, 36, 12, 4, 37, 13], | |
// 10 | |
[2, 86, 68, 2, 87, 69], | |
[4, 69, 43, 1, 70, 44], | |
[6, 43, 19, 2, 44, 20], | |
[6, 43, 15, 2, 44, 16], | |
// 11 | |
[4, 101, 81], | |
[1, 80, 50, 4, 81, 51], | |
[4, 50, 22, 4, 51, 23], | |
[3, 36, 12, 8, 37, 13], | |
// 12 | |
[2, 116, 92, 2, 117, 93], | |
[6, 58, 36, 2, 59, 37], | |
[4, 46, 20, 6, 47, 21], | |
[7, 42, 14, 4, 43, 15], | |
// 13 | |
[4, 133, 107], | |
[8, 59, 37, 1, 60, 38], | |
[8, 44, 20, 4, 45, 21], | |
[12, 33, 11, 4, 34, 12], | |
// 14 | |
[3, 145, 115, 1, 146, 116], | |
[4, 64, 40, 5, 65, 41], | |
[11, 36, 16, 5, 37, 17], | |
[11, 36, 12, 5, 37, 13], | |
// 15 | |
[5, 109, 87, 1, 110, 88], | |
[5, 65, 41, 5, 66, 42], | |
[5, 54, 24, 7, 55, 25], | |
[11, 36, 12], | |
// 16 | |
[5, 122, 98, 1, 123, 99], | |
[7, 73, 45, 3, 74, 46], | |
[15, 43, 19, 2, 44, 20], | |
[3, 45, 15, 13, 46, 16], | |
// 17 | |
[1, 135, 107, 5, 136, 108], | |
[10, 74, 46, 1, 75, 47], | |
[1, 50, 22, 15, 51, 23], | |
[2, 42, 14, 17, 43, 15], | |
// 18 | |
[5, 150, 120, 1, 151, 121], | |
[9, 69, 43, 4, 70, 44], | |
[17, 50, 22, 1, 51, 23], | |
[2, 42, 14, 19, 43, 15], | |
// 19 | |
[3, 141, 113, 4, 142, 114], | |
[3, 70, 44, 11, 71, 45], | |
[17, 47, 21, 4, 48, 22], | |
[9, 39, 13, 16, 40, 14], | |
// 20 | |
[3, 135, 107, 5, 136, 108], | |
[3, 67, 41, 13, 68, 42], | |
[15, 54, 24, 5, 55, 25], | |
[15, 43, 15, 10, 44, 16], | |
// 21 | |
[4, 144, 116, 4, 145, 117], | |
[17, 68, 42], | |
[17, 50, 22, 6, 51, 23], | |
[19, 46, 16, 6, 47, 17], | |
// 22 | |
[2, 139, 111, 7, 140, 112], | |
[17, 74, 46], | |
[7, 54, 24, 16, 55, 25], | |
[34, 37, 13], | |
// 23 | |
[4, 151, 121, 5, 152, 122], | |
[4, 75, 47, 14, 76, 48], | |
[11, 54, 24, 14, 55, 25], | |
[16, 45, 15, 14, 46, 16], | |
// 24 | |
[6, 147, 117, 4, 148, 118], | |
[6, 73, 45, 14, 74, 46], | |
[11, 54, 24, 16, 55, 25], | |
[30, 46, 16, 2, 47, 17], | |
// 25 | |
[8, 132, 106, 4, 133, 107], | |
[8, 75, 47, 13, 76, 48], | |
[7, 54, 24, 22, 55, 25], | |
[22, 45, 15, 13, 46, 16], | |
// 26 | |
[10, 142, 114, 2, 143, 115], | |
[19, 74, 46, 4, 75, 47], | |
[28, 50, 22, 6, 51, 23], | |
[33, 46, 16, 4, 47, 17], | |
// 27 | |
[8, 152, 122, 4, 153, 123], | |
[22, 73, 45, 3, 74, 46], | |
[8, 53, 23, 26, 54, 24], | |
[12, 45, 15, 28, 46, 16], | |
// 28 | |
[3, 147, 117, 10, 148, 118], | |
[3, 73, 45, 23, 74, 46], | |
[4, 54, 24, 31, 55, 25], | |
[11, 45, 15, 31, 46, 16], | |
// 29 | |
[7, 146, 116, 7, 147, 117], | |
[21, 73, 45, 7, 74, 46], | |
[1, 53, 23, 37, 54, 24], | |
[19, 45, 15, 26, 46, 16], | |
// 30 | |
[5, 145, 115, 10, 146, 116], | |
[19, 75, 47, 10, 76, 48], | |
[15, 54, 24, 25, 55, 25], | |
[23, 45, 15, 25, 46, 16], | |
// 31 | |
[13, 145, 115, 3, 146, 116], | |
[2, 74, 46, 29, 75, 47], | |
[42, 54, 24, 1, 55, 25], | |
[23, 45, 15, 28, 46, 16], | |
// 32 | |
[17, 145, 115], | |
[10, 74, 46, 23, 75, 47], | |
[10, 54, 24, 35, 55, 25], | |
[19, 45, 15, 35, 46, 16], | |
// 33 | |
[17, 145, 115, 1, 146, 116], | |
[14, 74, 46, 21, 75, 47], | |
[29, 54, 24, 19, 55, 25], | |
[11, 45, 15, 46, 46, 16], | |
// 34 | |
[13, 145, 115, 6, 146, 116], | |
[14, 74, 46, 23, 75, 47], | |
[44, 54, 24, 7, 55, 25], | |
[59, 46, 16, 1, 47, 17], | |
// 35 | |
[12, 151, 121, 7, 152, 122], | |
[12, 75, 47, 26, 76, 48], | |
[39, 54, 24, 14, 55, 25], | |
[22, 45, 15, 41, 46, 16], | |
// 36 | |
[6, 151, 121, 14, 152, 122], | |
[6, 75, 47, 34, 76, 48], | |
[46, 54, 24, 10, 55, 25], | |
[2, 45, 15, 64, 46, 16], | |
// 37 | |
[17, 152, 122, 4, 153, 123], | |
[29, 74, 46, 14, 75, 47], | |
[49, 54, 24, 10, 55, 25], | |
[24, 45, 15, 46, 46, 16], | |
// 38 | |
[4, 152, 122, 18, 153, 123], | |
[13, 74, 46, 32, 75, 47], | |
[48, 54, 24, 14, 55, 25], | |
[42, 45, 15, 32, 46, 16], | |
// 39 | |
[20, 147, 117, 4, 148, 118], | |
[40, 75, 47, 7, 76, 48], | |
[43, 54, 24, 22, 55, 25], | |
[10, 45, 15, 67, 46, 16], | |
// 40 | |
[19, 148, 118, 6, 149, 119], | |
[18, 75, 47, 31, 76, 48], | |
[34, 54, 24, 34, 55, 25], | |
[20, 45, 15, 61, 46, 16] | |
]; | |
QRRSBlock.getRSBlocks = function(typeNumber, errorCorrectLevel) { | |
var rsBlock = QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel); | |
if (rsBlock == undefined) { | |
throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + errorCorrectLevel); | |
} | |
var length = rsBlock.length / 3; | |
var list = new Array(); | |
for (var i = 0; i < length; i++) { | |
var count = rsBlock[i * 3 + 0]; | |
var totalCount = rsBlock[i * 3 + 1]; | |
var dataCount = rsBlock[i * 3 + 2]; | |
for (var j = 0; j < count; j++) { | |
list.push(new QRRSBlock(totalCount, dataCount) ); | |
} | |
} | |
return list; | |
} | |
QRRSBlock.getRsBlockTable = function(typeNumber, errorCorrectLevel) { | |
switch(errorCorrectLevel) { | |
case QRErrorCorrectLevel.L : | |
return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0]; | |
case QRErrorCorrectLevel.M : | |
return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1]; | |
case QRErrorCorrectLevel.Q : | |
return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2]; | |
case QRErrorCorrectLevel.H : | |
return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3]; | |
default : | |
return undefined; | |
} | |
} | |
//--------------------------------------------------------------------- | |
// QRBitBuffer | |
//--------------------------------------------------------------------- | |
function QRBitBuffer() { | |
this.buffer = new Array(); | |
this.length = 0; | |
} | |
QRBitBuffer.prototype = { | |
get : function(index) { | |
var bufIndex = Math.floor(index / 8); | |
return ( (this.buffer[bufIndex] >>> (7 - index % 8) ) & 1) == 1; | |
}, | |
put : function(num, length) { | |
for (var i = 0; i < length; i++) { | |
this.putBit( ( (num >>> (length - i - 1) ) & 1) == 1); | |
} | |
}, | |
getLengthInBits : function() { | |
return this.length; | |
}, | |
putBit : function(bit) { | |
var bufIndex = Math.floor(this.length / 8); | |
if (this.buffer.length <= bufIndex) { | |
this.buffer.push(0); | |
} | |
if (bit) { | |
this.buffer[bufIndex] |= (0x80 >>> (this.length % 8) ); | |
} | |
this.length++; | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment