Node.js - 如何将文件中的图像数据添加到画布中

21
以下代码旨在读取图像文件,然后使用Canvas模块将文件数据添加到画布中。 当我运行这段代码时,我收到错误消息“Image未定义”。我尝试从一个导入的模块中初始化图像对象吗?
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/');
2个回答

57

如果我理解有误,请原谅,但是看起来你找到了这段代码并尝试在不了解背后发生的事情的情况下使用它。即使你修复了“未定义图片(Image is not defined)”错误,还有很多其他问题。

我已经在本帖的最后放置了修复好的代码,但我建议您更深入地思考问题的代码:

  • 什么是Image?它从哪里来?您已导入httpfsCanvas,所以这些东西显然是定义过的。然而,Image没有在任何地方定义过,也不是内置的。

    事实证明,Image来自于node-canvas模块,您使用Canvas = require('canvas')导入了此模块。这意味着Image可以作为Canvas.Image使用。

    重要的是要理解这是由您设置的导入导致的。您也可以轻松地使用abc = require('canvas',然后Image将可用作abc.Image

  • ctx是什么?它从哪里来?

    同样,这是另一个变量,没有在任何地方定义。不像Image,它不可用作Canvas.ctx。它只是一个随意的变量名称,目前不对应任何内容,因此尝试在其上调用drawImage将引发异常。

  • canvas(小写)呢?那是什么?

    您正在使用canvas.toDataURL,但是没有任何名为canvas的变量。您希望此代码片段执行什么操作?现在它只会抛出异常,说canvas未定义。

我建议您更仔细地阅读文档,并更深入地研究将任何示例代码复制到自己的应用程序中的方法。


这里是已修复的代码,并添加了一些注释以解释我所做的更改。我通过快速查看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/');

谢谢Rohan。我实际上已经忘记了定义ctx和canvas变量,但是由于我还没有处理这些错误,所以从未注意到。你给出的链接就是我从中获取示例的地方,因为在该页面上,作者使用了new Image而不是Canvas.Image - mesh
2
是的,文档有点懒。在node-canvas模块的代码中,仅仅使用Image就可以了,因为它在源代码(lib/canvas.js)中定义了Image = canvas.Image。然而,除非你做出相同的定义,否则它在你自己的代码中不起作用。 - Rohan Singh
很遗憾,那个糟糕的文档仍然存在。我们该如何督促他们解决这个问题? - Dan
我提交了一个更改的拉取请求:https://github.com/LearnBoost/node-canvas/pull/418 - Rohan Singh
4
@RohanSingh,我们不需要等待 ImageObj.onload 吗? - Rayon
1
非常慷慨的帖子! - David

5

node-canvas现在有一个辅助函数loadImage,它返回一个Promise,解析为已加载的Image对象。这可以避免像接受的答案中那样使用onload处理程序。

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/');

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接