Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

nodejs - How to add image data from file into canvas

The following code is supposed to read an image file and then add the file data into a canvas with the help of the Canvas module.

When I run this code I receive the error message Image is not defined. Is the image object that I'm trying to initialise from a module that I simply import?

var http = require('http'), fs = require('fs'), 
Canvas = require('canvas');

http.createServer(function (req, res) {
    fs.readFile(__dirname + '/image.jpg', function(err, data) {
        if (err) throw err;
        img = new Image();
        img.src = data;
        ctx.drawImage(img, 0, 0, img.width / 4, img.height / 4);

        res.write('<html><body>');
        res.write('<img src="' + canvas.toDataURL() + '" />');
        res.write('</body></html>');
        res.end();
    });

}).listen(8124, "127.0.0.1");
console.log('Server running at http://127.0.0.1:8124/');
like image 360
mesh Avatar asked Mar 03 '12 17:03

mesh


2 Answers

I apologize if I'm wrong here, but it looks like you've found this code somewhere and tried to use it without actually understanding what's happening under the covers. Even if you were to fix the Image is not defined error, there are many others.

I have the fixed code at the end of this post, but I'd recommend thinking more deeply about these issues in the code from your question:

  • What is Image? Where does it come from? You've imported http, fs, and Canvas, so those things are obviously defined. However, Image hase not been defined anywhere and it is not a built-in.

    As it turns out, Image is from the node-canvas module, which you've imported with Canvas = require('canvas'). This means that Image is available as Canvas.Image.

    It's important to understand that this is because of the imports you've setup. You could just have easily have done abc = require('canvas'), and then Image would be available as abc.Image.

  • What is ctx? Where is that coming from?

    Again, this is another variable that just hasn't been defined anywhere. Unlike Image, it isn't available as Canvas.ctx. It's just a random variable name that doesn't correspond to anything at this point, so trying to call drawImage on it is going to throw an exception.

  • What about canvas (lowercase)? What is that?

    You are using canvas.toDataURL, but there is no variable called canvas anywhere. What are you expecting this piece of code to do? Right now it's just going to throw an exception saying that canvas is undefined.

I'd recommend reading documentation more closely and looking more closely at any example code you copy into your own applications in the future.


Here is the fixed code, with some comments to explain my changes. I figured this out by taking a quick look at the documentation at https://github.com/learnboost/node-canvas.

var http = require('http'), fs = require('fs'), 
Canvas = require('canvas');

http.createServer(function (req, res) {
    fs.readFile(__dirname + '/image.jpg', function(err, data) {
        if (err) throw err;
        var img = new Canvas.Image; // Create a new Image
        img.src = data;

        // Initialiaze a new Canvas with the same dimensions
        // as the image, and get a 2D drawing context for it.
        var canvas = new Canvas(img.width, img.height);
        var ctx = canvas.getContext('2d');
        ctx.drawImage(img, 0, 0, img.width / 4, img.height / 4);

        res.write('<html><body>');
        res.write('<img src="' + canvas.toDataURL() + '" />');
        res.write('</body></html>');
        res.end();
    });

}).listen(8124, "127.0.0.1");
console.log('Server running at http://127.0.0.1:8124/');
like image 107
Rohan Singh Avatar answered Nov 05 '22 00:11

Rohan Singh


node-canvas now has a helper function, loadImage, that returns a Promise resolving to a loaded Image object. This prevents having to mess around with onload handlers like in the accepted answer.

const http = require('http'); 
const fs = require('fs');
const Canvas = require('canvas');

http.createServer(function (req, res) {
    fs.readFile(__dirname + '/image.jpg', async function(err, data) {
        if (err) throw err;
        const img = await Canvas.loadImage(data);
        const canvas = new Canvas(img.width, img.height);
        const ctx = canvas.getContext('2d');
        ctx.drawImage(img, 0, 0, img.width / 4, img.height / 4);

        res.write('<html><body>');
        res.write('<img src="' + canvas.toDataURL() + '" />');
        res.write('</body></html>');
        res.end();
    });

}).listen(8124, "127.0.0.1");
console.log('Server running at http://127.0.0.1:8124/');
like image 42
aendra Avatar answered Nov 05 '22 01:11

aendra