Image processing in Cloudflare Workers

Learn how to use Cloudflare Workers at the edge for efficient image processing and optimization, boosting performance with serverless solutions.

I was looking for an alternative to Sharp since it does not work on Cloudflare Workers as it uses Node.js APIs, which are not yet supported in Cloudflare's workerd runtime. Then I came across Photon, a high-performance Rust image processing library, which compiles to WebAssembly. Photon offers a variety of functions for resizing, transforming, watermarking, and more. There is official npm package available for it, but it was not working with Wrangler when I tried it last time, and also it was missing some new functions.

Therefore, I forked the repository and compiled it to WebAssembly using wasm-pack to make it compatible with Cloudflare Workers. I have also published it as npm package @cf-wasm/photon.

Implementation

You can use this package in an existing workers project or create a new project by running:

npm create cloudflare@latest -- cf-workers-photon
cd cf-workers-photon

Then install @cf-wasm/photon by running:

npm i @cf-wasm/photon

Now you can import functions exported by this package and use them in your code.

Here is an example which uses resize function to resize an image and respond with a WebP format.

import { PhotonImage, SamplingFilter, resize } from "@cf-wasm/photon";

export default {
  async fetch() {
    // url of image to fetch
    const imageUrl = "https://avatars.githubusercontent.com/u/314135";

    // fetch image and get the Uint8Array instance
    const inputBytes = await fetch(imageUrl)
      .then((res) => res.arrayBuffer())
      .then((buffer) => new Uint8Array(buffer));

    // create a PhotonImage instance
    const inputImage = PhotonImage.new_from_byteslice(inputBytes);

    // resize image using photon
    const outputImage = resize(
      inputImage,
      inputImage.get_width() * 0.5,
      inputImage.get_height() * 0.5,
      SamplingFilter.Nearest
    );

    // get webp bytes
    const outputBytes = outputImage.get_bytes_webp();

    // for other formats
    // png  : outputImage.get_bytes();
    // jpeg : outputImage.get_bytes_jpeg(quality);

    // call free() method to free memory
    inputImage.free();
    outputImage.free();

    // return the Response instance
    return new Response(outputBytes, {
      headers: {
        "Content-Type": "image/webp"
      }
    });
  }
} satisfies ExportedHandler;

Handling Large Images

It's important to be mindful of worker memory limits (typically 128MB) when handling large images. Check this issue (#48) for more information.

Conclusion

By leveraging Cloudflare Workers and the power of WebAssembly with Photon, you can efficiently process images at the edge, optimizing them on the fly and serving them in various formats like WebP, JPEG, or PNG. This provides a scalable, fast, and cost-effective solution for image manipulation, and the example above demonstrates how easy it is to implement this powerful functionality in your serverless projects.

Whether you're building an image-heavy site or need dynamic resizing for a diverse set of devices, Cloudflare Workers combined with Photon can help you achieve high performance and low latency with minimal overhead.

Copyright (c):
fineshopdesign.com

About the author

Deø Kumar
Lost in the echoes of another realm.

Post a Comment

To avoid SPAM, all comments will be moderated before being displayed.