Generating images in Workers

I'm trying to generate an image in a Worker, and then store the image in an R2 bucket.

My current approach (example code included below) was to:

  1. Use the Canvas API to generate the image,
  2. Use HTMLCanvasElement.toDataURL() and dataURItoBlob() to convert the image to a Blob, and then
  3. Put the Blob in an R2 bucket.
However, as document is not defined and the Canvas API is not supported (https://github.com/cloudflare/workerd/discussions/212), this approach does not work in Workers.

Are there any other approaches I could try to achieve this in Workers?

interface Env {
  BUCKET: R2Bucket;
}

export const onRequest: PagesFunction<Env> = async (context) => {
  const canvas = document.createElement("canvas");

  canvas.width = 200;
  canvas.height = 200;

  const ctx = canvas.getContext("2d");

  if (ctx === null) {
    return new Response(null, { status: 500 });
  }

  ctx.fillStyle = "red";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  ctx.textAlign = "center";
  ctx.textBaseline = "middle";
  ctx.fillText("text", canvas.width / 2, canvas.width / 2);

  const dataUrl = canvas.toDataURL("image/jpeg");
  const blobData = dataURItoBlob(dataUrl);

  await context.env.BUCKET.put("my-image.jpeg", blobData);

  return new Response(null, { status: 200 });
};

function dataURItoBlob(dataURI: string) {
  const binary = Buffer.from(dataURI.split(",")[1], "base64").toString();
  const array = [];

  for (let i = 0; i < binary.length; i++) {
    array.push(binary.charCodeAt(i));
  }

  return new Blob([new Uint8Array(array)], { type: "image/jpeg" });
}
Was this page helpful?