Image Processing in Browser


ImageMagick

One of the oldest, free and opensource tool to manipulate images. This cross platform library can now work natively in the browser thanks to web assembly github.com/KnicKnic/WASM-ImageMagick. In this post I’ll explore the library and show how easy it is to actually incorporate in a ReactJS application

npm installation

Post installation it is necessary to copy the magick.wasm and magick.js to static/js location.

npm install --save wasm-imagemagick
cp node_modules/wasm-imagemagick/dist/magick.wasm public/static/js
cp node_modules/wasm-imagemagick/dist/magick.js public/static/js

API

import { call } from "wasm-imagemagick";

The most low level way to deal with imagemagick wasm is the call API. It takes an array of images and a sequence of arguments to perform the operation on image(s) just like the command line utility.

JavaScript File

File type object in JavaScript represents a blob which is obtained mostly from the <input> element’s filelist. It can be created manually as well to represent any supported file type and fill the data with arbitrary bytes.

var file = new File(["\0"], "file.png", { type: "image/png" });
file.arrayBuffer().then((v) => console.log(new Uint8Array(v)));
// Output: [0]

While working with ImageMagick you’ll need a file object either obtained from user upload or fetching it from a remote location.

Executing Command

With the call API it’s almost similar to running ImageMagick on CLI. For example if you want to run the command.

magick convert input.png -rotate 90 -resize 200% out.png

first prepare the input image

// imageFile instanceof File -> true
const content = new Uint8Array(await imageFile.arrayBuffer());
const image = { name: "input.png", content };

Then write out the command as a sequence of arguments in an array.

const command = [
  "convert",
  "input.png",
  "-rotate",
  "90",
  "-resize",
  "200%",
  "out.png",
];

and execute the API. It will return a result object with an array of processed image files.

const result = await call([image], command);
const url = URL.createObjectURL(
  new Blob([result.outputFiles[0].buffer], { type: "image/png" })
);

The extracted URL can be assigned to an <img> element to display the output image in the browser.

Example

The sample implementation with a bit more options can be found here