qrcode
Advanced tools
Comparing version 0.1.1 to 0.2.2
/** | ||
this comtains the max string length for all qr code Versions in Binary Safe / Byte Mode | ||
this contains the max string length for all qr code Versions in Binary Safe / Byte Mode | ||
each entry is in the order of error correct level | ||
@@ -10,3 +10,3 @@ [L,M,Q,H] | ||
var _QRVersionCapacityTable = module.exports = [ | ||
exports.QRCapacityTable = [ | ||
[17,14,11,7] | ||
@@ -52,2 +52,2 @@ ,[32,26,20,14] | ||
,[2953,2331,1663,1273]//40 | ||
]; | ||
]; |
/* | ||
* copyright 2010 Ryan Day | ||
* http://github.com/soldair/node-qrcode | ||
* | ||
* Licensed under the MIT license: | ||
* http://www.opensource.org/licenses/mit-license.php | ||
* | ||
* canvas example and fallback support example provided by Joshua Koo | ||
* http://jabtunes.com/labs/qrcode.html | ||
* "Instant QRCode Mashup by Joshua Koo!" | ||
* as far as i can tell the page and the code on the page are public domain - Ryan | ||
* | ||
* original table example and library provided by Kazuhiko Arase | ||
* http://d-project.googlecode.com/svn/trunk/misc/qrcode/js/ | ||
*/ | ||
* copyright 2010 Ryan Day | ||
* http://github.com/soldair/node-qrcode | ||
* | ||
* Licensed under the MIT license: | ||
* http://www.opensource.org/licenses/mit-license.php | ||
* | ||
* canvas example and fallback support example provided by Joshua Koo | ||
* http://jabtunes.com/labs/qrcode.html | ||
* "Instant QRCode Mashup by Joshua Koo!" | ||
* as far as i can tell the page and the code on the page are public domain | ||
* | ||
* original table example and library provided by Kazuhiko Arase | ||
* http://d-project.googlecode.com/svn/trunk/misc/qrcode/js/ | ||
* | ||
*/ | ||
var QRCodeLib = require(__dirname+'/qrcode.js') | ||
,QRVersionCapacityTable = require(__dirname+'/qrcapacitytable.js'); | ||
var QRCodeLib = require('./qrcode.js'); | ||
var QRVersionCapacityTable = require('./qrcapacitytable.js').QRCapacityTable; | ||
var QRCode = QRCodeLib.QRCode; | ||
//client side compat. set global assignment to local expected values. | ||
if(typeof exports == 'undefined') exports = {}; | ||
if(typeof QRCode != 'undefined') { | ||
QRCodeLib.QRCode = QRCode; | ||
QRCodeLib.QRErrorCorrectLevel = QRErrorCorrectLevel; | ||
QRVersionCapacityTable = _QRVersionCapacityTable | ||
} | ||
//export QRCodeDraw | ||
var QRCodeDraw = module.exports = exports = { | ||
scale:4, | ||
defaultMargin:20, | ||
marginScaleFactor:5, | ||
// you may configure the error behavior for input string too long | ||
errorBehavior:{ | ||
length:'trim' | ||
}, | ||
color:{ | ||
dark:'black', | ||
light:'white' | ||
}, | ||
defaultErrorCorrectLevel:QRCodeLib.QRErrorCorrectLevel.H, | ||
QRErrorCorrectLevel:QRCodeLib.QRErrorCorrectLevel, | ||
draw:function(canvas,text/*,errorCorrectLevel,cb*/) { | ||
var cb,errorCorrectLevel | ||
,level,error; | ||
exports.QRCodeDraw = QRCodeDraw; | ||
exports.QRVersionCapacityTable = QRVersionCapacityTable; | ||
exports.QRErrorCorrectLevel = QRCodeLib.QRErrorCorrectLevel; | ||
exports.QRCode = QRCodeLib.QRCode; | ||
//argument processing | ||
if(arguments.length == 2 || typeof arguments[arguments.length-1] != 'function') { | ||
//enforce callback api just in case the processing can be made async in the future | ||
// or support proc open to libqrencode | ||
throw new Error('callback required as last argument'); | ||
} | ||
cb = arguments[arguments.length-1]; | ||
if(arguments.length > 3){ | ||
errorCorrectLevel = arguments[2]; | ||
} | ||
//this interface kinda sucks - there is very small likelyhood of this ever being async | ||
this.QRLevel(text,errorCorrectLevel,function(e,t,l,ec){ | ||
text = t,level = l,error = e,errorCorrectLevel = ec; | ||
}); | ||
function QRCodeDraw(){} | ||
if(!level) { | ||
//if we are unable to find an appropriate qr level error out | ||
cb(error,canvas); | ||
return; | ||
} | ||
QRCodeDraw.prototype = { | ||
scale:4,//4 px module size | ||
defaultMargin:20, | ||
marginScaleFactor:5, | ||
Array:(typeof Uint32Array == 'undefined'?Uint32Array:Array), | ||
// you may configure the error behavior for input string too long | ||
errorBehavior:{ | ||
length:'trim' | ||
}, | ||
color:{ | ||
dark:'black', | ||
light:'white' | ||
}, | ||
defaultErrorCorrectLevel:QRCodeLib.QRErrorCorrectLevel.H, | ||
QRErrorCorrectLevel:QRCodeLib.QRErrorCorrectLevel, | ||
draw:function(canvas,text,options,cb){ | ||
var cb, | ||
options = {}, | ||
level, | ||
error; | ||
//create qrcode! | ||
try{ | ||
var qr = new QRCodeLib.QRCode(level, errorCorrectLevel) | ||
, scale = this.scale||4 | ||
, ctx = canvas.getContext('2d') | ||
, width = 0; | ||
var args = Array.prototype.slice.call(arguments); | ||
cb = args.pop(); | ||
canvas = args.shift(); | ||
options = args.shift()||{}; | ||
qr.addData(text); | ||
qr.make(); | ||
if(typeof cb != 'function') { | ||
//enforce callback api just in case the processing can be made async in the future | ||
// or support proc open to libqrencode | ||
throw new Error('callback required'); | ||
} | ||
if(typeof options !== "object"){ | ||
options.errorCorrectLevel = options; | ||
} | ||
var margin = this.defaultMargin | ||
//elegant white space next to | ||
if (scale * this.marginScaleFactor > margin) { | ||
margin = scale * this.marginScaleFactor; | ||
} | ||
var currenty = margin | ||
width = qr.getModuleCount()*scale + margin*2; | ||
this.resetCanvas(canvas,ctx,width); | ||
for (var r = 0; r < qr.getModuleCount(); r++) { | ||
var currentx = margin; | ||
for (var c = 0; c < qr.getModuleCount(); c++) { | ||
if (qr.isDark(r, c) ) { | ||
ctx.fillStyle = this.color.dark; | ||
ctx.fillRect (currentx, currenty, 1*scale, 1*scale); | ||
} else if(this.color.light){ | ||
//if falsy configured color | ||
ctx.fillStyle = this.color.light; | ||
ctx.fillRect (currentx, currenty, 1*scale, 1*scale); | ||
} | ||
currentx += scale *1; | ||
} | ||
currenty += scale*1; | ||
} | ||
} catch (e) { | ||
error = e; | ||
} | ||
cb(error,canvas,width); | ||
}, | ||
//changed the interface here | ||
QRLevel:function(text,errorCorrectLevel,cb){ | ||
var c = text.length | ||
, error | ||
, level = 0 | ||
,errorCorrectLevel = this.QRErrorCorrectLevel[errorCorrectLevel]||this.defaultErrorCorrectLevel | ||
,errorCorrectIndex = [1,0,3,2]//fix odd mapping to order in table | ||
,keys = ['L','M','Q','H']; | ||
this.QRVersion(text,options.errorCorrectLevel||this.QRErrorCorrectLevel.H,options.version,function(e,t,l,ec){ | ||
text = t,level = l,error = e,errorCorrectLevel = ec; | ||
}); | ||
this.scale = options.scale||this.scale; | ||
this.margin = options.margin||this.scale*2; | ||
if(!level) { | ||
//if we are unable to find an appropriate qr level error out | ||
cb(error,canvas); | ||
return; | ||
} | ||
//TODO ADD THROW FOR INVALID errorCorrectLevel? | ||
for(var i=0,j=QRVersionCapacityTable.length;i<j;i++) { | ||
if(c < QRVersionCapacityTable[i][errorCorrectIndex[errorCorrectLevel]]){ | ||
level = i+1; | ||
break; | ||
} | ||
} | ||
//create qrcode! | ||
try{ | ||
var qr = new QRCodeLib.QRCode(level, errorCorrectLevel) | ||
, scale = this.scale||4 | ||
, ctx = canvas.getContext('2d') | ||
, width = 0; | ||
//console.log('error correct level: '+keys[errorCorrectIndex[errorCorrectLevel]]); | ||
//console.log('qr code level: '+level); | ||
qr.addData(text); | ||
qr.make(); | ||
if(!level){ | ||
if(this.errorBehavior.length == 'trim'){ | ||
text = text.substr(0,QRVersionCapacityTable[QRVersionCapacityTable.length-1][errorCorrectIndex[errorCorrectLevel]]); | ||
level = QRVersionCapacityTable.length; | ||
} else { | ||
error = new Error('input string too long for error correction ' | ||
+keys[errorCorrectIndex[errorCorrectLevel]] | ||
+' max length ' | ||
+QRVersionCapacityTable[QRVersionCapacityTable.length-1][errorCorrectIndex[errorCorrectLevel]] | ||
+' for qrcode version '+(QRVersionCapacityTable.length-1) | ||
); | ||
} | ||
} | ||
if(cb) { | ||
cb(error,text,level,errorCorrectLevel); | ||
} | ||
return level; | ||
}, | ||
resetCanvas:function(canvas,ctx,width){ | ||
ctx.clearRect(0,0,canvas.width,canvas.height); | ||
if(!canvas.style) canvas.style = {}; | ||
canvas.style.height = canvas.height = width;//square! | ||
canvas.style.width = canvas.width = width; | ||
if(this.color.light){ | ||
ctx.fillStyle = this.color.light; | ||
ctx.fillRect(0,0,canvas.width,canvas.height); | ||
} else { | ||
//support transparent backgrounds? | ||
//not exactly to spec but i really would like someone to be able to add a background with heavily reduced luminosity for simple branding | ||
//i could just ditch this because you could also just set #******00 as the color =P | ||
ctx.clearRect(0,0,canvas.width,canvas.height); | ||
} | ||
var margin = this.marginWidth(); | ||
var currenty = margin; | ||
width = this.dataWidth(qr)+ margin*2; | ||
this.resetCanvas(canvas,ctx,width); | ||
} | ||
}; | ||
for (var r = 0,rl=qr.getModuleCount(); r < rl; r++) { | ||
var currentx = margin; | ||
for (var c = 0,cl=qr.getModuleCount(); c < cl; c++) { | ||
if (qr.isDark(r, c) ) { | ||
ctx.fillStyle = this.color.dark; | ||
ctx.fillRect (currentx, currenty, scale, scale); | ||
} else if(this.color.light){ | ||
//if falsy configured color | ||
ctx.fillStyle = this.color.light; | ||
ctx.fillRect (currentx, currenty, scale, scale); | ||
} | ||
currentx += scale; | ||
} | ||
currenty += scale; | ||
} | ||
} catch (e) { | ||
error = e; | ||
} | ||
cb(error,canvas,width); | ||
}, | ||
drawBitArray:function(text/*,errorCorrectLevel,options,cb*/) { | ||
var args = Array.prototype.slice.call(arguments), | ||
cb = args.pop(), | ||
text = args.shift(), | ||
errorCorrectLevel = args.shift(), | ||
options = args.shift() || {}; | ||
//argument processing | ||
if(typeof cb != 'function') { | ||
//enforce callback api just in case the processing can be made async in the future | ||
// or support proc open to libqrencode | ||
throw new Error('callback required as last argument'); | ||
} | ||
cb = arguments[arguments.length-1]; | ||
if(arguments.length > 2){ | ||
errorCorrectLevel = arguments[2]; | ||
} | ||
//this interface kinda sucks - there is very small likelyhood of this ever being async | ||
this.QRVersion(text,errorCorrectLevel,(options||{}).version,function(e,t,l,ec){ | ||
text = t,level = l,error = e,errorCorrectLevel = ec; | ||
}); | ||
//console.log(text,level,error,errorCorrectLevel); | ||
if(!level) { | ||
//if we are unable to find an appropriate qr level error out | ||
cb(error,[],0); | ||
return; | ||
} | ||
//create qrcode! | ||
try{ | ||
var qr = new QRCodeLib.QRCode(level, errorCorrectLevel) | ||
, scale = this.scale||4 | ||
, width = 0,bits,bitc=0,currenty=0; | ||
qr.addData(text); | ||
qr.make(); | ||
width = this.dataWidth(qr,1); | ||
bits = new this.Array(width*width); | ||
for (var r = 0,rl=qr.getModuleCount(); r < rl; r++) { | ||
for (var c = 0,cl=qr.getModuleCount(); c < cl; c++) { | ||
if (qr.isDark(r, c) ) { | ||
bits[bitc] = 1; | ||
} else { | ||
bits[bitc] = 0; | ||
} | ||
bitc++; | ||
} | ||
} | ||
} catch (e) { | ||
error = e; | ||
console.log(e.stack); | ||
} | ||
cb(error,bits,width); | ||
}, | ||
QRVersion:function(text,errorCorrectLevel,version,cb){ | ||
var c = text.length, | ||
error, | ||
errorCorrectLevel = this.QRErrorCorrectLevel[errorCorrectLevel]||this.defaultErrorCorrectLevel, | ||
errorCorrectIndex = [1,0,3,2],//fix odd mapping to order in table | ||
keys = ['L','M','Q','H'], | ||
capacity = 0, | ||
versionSpecified = false; | ||
if(typeof version !== "undefined" && version !== null) { | ||
versionSpecified = true; | ||
} | ||
//TODO ADD THROW FOR INVALID errorCorrectLevel...? | ||
if(versionSpecified){ | ||
console.log('SPECIFIED VERSION! ',version); | ||
//i have specified a version. this will give me a fixed size qr code. version must be valid. 1-40 | ||
capacity = QRVersionCapacityTable[version][errorCorrectIndex[errorCorrectLevel]]; | ||
} else { | ||
//figure out what version can hold the amount of text | ||
for(var i=0,j=QRVersionCapacityTable.length;i<j;i++) { | ||
capacity = QRVersionCapacityTable[i][errorCorrectIndex[errorCorrectLevel]]; | ||
if(c < QRVersionCapacityTable[i][errorCorrectIndex[errorCorrectLevel]]){ | ||
version = i+1; | ||
break; | ||
} | ||
} | ||
//if not version set to max | ||
if(!version) { | ||
version = QRVersionCapacityTable.length-1; | ||
} | ||
} | ||
if(capacity < c){ | ||
if(this.errorBehavior.length == 'trim'){ | ||
text = text.substr(0,capacity); | ||
level = QRVersionCapacityTable.length; | ||
} else { | ||
error = new Error('input string too long for error correction ' | ||
+keys[errorCorrectIndex[errorCorrectLevel]] | ||
+' max length ' | ||
+ capacity | ||
+' for qrcode version '+version | ||
); | ||
} | ||
} | ||
if(cb) { | ||
cb(error,text,version,errorCorrectLevel); | ||
} | ||
return version; | ||
}, | ||
marginWidth:function(){ | ||
var margin = this.defaultMargin; | ||
this.scale = this.scale||4; | ||
//elegant white space next to code is required by spec | ||
if (this.scale * this.marginScaleFactor > margin) { | ||
margin = this.scale * this.marginScaleFactor; | ||
} | ||
return margin; | ||
}, | ||
dataWidth:function(qr,scale){ | ||
return qr.getModuleCount()*(scale||this.scale||4); | ||
}, | ||
resetCanvas:function(canvas,ctx,width){ | ||
ctx.clearRect(0,0,canvas.width,canvas.height); | ||
if(!canvas.style) canvas.style = {}; | ||
canvas.style.height = canvas.height = width;//square! | ||
canvas.style.width = canvas.width = width; | ||
if(this.color.light){ | ||
ctx.fillStyle = this.color.light; | ||
ctx.fillRect(0,0,canvas.width,canvas.height); | ||
} else { | ||
//support transparent backgrounds? | ||
//not exactly to spec but i really would like someone to be able to add a background with heavily reduced luminosity for simple branding | ||
//i could just ditch this because you could also just set #******00 as the color =P | ||
ctx.clearRect(0,0,canvas.width,canvas.height); | ||
} | ||
} | ||
}; | ||
@@ -1,7 +0,10 @@ | ||
/*--------------------------------------------------------------------- | ||
/** | ||
* QRCode for JavaScript | ||
* | ||
* modified by Ryan Day for nodejs/common js support | ||
* Copyright (c) 2010 Ryan Day | ||
* modified by Ryan Day for nodejs support | ||
* Copyright (c) 2011 Ryan Day | ||
* | ||
* Licensed under the MIT license: | ||
* http://www.opensource.org/licenses/mit-license.php | ||
* | ||
* EXPORTS: | ||
@@ -12,10 +15,2 @@ * { | ||
* } | ||
*/ | ||
//client side compat | ||
if(typeof exports == 'undefined') exports = {}; | ||
if(typeof module == 'undefined') module = {exports:{}}; | ||
if(typeof require != 'function') require = function(){return {}}; | ||
if(typeof __dirname == 'undefined') __dirname = ''; | ||
//--------------------------------------------------------------------- | ||
@@ -36,30 +31,12 @@ // QRCode for JavaScript | ||
//--------------------------------------------------------------------- | ||
*/ | ||
//--------------------------------------------------------------------- | ||
// QR8bitByte | ||
// QRCode | ||
//--------------------------------------------------------------------- | ||
function QR8bitByte(data) { | ||
this.mode = QRMode.MODE_8BIT_BYTE; | ||
this.data = data; | ||
} | ||
exports.QRCode = QRCode; | ||
QR8bitByte.prototype = { | ||
var QRDataArray = (typeof Uint32Array == 'undefined'?Uint32Array:Array); | ||
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) { | ||
@@ -71,6 +48,4 @@ this.typeNumber = typeNumber; | ||
this.dataCache = null; | ||
this.dataList = new Array(); | ||
this.dataList = new QRDataArray(); | ||
} | ||
//EXPORT! | ||
exports.QRCode = QRCode; | ||
@@ -103,7 +78,7 @@ QRCode.prototype = { | ||
this.moduleCount = this.typeNumber * 4 + 17; | ||
this.modules = new Array(this.moduleCount); | ||
this.modules = new QRDataArray(this.moduleCount); | ||
for (var row = 0; row < this.moduleCount; row++) { | ||
this.modules[row] = new Array(this.moduleCount); | ||
this.modules[row] = new QRDataArray(this.moduleCount); | ||
@@ -383,3 +358,3 @@ for (var col = 0; col < this.moduleCount; col++) { | ||
return QRCode.createBytes(buffer, rsBlocks); | ||
} | ||
}; | ||
@@ -393,4 +368,4 @@ QRCode.createBytes = function(buffer, rsBlocks) { | ||
var dcdata = new Array(rsBlocks.length); | ||
var ecdata = new Array(rsBlocks.length); | ||
var dcdata = new QRDataArray(rsBlocks.length); | ||
var ecdata = new QRDataArray(rsBlocks.length); | ||
@@ -405,3 +380,3 @@ for (var r = 0; r < rsBlocks.length; r++) { | ||
dcdata[r] = new Array(dcCount); | ||
dcdata[r] = new QRDataArray(dcCount); | ||
@@ -417,3 +392,3 @@ for (var i = 0; i < dcdata[r].length; i++) { | ||
var modPoly = rawPoly.mod(rsPoly); | ||
ecdata[r] = new Array(rsPoly.getLength() - 1); | ||
ecdata[r] = new QRDataArray(rsPoly.getLength() - 1); | ||
for (var i = 0; i < ecdata[r].length; i++) { | ||
@@ -431,3 +406,3 @@ var modIndex = i + modPoly.getLength() - ecdata[r].length; | ||
var data = new Array(totalCodeCount); | ||
var data = new QRDataArray(totalCodeCount); | ||
var index = 0; | ||
@@ -453,4 +428,27 @@ | ||
}; | ||
//--------------------------------------------------------------------- | ||
// 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); | ||
} | ||
} | ||
}; | ||
//--------------------------------------------------------------------- | ||
@@ -470,5 +468,4 @@ // QRMode | ||
//--------------------------------------------------------------------- | ||
//QRCodeLib is used when called from client side js | ||
//exported | ||
var QRErrorCorrectLevel = exports.QRErrorCorrectLevel = { | ||
@@ -475,0 +472,0 @@ L : 1, |
{ "name": "qrcode" | ||
, "description": "QRCode / 2d Barcode api with both server side and client side support using canvas" | ||
, "version": "0.1.1" | ||
, "author": "Ryan Day <soldair@gmail.com>" | ||
, "keywords": ["canvas", "qrcode", "barcode"] | ||
, "main": "./qrcode.js" | ||
,"description": "QRCode / 2d Barcode api with both server side and client side support using canvas" | ||
,"version": "0.2.2" | ||
,"author": "Ryan Day <soldair@gmail.com>" | ||
,"keywords": ["canvas", "qrcode", "barcode"] | ||
,"main": "./qrcode.js" | ||
,"homepage":"http://github.com/soldair/node-qrcode" | ||
,"scripts":{ | ||
"pretest":"node build.js" | ||
,"prepublish":"node build.js" | ||
,"test":"./test.sh" | ||
} | ||
,"bin":{ | ||
"qrcode":"./bin/qrcode" | ||
} | ||
,"dependencies": { | ||
"canvas": ">= 0.4.3" | ||
"canvas": ">= 0.4.3", | ||
"colors":"*" | ||
} | ||
,"devDependencies":{ | ||
"express":"2.5.x" | ||
,"browserify":"1.9.x" | ||
,"uglify-js":"1.2.x" | ||
} | ||
,"repository":{ | ||
@@ -12,0 +26,0 @@ "type":"git" |
136
qrcode.js
@@ -1,41 +0,112 @@ | ||
var QRCodeDraw = require(__dirname+'/lib/qrcode-draw') | ||
, Canvas = require('canvas') | ||
, fs = require('fs'); | ||
/* | ||
*copyright Ryan Day 2012 | ||
* | ||
* Licensed under the MIT license: | ||
* http://www.opensource.org/licenses/mit-license.php | ||
* | ||
* this is the main server side application file for node-qrcode. | ||
* these exports use serverside canvas api methods for file IO and buffers | ||
* | ||
*/ | ||
var QRCodeLib = require(__dirname+'/lib/qrcode-draw') | ||
, terminalRender = require(__dirname+'/lib/termialrender.js') | ||
, Canvas = require('canvas') | ||
, fs = require('fs'); | ||
var QRCodeDraw = QRCodeLib.QRCodeDraw, | ||
QRCode = QRCodeLib.QRCode; | ||
//EXPORTS | ||
// | ||
// breaking change to 0.1 this used to be an instance. now it returns the constructor. | ||
// | ||
exports.QRCodeDraw = QRCodeDraw; | ||
/* | ||
* provide an api to return the max characters allowed for given dimensions, and miniumum error correction level | ||
* the qr code library will always use the maximum error correction level for the given numbar of chars constrained by size | ||
*/ | ||
exports.getMaxChars = function(minErrorCorrectionLevel,width,moduleScale){ | ||
//TODO THIS NEEDS TO WORK | ||
console.log('this doesnt work yet. comming soon =)'); | ||
}; | ||
// returns Canvas Object with qr code drawn on it | ||
var draw = exports.draw = function(text,cb){ | ||
/* | ||
* String text, optional Object options, Function callback | ||
*/ | ||
var draw = exports.draw = function(text,options,cb){ | ||
var args = Array.prototype.slice.call(arguments); | ||
cb = args.pop(); | ||
if(typeof cb != 'function') { | ||
throw new TypeError('last argument must be a function'); | ||
} | ||
text = args.shift(); | ||
options = args.shift()||{}; | ||
//NOTE the width and height are determined from within the qr code lib and are not configurable from the outside yet | ||
QRCodeDraw.draw(new Canvas(200,200),text,function(error,canvas){ | ||
var drawInstance = new QRCodeDraw(); | ||
drawInstance.draw(new Canvas(200,200),text,options,function(error,canvas){ | ||
cb(error,canvas) | ||
}); | ||
} | ||
}; | ||
//returns data uri for drawn qrcode png | ||
var dataURL = exports.toDataURL = function(text,cb){ | ||
draw(text,function(error,canvas){ | ||
if(error) { | ||
cb(error,''); | ||
} else { | ||
canvas.toDataURL(cb); | ||
} | ||
}); | ||
exports.toDataURL = exports.toDataURI = function(text,cb){ | ||
draw(text,function(error,canvas){ | ||
if(error) { | ||
cb(error,''); | ||
} else { | ||
canvas.toDataURL(cb); | ||
} | ||
}); | ||
} | ||
//synchronous PNGStream | ||
exports.toPNGStream = function (text, WSpath, cb) { | ||
var out = fs.createWriteStream(WSpath); | ||
draw(text,function (error,canvas) { | ||
if(error) { | ||
cb(error,''); | ||
} else { | ||
stream = canvas.createPNGStream(); | ||
} | ||
stream.pipe(out); | ||
stream.on('end', function () { | ||
cb(error,''); | ||
}); | ||
stream.pipe(out); | ||
}); | ||
return out; | ||
} | ||
//returns bytes written to file | ||
exports.save = function(path,text,cb){ | ||
draw(text,function(error,canvas){ | ||
var fd,buf,fdAndBuf = function(){ | ||
fs.write(fd, buf, 0, buf.length, 0, function(err,written){ | ||
fs.write(fd, buf, 0, buf.length, 0, function(error,written){ | ||
fs.close(fd); | ||
cb(err,written); | ||
if(cb) cb(error,written); | ||
}); | ||
}; | ||
//run async calls at the same time ish so they can take advantage of the others idle time | ||
canvas.toBuffer(function(err, _buf){ | ||
if(err) return cb(err,0); | ||
//run non dependent async calls at the same time ish | ||
canvas.toBuffer(function(error, _buf){ | ||
if(error) return cb(error,0); | ||
@@ -47,3 +118,3 @@ buf = _buf | ||
fs.open(path, 'w', 0666, function(err,_fd){ | ||
if(err) return cb(err,0); | ||
if(error) return cb(error,0); | ||
fd = _fd | ||
@@ -54,2 +125,27 @@ if(buf) fdAndBuf(); | ||
}); | ||
}; | ||
// | ||
//this returns an array of points that have either a 0 or 1 value representing 0 for light and 1 for dark | ||
//these values include points in the white edge of the qrcode because that edge is actually part of the spec | ||
// | ||
exports.drawBitArray = function(text,cb){ | ||
var drawInstance = new QRCodeDraw(); | ||
drawInstance.drawBitArray(text,function(error,bits,width){ | ||
cb(error,bits,width); | ||
}); | ||
} | ||
exports.drawText = function(text,cb){ | ||
var drawInstance = new QRCodeDraw(); | ||
drawInstance.drawBitArray(text,function(error,bits,width){ | ||
if (!error) { | ||
var code = terminalRender.renderBits(bits,width); | ||
cb(error,code); | ||
} else { | ||
cb(error,null); | ||
} | ||
}); | ||
} | ||
@@ -5,3 +5,3 @@ node-qrcode | ||
This is a node js server side QR code / 2d barcode generator. | ||
This is a server side QR code / 2d barcode generator. | ||
it is an extension of "QRCode for JavaScript" which Kazuhiko Arase thankfully mit licensed | ||
@@ -12,2 +12,19 @@ | ||
examples | ||
-------- | ||
simple test | ||
var QRCode = require('qrcode'); | ||
QRCode.toDataURL('i am a pony!',function(err,url){ | ||
console.log(url); | ||
}); | ||
in your shell if you install globally | ||
qrcode "hi i want a qrcode" | ||
qr code capacity. | ||
----------------- | ||
this libary can encode a string up to lengths: | ||
@@ -29,2 +46,6 @@ 2953 in error correct level L | ||
to use qrcode from the command line to save qrcode images or generate ones you can view in your termial | ||
npm install -g qrcode | ||
api | ||
@@ -41,19 +62,12 @@ --- | ||
saves png to the path specified returns bytes written | ||
examples | ||
-------- | ||
simple test | ||
var sys = require('sys'); | ||
var QRCode = require('qrcode'); | ||
QRCode.drawText(text,cb) | ||
returns an ascii representation of the qrcode using unicode characters and ansi control codes for background control. | ||
QRCode.toDataURL('i am a pony!',function(err,url){ | ||
sys.print(url); | ||
}); | ||
QRCode.drawBitArray(text,cb(error,bits,width)); | ||
returns an array with each value being either 0 light or 1 dark and the width of each row. | ||
this is enough info to render a qrcode any way you want =) | ||
in bash | ||
node ./tests/url.js | ||
for server use: | ||
@@ -77,2 +91,2 @@ see tests/server.js | ||
The word "QR Code" is registered trademark of | ||
DENSO WAVE INCORPORATED | ||
DENSO WAVE INCORPORATED |
var express = require('express') | ||
,app = express.createServer() | ||
,fs = require('fs'); | ||
,fs = require('fs') | ||
,QRCode = require(__dirname+'/../qrcode') | ||
,canvasutil = require(__dirname+'/../../node-canvasutil/app.js') | ||
,Canvas = require('canvas') | ||
,Image = Canvas.Image; | ||
@@ -9,3 +13,3 @@ app.configure(function(){ | ||
app.use(app.router); | ||
app.use(express.static(__dirname + '/../lib')); | ||
app.use(express.static(__dirname + '/../')); | ||
}); | ||
@@ -19,3 +23,280 @@ | ||
var effectHandlers = {}; | ||
app.get('/generate', function(req, res){ | ||
var q = req.query||{},imageSrc; | ||
QRCode.QRCodeDraw.color.light = q.lightColor||'#ffffff'; | ||
QRCode.QRCodeDraw.color.dark = q.darkColor||'#000000'; | ||
QRCode.QRCodeDraw.scale = +(q.scale); | ||
if(isNaN(QRCode.QRCodeDraw.scale)) QRCode.QRCodeDraw.scale = 4; | ||
//NOTE when i set scale to 500 something seg faulted | ||
if(QRCode.QRCodeDraw.scale > 50) QRCode.QRCodeDraw.scale = 50; | ||
var effect = q.effect||'plain'; | ||
if(!effectHandlers[effect]){ | ||
effect = 'plain'; | ||
} | ||
effectHandlers[effect](q,function(error,canvas){ | ||
if(!error){ | ||
canvas.toBuffer(function(err, buf){ | ||
res.header('Content-Type','image/png'); | ||
res.send(buf); | ||
}); | ||
} else { | ||
var msg = error.message+"\n"+error.stack; | ||
res.header('Content-Type','text/plain'); | ||
res.send(msg); | ||
console.error(msg); | ||
} | ||
}); | ||
}); | ||
effectHandlers.node = function(args,cb){ | ||
args.src = __dirname+'/fixtures/node_logo.png'; | ||
this.image(args,cb); | ||
}; | ||
effectHandlers.npm = function(args,cb){ | ||
args.src = __dirname+'/fixtures/npm_logo.png'; | ||
this.image(args,cb); | ||
}; | ||
effectHandlers.bacon = function(args,cb){ | ||
args.src = __dirname+'/fixtures/bacon-love.png'; | ||
this.image(args,cb); | ||
}; | ||
effectHandlers.baconBikini = function(args,cb){ | ||
args.src = __dirname+'/fixtures/bacon-bikini.png'; | ||
this.image(args,cb); | ||
}; | ||
effectHandlers.rounded = function(args,cb){ | ||
QRCode.draw(args.text||'',function(err,canvas){ | ||
if(err) { | ||
cb(err,canvas); | ||
return; | ||
} | ||
var tpx = new canvasutil.PixelCore() | ||
,luma709Only = canvasutil.conversionLib.luma709Only | ||
,savedBuffer | ||
,up=[],down=[],left=[],right=[] | ||
,upPx,downPx,leftPx,rightPx,undefined,r,t,l,b,corner = 0; | ||
tpx.threshold = 100; | ||
tpx.iterate(canvas,function(px,i,len,pixels,w,h,pixelCore){ | ||
corner = 0; | ||
//is dark | ||
if(luma709Only(px.r,px.g,px.b) < pixelCore.threshold) { | ||
if(i-w > 0){ | ||
upPx = (i-w)*4; | ||
up[0] = pixels[upPx + 0]; | ||
up[1] = pixels[upPx + 1]; | ||
up[2] = pixels[upPx + 2]; | ||
//console.log('up',up); | ||
} | ||
if(i+w <= len) { | ||
downPx = (i+w)*4; | ||
down[0] = pixels[downPx + 0]; | ||
down[1] = pixels[downPx + 1]; | ||
down[2] = pixels[downPx + 2]; | ||
//console.log('down',down); | ||
} | ||
//have left pixel but no wrapping | ||
if(i%w != 0){ | ||
leftPx = (i-1)*4; | ||
left[0] = pixels[leftPx + 0]; | ||
left[1] = pixels[leftPx + 1]; | ||
left[2] = pixels[leftPx + 2]; | ||
//console.log('left',left); | ||
} | ||
if(i%w != w-1){ | ||
rightPx = (i+1)*4; | ||
right[0] = pixels[rightPx + 0]; | ||
right[1] = pixels[rightPx + 1]; | ||
right[2] = pixels[rightPx + 2]; | ||
//console.log('right',right); | ||
} | ||
r = rightPx?luma709Only(right[0],right[1],right[2]):0; | ||
t = upPx?luma709Only(up[0],up[1],up[2]):0; | ||
l = leftPx?luma709Only(left[0],left[1],left[2]):0; | ||
d = downPx?luma709Only(down[0],down[1],down[2]):0; | ||
if(l > pixelCore.threshold){//if left is light and i am dark | ||
if(t > pixelCore.threshold){//if top is light and i am dark | ||
corner = 1; | ||
pixels[rightPx + 4] = 100; | ||
} else if(d > pixelCore.threshold){//if bottom is light and i am dark | ||
pixels[rightPx + 4] = 100; | ||
corner = 1; | ||
} | ||
} else if(r > pixelCore.threshold){ | ||
if(t > pixelCore.threshold){//if top is light and i am dark | ||
corner = 1; | ||
} else if(d > pixelCore.threshold){//if bottom is light and i am dark | ||
corner = 1; | ||
} | ||
} | ||
if(corner) { | ||
px.a = 50; | ||
} | ||
} | ||
}); | ||
cb(false,canvas); | ||
}); | ||
}; | ||
effectHandlers.remoteImage = function(args,cb){ | ||
var src = args.src,domain,uri; | ||
if(!src) { | ||
cb(new Error('src required'),null); | ||
} else { | ||
if(src.indexof('://') != -1){ | ||
src = src.split('://').unshift(); | ||
var parts = src.split('/'); | ||
domain = parts.shift(); | ||
uri = parts.join('/'); | ||
} | ||
} | ||
if(!domain || !uri) { | ||
cb(new Error('missing domain or uri '+args.src)); | ||
return; | ||
} | ||
var options = { | ||
host: domain, | ||
port: 80, | ||
path: uri, | ||
method: 'GET' | ||
} | ||
,req = http.request(options, function(res) { | ||
if(res.statusCode < 200 || res.statusCode > 299){ | ||
cb(new Error('http '+res.statusCode+' response code'),null); | ||
return; | ||
} | ||
res.setEncoding('utf8'); | ||
var data = ''; | ||
res.on('data', function (chunk) { | ||
data += chunk; | ||
console.log('BODY: ' + chunk); | ||
}); | ||
res.on('complete',function(){ | ||
cb(false,data); | ||
}); | ||
res.on('error',function(error){ | ||
cb(error,null); | ||
cb = function(){}; | ||
}); | ||
}); | ||
req.end(); | ||
}; | ||
effectHandlers.image = function(args,cb){ | ||
src = args.src||''; | ||
var img = new Image(),convert = canvasutil.conversionLib; | ||
img.onload = function(){ | ||
QRCode.draw(args.text||'',function(err,canvas){ | ||
if(err) { | ||
cb(err,false); | ||
return; | ||
} | ||
var codeCtx = canvas.getContext('2d') | ||
, frame = codeCtx.getImageData(0,0,canvas.width,canvas.width) | ||
, tpx = new canvasutil.PixelCore() | ||
, baconCanvas = new Canvas(canvas.width,canvas.width) | ||
, ctx = baconCanvas.getContext('2d') | ||
,topThreshold = args.darkThreshold||25 | ||
,bottomThreshold = args.lightThreshold||75; | ||
tpx.threshold = 50; | ||
//scale image | ||
var w = canvas.width; | ||
var h = canvas.height; | ||
if(img.width>img.height) { | ||
w = w*(canvas.height/h) | ||
h = canvas.height; | ||
} else { | ||
h = h*(canvas.height/w) | ||
w = canvas.width; | ||
} | ||
ctx.drawImage(img,0,0,w,h); | ||
try{ | ||
tpx.iterate(baconCanvas,function(px,i,l,pixels,w,h,pixelCore){ | ||
var luma = (0.2125*px.r + 0.7154*px.g + 0.0721*px.b) | ||
, codeLuma = convert.luma709Only(frame.data[i*4],frame.data[i*4+1],frame.data[i*4+2]); | ||
if(codeLuma > pixelCore.threshold){ | ||
if(luma < bottomThreshold) { | ||
var yuv = convert.rgbToYuv(px.r,px.g,px.b),rgb; | ||
rgb = convert.yuvToRgb(bottomThreshold,yuv[1],yuv[2]); | ||
px.r = rgb[0]; | ||
px.g = rgb[1]; | ||
px.b = rgb[2]; | ||
px.a = 255; | ||
} | ||
} else { | ||
if(luma > topThreshold) { | ||
var yuv = convert.rgbToYuv(px.r,px.g,px.b),rgb; | ||
rgb = convert.yuvToRgb(topThreshold,yuv[1],yuv[2]); | ||
px.r = rgb[0]; | ||
px.g = rgb[1]; | ||
px.b = rgb[2]; | ||
} | ||
} | ||
}); | ||
} catch(e){ | ||
cb(err,false); | ||
} | ||
cb(false,baconCanvas); | ||
}); | ||
}; | ||
img.onerror = function(error){ | ||
error.message += ' ('+src+')'; | ||
cb(error,null); | ||
} | ||
img.src = src; | ||
}; | ||
effectHandlers.plain = function(args,cb){ | ||
var text = args.text||''; | ||
QRCode.draw(text||'',function(err,canvas){ | ||
cb(err,canvas); | ||
}); | ||
}; | ||
app.listen(3031); | ||
console.log('listening on 3031'); |
var QRCode = require(__dirname+'/../qrcode') | ||
, fs = require('fs') | ||
, sys = require('sys'); | ||
, util = require('util'); | ||
@@ -11,5 +11,5 @@ var path = './tmp.png'; | ||
} else { | ||
sys.print(written == (fs.statSync(path)||{}).size?"PASS: written should be to the correct file\n":"FAIL: file should be written size\n"); | ||
util.print(written == (fs.statSync(path)||{}).size?"PASS: written should be to the correct file\n":"FAIL: file should be written size\n"); | ||
fs.unlinkSync(path); | ||
} | ||
}); |
var QRCode = require(__dirname+'/../qrcode') | ||
, connect = require('connect'); | ||
, connect = require('express'); | ||
@@ -35,2 +35,2 @@ function testQRCode(req, res) { | ||
connect.createServer(testQRCode).listen(3030); | ||
console.log('test server started on port 3030'); | ||
console.log('test server started on port 3030'); |
// simple test | ||
var sys = require('sys'); | ||
var QRCode = require(__dirname+'/../qrcode'); | ||
var QRCode = require(__dirname+'/../qrcode.js'); | ||
var shouldBe = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIwAAACMCAYAAACuwEE+AAAABmJLR0QA/wD/AP+gvaeTAAAC+ElEQVR4nO3dSY7bQBBFQcvw/a8s77kw/VATpY7YdosSiI9kogbW6/1+v3/Bf/p9+gfwWQSGRGBIBIZEYEgEhkRgSASGRGBIBIZEYEgEhkRgSASGRGBIBIZEYEgEhkRgSP7MvuDr9Zp9yX+6Lkm+fv/okuV6vbv/P31/RqkwJAJDIjAk03uYq9nP0Nk9wN31as9SPf3+XKkwJAJDIjAky3uYq/qMrc/4Oi4z2qOc7kF2b41XYUgEhkRgSLb3MKvVuZy7HuDu87t7nNNUGBKBIREYkq/rYa5G51Zmr6/5dCoMicCQCAzJ9h7mdA8wuiZ3tdP3544KQyIwJAJDsryH2b0P52r2vqXZc1Wn70+lwpAIDInAkLx+2nlJs3uMH3b7VBgagSERGJLj62Fmv3+l/n/tUWav6R3dh7S7x1JhSASGRGBIlr/jbvY73mY/k0d/39N6nNVUGBKBIREYkuk9zOhe5avRcZKnzfU87fdUKgyJwJAIDMny9TCre5DT4zqr58KeRoUhERgSgSHZPpd0Z/Z6j9F9RKvf8zvb6h5JhSERGBKBITm+L2n2mtTZPcuo1Wtwrenl0QSGRGBIjo/DzH5mj/6eq91zTXefP02FIREYEoEh2b4eZvZczu71Nk9/Z95qKgyJwJAIDMnycZjRz8/uWer335k9F/X0nkaFIREYEoEhOb4eZrbZ4zKze6o7q9cwj1JhSASGRGBIHjcOU9V9QqPXv/t7fd/N7OuvpsKQCAyJwJAsP2tgdk8xe25o93lJq4e9Vl9fhSERGBKBIdl+XtLoepOqngUwe+5n9V7t3VQYEoEhERiS42c+zjb7DMfd5z2N/h7jMDyKwJAIDMnX9TCr3wtc7Z47sqaXRxEYEoEh2d7D7J4LOb3G+M6n9UwqDInAkAgMyfIe5vQ+mtE1u6vPoFx95qVxGI4SGBKBIfm698OwlgpDIjAkAkMiMCQCQyIwJAJDIjAkAkMiMCQCQyIwJAJDIjAkAkMiMCQCQyIwJAJD8hcDEI4hfsS5IwAAAABJRU5ErkJggg=="; | ||
var shouldBe = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIwAAACMCAIAAAAhotZpAAAABmJLR0QA/wD/AP+gvaeTAAAC0UlEQVR4nO2dQW7EIAwAm6r//3J6qLSiB1Qj24TpzhxXCdlo5FiAgeu+7w85m8+n/4D8jZIAKAmAkgAoCYCSACgJgJIAKAmAkgAoCYCSACgJgJIAKAmAkgAoCYCSACgJwFfm5uu6qv7Hi7HmYmx/tRYjcu/smu73WsVIAqAkAEoCkMpJI5lvbiYHzO6N5KEIT73XiJEEQEkAlASgLCeNRL7FkW99pM+0mnu6c0xHbb2RBEBJAJQEoCUnVREZW5vlgNn1HbmqGyMJgJIAKAnA0TlpZHUcLDMXdRpGEgAlAVASgJac1J0DVmsWup/bjZEEQEkAlASgLCd11KqNZOrxMmOA3e8VwUgCoCQASgJwEce1MrmE+L5GEgAlAVASgPaclFknFLkmknsy9XKr93bkQiMJgJIAKAlA2ZrZzJrTzPc6k3sy9Xg7x/SMJABKAqAkAKmctFqHPbLav9k55nba+J6RBEBJAJQEoGzsrirHdPexqsYSd2IkAVASACUBSOWkqv3oRjLzSVW1eZH/E6EqtxlJAJQEQEkAttY4jHTUcGfmeKrqFKxxeFOUBEBJAFpqHEYy3/HVZ60+N9O+NQ7yCyUBUBKAlvmkzNhax7zUU+ttqzCSACgJgJIAbD0/qXuNUdVaokj7O/OTkQRASQCUBODofRwyfaZM/sv8n9n1zif9c5QEQEkAjj5ntmot7ez3yNqpTDtVGEkAlARASQAw58xW7bPQUR/R3Y6RBEBJAJQE4OhzZmfXz/YEyoy/VdWRd2AkAVASACUBOPpMv9X5pO7991afZT/pjVASACUBODonrY6zndDX6chPRhIAJQFQEgDMObPd9RQdz7Wf9EYoCYCSAJTtd1dF1b55kTYz65l2niVoJAFQEgAlATh6fZL8YCQBUBIAJQFQEgAlAVASACUBUBIAJQFQEgAlAVASACUBUBIAJQFQEgAlAVASACUB+AZ8GY0T5C7RkwAAAABJRU5ErkJggg=="; | ||
QRCode.toDataURL('i am a pony!',function(err,url){ | ||
sys.print(url == shouldBe?"PASS: url is what it should be !\n":"FAIL: oh no something broke the qr generation!\n"); | ||
}); | ||
if(err) console.log(err); | ||
console.log(url == shouldBe?"PASS: url is what it should be !\n":"FAIL: oh no something broke the qr generation!\n"); | ||
}); |
Sorry, the diff of this file is not supported yet
Floating dependency
QualityPackage has a dependency with a floating version range. This can cause issues if the dependency publishes a new major version.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
Non-existent author
Supply chain riskThe package was published by an npm account that no longer exists.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
878256
34
5436
88
0
2
3
2
1
25
3
+ Addedcolors@*
+ Addedcolors@1.4.0(transitive)