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.