Draw discord avatar image on canvas from URL (Node.js)

Viewed 1091

I am trying to draw the avatar image from a discord user onto a node.js canvas. According to the docs, I should just be able to put the url as the src like this:

var img = new Canvas.Image;
img.onload = () => context.drawImage(img, x, y, w, h);
img.onerror = err => console.log(err);
img.src = url;

This doesn't work at all. So according to other sources, I have to fetch the image with an http client myself. Using Axios I get:

function requestImageFromURL(url, callback){
    Axios.get(url)
    .then(response => {
        callback(response.data);
    })
    .catch(err => {})
    .finally(() => {});
}

function drawImageFromURL(url, x, y, width, height){
    requestImageFromURL(url, function(buffer){
        var img = new Canvas.Image;
        img.onload = () => context.drawImage(img, x, y, width, height);
        img.onerror = err => console.log(err);
        img.src = buffer;
    });
}

but this throws some really strange errors like Error: EINVAL, Invalid argument '�PNG → '. So I kinda get the data, but canvas processes them not quite right? Or is there more pre-processing necessary on the data I receive?

3 Answers

Calling class constructors should end with (). But in that code there's no (), just Canvas.Image. Try the first code using () and it should work.

Canvas.Image is a constructor. Therefore you'll have to use () so that you can manipulate it.

Should look something like this

function drawImageFromURL(url, x, y, width, height){
    requestImageFromURL(url, function(buffer){
        var img = new Canvas.Image()
        img.onload = () => context.drawImage(img, x, y, width, height);
        img.onerror = err => console.log(err);
        img.src = buffer;
    });
}

First step: Create background image, where your avatar will be drawn.

That's a part of my code which is sending message, when member join server, so don't mind member parameter.

photo.png stands for my background image.


const avatar = await Canvas.loadImage(member.user.displayAvatarURL({ format: 'jpg' }));
        context.drawImage(avatar, 40, 13, 120, 120);
        const attachment = new MessageAttachment(canvas.toBuffer(), 'photo.png');
        channel.send(`Welcome, ${member}!`, attachment);
Related