Using node-canvas how to render personalized image (back end)

I have a function called dynamic_img.js with this code:

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

exports.handler = async (event, context) => {

    const { createCanvas, loadImage } = require('canvas')
    const canvas = createCanvas(200, 200)
    const ctx = canvas.getContext('2d')

    // Write "Awesome!"
    ctx.font = '40px Impact'
    ctx.rotate(0.1)
    ctx.fillText('Awesome!', 50, 100)

    // Draw line under text
    var text = ctx.measureText('Awesome!')
    ctx.strokeStyle = 'rgba(0,0,0,0.5)'
    ctx.beginPath()
    ctx.lineTo(50, 102)
    ctx.lineTo(50 + text.width, 102)
    ctx.stroke()

    // Draw cat with lime helmet
    const url = "https://www.twnel.com/wp-content/uploads/2022/12/2022-12-07_12h11_44.png"
    await loadImage(url).then((image) => {
        ctx.drawImage(image, 50, 0, 70, 70)
    })

    console.log('<img src="' + canvas.toDataURL() + '" />')
    // canvas.createPNGStream().pipe(__dirname + '/test.png')

    return {
        statusCode: 200,
        body: canvas.toDataURL()
    }
}

I have not deployed this yet. I’m still working on my local machine.

This code returns this on this path: localhost:8888/api/dynamic_img/

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAABmJLR0QA/wD/AP+gvaeTAAAgAElEQVR4nOy9WaylW37Y9Vtrfeub97zPPqfOqbq37ty3Z6fdJm6nQyCQATsBWXSEiMgTEjwgHiyRgEBCFkiRIggBg4wSCQn8gBQLBRKiyIQwxNjx0O12D7fvWLduTfvMe/7mNfCwSxGvJtW6nMv5vVQ97rPX+Z21/mv9B7jllltuueWWW2655ZZbbrnlD4r4tD/ALZ9Ngk/7A7wIvvXPfO1fAP67IFDzyezOfHb3/vxs/vis3q7nw/Hh3MH84ux8PnktOvulX/ ...

I want o be able to return an image at a custom path, such as localhost:8888/api/dynamic_img/test.png

I think I need to use canvas.createPNGStream().pipe(__dirname + '/test.png'), but I don’t know where to put it.

Any suggestions?

On the other hand, when I do a small change and I save my work it doesn’t work anymore.
I get this error and I need to run npm run netlify again

Error: Module did not self-register: ‘\?\C:\Users\Gilbert\netify\serverless-functions-starter\node_modules\canvas\build\Release\canvas.node’.
Object.Module._extensions…node (node:internal/modules/cjs/loader:1183:18)
Module.load (node:internal/modules/cjs/loader:981:32)
Function.Module._load (node:internal/modules/cjs/loader:822:12)
Module.require (node:internal/modules/cjs/loader:1005:19)
require (node:internal/modules/cjs/helpers:102:18)
Object. (C:\Users\Gilbert\netify\serverless-functions-starter\node_modules\canvas\lib\bindings.js:3:18)
Module._compile (node:internal/modules/cjs/loader:1101:14)
Object.Module._extensions…js (node:internal/modules/cjs/loader:1153:10)
Module.load (node:internal/modules/cjs/loader:981:32)
Function.Module._load (node:internal/modules/cjs/loader:822:12)

I tried npm install -g netlify-cli as suggested somewhere, but it didn’t solve the issue

I discovered that the backend code was fine. I just needed to call the API that generates the dynamic image from the front-end and render the image.

I created a redirect to show a URL with a png extension. It works fine, but it shows the original URL first and the it goes the alias (it takes an instant).

It would be better if it doesn’t show the original path. Any suggestions?

On the other hand, is there a way to create redirects programmatically?
Right now I hard coded the one I’m using in the netlify.toml file as:

[[redirects]]
    from = '/examples/image1.png'
    to = '/examples/test-img/index.html'
    status = 301

You seem to be returning a base64 string. I don’t think browsers can automatically render that as an image if it’s sent as a text response. I’d recommend sending a HTML file as a response:

That way, the browser can then display the image in the browser.

However, you won’t be able to send a HTML response for a PNG request. So, that brings me to my main question:

What is it that you’re exactly planning to use this API for? Are you planning to generate images on demand that should load in a browser, or are you planning to consume this image in your frontend? If it’s the former, you would have to use the HTML method. If it’s the latter, you can get away with sending a base64 string and if you set that as a image’s source dynamically, browser would display that as an image.

Hi. Yes, I want to generate images on demand that should load on the browser.

The ideas is that and image can get URL parameters such as https://site.com/image1.png?name=Gilbert

This should generate the image created server side but using the name Gilbert as a variable.

My current problem is that I don’t know how to make that the site will show the image at that URL https://site.com/image1.png

Am I clear?

Hey @Gilbert,

Returning an image should not be a problem. Did you try something like:

return {
  body: ''base64-string-of-the-image",
  headers: {
    'content-type': 'image/png'
  },
  isBase64Encoded: true,
  statusCode: 200
}

If this doesn’t work, could you please share a repo as an example so we can see what is happening?