diff --git a/lib/buffer.js b/lib/buffer.js new file mode 100644 index 0000000..7c3b44b --- /dev/null +++ b/lib/buffer.js @@ -0,0 +1,22 @@ + +/*! + * Canvas - Buffer + * Copyright (c) 2010 LearnBoost + * MIT Licensed + */ + +/** + * Concatenate `this` Buffer with `buf`. + * + * @param {Buffer} buf + * @return {Buffer} + * @api public + */ + +Buffer.prototype.concat = function(buf) { + var len = this.length + , tmp = new Buffer(len + buf.length); + this.copy(tmp, 0, 0); + buf.copy(tmp, len, 0); + return tmp; +}; \ No newline at end of file diff --git a/lib/canvas.js b/lib/canvas.js index 927e95c..8b86c1c 100644 --- a/lib/canvas.js +++ b/lib/canvas.js @@ -41,6 +41,12 @@ exports.cairoVersion = cairoVersion; var cache = {}; +/** + * Buffer extensions. + */ + +require('./buffer'); + /** * Return a function used to normalize an RGBA color `prop`. * @@ -168,6 +174,35 @@ Canvas.prototype.createPNGStream = function(){ return new PNGStream(this); }; +Canvas.prototype.toBuffer = function(){ + var buf; + this.streamPNG(function(err, chunk, len){ + if (err) throw err; + if (len) { + buf = buf + ? buf.concat(chunk) + : chunk; + } + }); + return buf; +}; + +/** + * Return a data url. + * + * @param {String} type + * @return {String} + * @api public + */ + +Canvas.prototype.toDataURL = function(type){ + // TODO: jpeg / svg + type = type || 'image/png'; + if ('image/png' != type) throw new Error('currently only image/png is supported'); + return 'data:' + type + + ';base64,' + this.toBuffer().toString('base64'); +}; + /** * Add `color` stop at the given `offset`. * diff --git a/test/canvas.test.js b/test/canvas.test.js index 7fdc971..e4f4b5f 100644 --- a/test/canvas.test.js +++ b/test/canvas.test.js @@ -550,6 +550,28 @@ module.exports = { assert.ok(!ctx.isPointInPath(50,120)); }, + 'test #toDataURL()': function(assert){ + var canvas = new Canvas(200, 200) + , ctx = canvas.getContext('2d'); + + ctx.fillRect(0,0,100,100); + ctx.fillStyle = 'red'; + ctx.fillRect(100,0,100,100); + + var str = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYA' + + 'AACtWK6eAAAABmJLR0QA/wD/AP+gvaeTAAABbElEQVR4nO3TQQ0AMQwDwVz5c+4x2' + + 'G/zmEFgydpvZu6whjN2Oa8HwGYCgSAQCAKBIBAIAoEgEAgCgSAQCAKBIBAIAoEgEA' + + 'gCgSAQCAKBIBAIAoEgEAgCgSAQCAKBIBAIAoEgEAgCgSAQCAKBIBAIAoEgEAgCgSA' + + 'QCAKBIBAIAoEgEAgCgSAQCAKBIBAIAoEgEAgCgSAQCAKBIBAIAoEgEAgCgSAQCAKBI' + + 'BAIAoEgEAgCgSAQCAKBIBAIAoEgEAgCgSAQCAKBIBAIAoEgEAgCgSAQCAKBIBAIAoEg' + + 'EAgCgSAQCAKBIBAIAoEgEAgCgSAQCAKBIBAIAoEgEAgCgSAQCAKBIBAIAoEgEAgCgSAQ' + + 'CAKBIBAIAoEgEAgCgSAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAhX5bnALGvZc/ggA' + + 'AAABJRU5ErkJggg=='; + + assert.equal(str, canvas.toDataURL(), 'Canvas#toDataURL() failed'); + }, + 'test PNGStream': function(assert, beforeExit){ var canvas = new Canvas(320, 320) , ctx = canvas.getContext('2d')