(updated ) by

Fetch images into Uint8Array/UInt8Buffer for WASM web applications

When using WASM, we may want to load an image into WASM flow. One way to get an image into WASM is getting a Uint8Array version. In Rust, we can represent this as a slice &[u8]. We can then use this to load the image using the image crate for example.

To do this in the browser we have 2 main options.

  • Load an image from the network via the fetch() API in the browser.
  • Load an image via a file upload.

The general flow is to go form the image, to Blob, to ArrayBuffer to Uint8Array in JavaScript.

Load from fetch()

// image is URL to image to load
// image = "./image.jpg";
const loadImage = async (image) => {
  return fetch(image)
    .then((resp) => resp.blob())
    .then((blob) => new Uint8Array(blob.arrayBuffer()));
};

async function readImage() {
  const uint8Image = await loadImage("./image.jpg");

  // use uint8Image in your WASM application, like `&[u8]` in rust
}

Load from file upload

We let users “upload” images into their browser and then process them in the browser


// We can run this inside a worker which can prevent blocking of the UI
async function readFile(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = function (e) {
      const buffer = new Uint8Array(e.target.result);
      resolve(buffer);
    };
    reader.readAsArrayBuffer(file);
  });
}

HTML we have some input file element.

<input type="file" id="image_file" />

Usage

We can then connect the file input, read the file into Uint8Array.

// Get the element for the #image_file element
const imageFileInput = document.querySelector("#image_file");

// We are checking the onChange event
// but you could check a form submit or other way instead of loading it when it changes.
imageFileInput.addEventListener("change", async (evt) => {
    e.preventDefault();
    const files = evt.target.files;

    // Images will be represented as a FileList so we can iterate through it.
    // You could just access the first element (`files.item(0)`) and check it instead.
    for (let i = 0; i < files.length; i++) {
        const file = files.item(i);
        const uint8Image = await readFile(file);

        // use uint8Image in your WASM application, like `&[u8]` in rust
    }
});

Hope this will be helpful at how to load an image in the browser to feed into your WASM web application.