Implement asynchronously loading Rasters from disk and remote locations for Node.js

Closes #328.
This commit is contained in:
Jürg Lehni 2013-12-03 23:07:54 +01:00
parent c423fcda39
commit fc02c58ddb
5 changed files with 66 additions and 17 deletions

View file

@ -0,0 +1,25 @@
var paper = require('paper');
var fs = require('fs');
var canvas = new paper.Canvas(800, 600);
paper.setup(canvas);
var url = 'http://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png';
var raster = new paper.Raster(url);
raster.position = paper.view.center;
raster.onLoad = function() {
console.log('The image has loaded:' + raster.bounds);
// Saving the canvas to a file.
out = fs.createWriteStream(__dirname + '/canvas.png');
stream = canvas.pngStream();
stream.on('data', function(chunk){
out.write(chunk);
});
stream.on('end', function() {
console.log('saved png');
});
};

1
node_modules/.gitignore generated vendored
View file

@ -1,6 +1,7 @@
.bin .bin
canvas canvas
jsdom jsdom
request
uglify-js uglify-js
prepro prepro
grunt* grunt*

View file

@ -21,7 +21,8 @@
}, },
"dependencies": { "dependencies": {
"canvas": ">= 0.7.0", "canvas": ">= 0.7.0",
"jsdom": ">= 0.6.0" "jsdom": ">= 0.6.0",
"request": "~2.27.0"
}, },
"devDependencies": { "devDependencies": {
"uglify-js": "~2.3.6", "uglify-js": "~2.3.6",

View file

@ -18,11 +18,10 @@
var jsdom = require('jsdom'), var jsdom = require('jsdom'),
domToHtml = require('jsdom/lib/jsdom/browser/domtohtml').domToHtml, domToHtml = require('jsdom/lib/jsdom/browser/domtohtml').domToHtml,
// Node Canvas library: https://github.com/learnboost/node-canvas // Node Canvas library: https://github.com/learnboost/node-canvas
Canvas = require('canvas'); Canvas = require('canvas'),
// Expose global browser variables and create a document and a window using
// Expose global browser variables and create a document and a window using // jsdom, e.g. for import/exportSVG()
// jsdom, e.g. for import/exportSVG() document = jsdom.jsdom('<html><body></body></html>'),
var document = jsdom.jsdom('<html><body></body></html>'),
window = document.createWindow(), window = document.createWindow(),
navigator = window.navigator, navigator = window.navigator,
HTMLCanvasElement = Canvas, HTMLCanvasElement = Canvas,

View file

@ -291,20 +291,23 @@ var Raster = Item.extend(/** @lends Raster# */{
}, },
setSource: function(src) { setSource: function(src) {
/*#*/ if (__options.environment == 'browser') {
var that = this, var that = this,
// src can be an URL or a DOM ID to load the image from image;
image = document.getElementById(src) || new Image();
function loaded() { function loaded() {
var view = that._project.view; var view = that._project.view;
if (view) if (view)
paper = view._scope; paper = view._scope;
that.setImage(image);
that.fire('load'); that.fire('load');
if (view) if (view)
view.draw(true); view.draw(true);
} }
/*#*/ if (__options.environment == 'browser') {
// src can be an URL or a DOM ID to load the image from
image = document.getElementById(src) || new Image();
// IE has naturalWidth / Height defined, but width / height set to 0 // IE has naturalWidth / Height defined, but width / height set to 0
// when the image is invisible in the document. // when the image is invisible in the document.
if (image.naturalWidth && image.naturalHeight) { if (image.naturalWidth && image.naturalHeight) {
@ -314,10 +317,7 @@ var Raster = Item.extend(/** @lends Raster# */{
} else { } else {
// Trigger the onLoad event on the image once it's loaded // Trigger the onLoad event on the image once it's loaded
DomEvent.add(image, { DomEvent.add(image, {
load: function() { load: loaded
that.setImage(image);
loaded();
}
}); });
// A new image created above? Set the source now. // A new image created above? Set the source now.
if (!image.src) if (!image.src)
@ -325,17 +325,37 @@ var Raster = Item.extend(/** @lends Raster# */{
} }
this.setImage(image); this.setImage(image);
/*#*/ } else if (__options.environment == 'node') { /*#*/ } else if (__options.environment == 'node') {
var image = new Image(); image = new Image();
// If we're running on the server and it's a string, // If we're running on the server and it's a string,
// check if it is a data URL // check if it is a data URL
if (/^data:/.test(src)) { if (/^data:/.test(src)) {
// Preserve the data in this._data since canvas-node eats it. // Preserve the data in this._data since canvas-node eats it.
// TODO: Fix canvas-node instead // TODO: Fix canvas-node instead
image.src = this._data = src; image.src = this._data = src;
// Fire load event delayed, so behavior is the same as when it's
// actually loaded and we give the code time to install event
setTimeout(loaded, 0);
} else if (/^https?:\/\//.test(src)) {
// Load it from remote location:
require('request').get({
url: src,
encoding: null // So the response data is a Buffer
}, function (err, response, data) {
if (err)
throw err;
if (response.statusCode == 200) {
image.src = this._data = data;
loaded();
}
});
} else { } else {
// Load it from disk: // Load it from disk:
// TODO: load images async, calling setImage once loaded as above. require('fs').readFile(src, function (err, data) {
image.src = fs.readFileSync(src); if (err)
throw err;
image.src = this._data = data;
loaded();
});
} }
this.setImage(image); this.setImage(image);
/*#*/ } // __options.environment == 'node' /*#*/ } // __options.environment == 'node'
@ -393,8 +413,11 @@ var Raster = Item.extend(/** @lends Raster# */{
// See if the linked image is base64 encoded already, if so reuse it, // See if the linked image is base64 encoded already, if so reuse it,
// otherwise try using canvas.toDataURL() // otherwise try using canvas.toDataURL()
/*#*/ if (__options.environment == 'node') { /*#*/ if (__options.environment == 'node') {
if (this._data) if (this._data) {
if (this._data instanceof Buffer)
this._data = this._data.toString('base64');
return this._data; return this._data;
}
/*#*/ } else { /*#*/ } else {
var src = this._image && this._image.src; var src = this._image && this._image.src;
if (/^data:/.test(src)) if (/^data:/.test(src))