React + Rust + Wasm: Image Processing
In this article, we will alter the redness of an image in our React application from our Rust WASM library using Photon APIs. We will build on the previous tutorial available here.
Add photon-rs to the dependencies
First of all, let’s add photon-rs
as a dependency:
# Cargo.toml[package]
name = "rust-wasm-lib"
version = "0.1.0"
edition = "2021"# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html[lib]
crate-type = ["cdylib"][dependencies]
js-sys = "0.3.60"
wasm-bindgen = "0.2.83"
photon-rs = "0.3.1"[dependencies.web-sys]
version = "0.3.4"
features = [
'Document',
'Element',
'HtmlElement',
'Node',
'Window',
'CanvasRenderingContext2d',
'HtmlCanvasElement',
'WebGlBuffer',
'WebGlVertexArrayObject',
'WebGl2RenderingContext',
'WebGlProgram',
'WebGlShader'
]
Image Processing using Rust
Last time, we exposed a function to render a triangle using WebGL2 2D APIs. Now, let’s modify our lib.rs
to expose another function that will take the DOM Id of the canvas element and alter the redness value of its image.
Create a 2D context
#[wasm_bindgen]
pub fn alter_red(element_id: &str) {
let window = web_sys::window().expect("no global `window` exists");
let document = window.document().expect("should have a document on window"); let canvas = document
.get_element_by_id(element_id)
.expect("no canvas found");
let canvas: web_sys::HtmlCanvasElement = canvas
.dyn_into::<web_sys::HtmlCanvasElement>()
.map_err(|_| ())
.unwrap(); let context = canvas
.get_context("2d")
.unwrap()
.unwrap()
.dyn_into::<web_sys::CanvasRenderingContext2d>()
.unwrap(); # We will fill this piece later
}
Import Photon-Rs
...
use photon_rs::*;
...
Read Image from Canvas
#[wasm_bindgen]
pub fn alter_red(element_id: &str) {
... let mut image = open_image(canvas.clone(), context.clone());
}
We create a mutable reference so that we could modify the red channel later.
Use Photon-Rs API to alter redness
#[wasm_bindgen]
pub fn alter_red(element_id: &str) {
... channels::alter_red_channel(&mut image, 40);
}
Draw altered image back on canvas
#[wasm_bindgen]
pub fn alter_red(element_id: &str) {
... putImageData(canvas, context, image);}
Build the new wasm library
Let’s run wasm-pack again to build the updated library
wasm-pack build --target web
Call the new function from the demo app
Finally, let’s import an image, draw it on a canvas and call the exported alter_red
function from our App.ts
file like so:
// App.tsimport React, { useEffect } from 'react';
import init, { alter_red } from "rust-wasm-lib";
import './App.css';
import test from './test.png';function App() {
useEffect(() => {
init().then(() => {
const img = new Image(); img.onload = () => {
const canvas = (document.getElementById("canvas") as HTMLCanvasElement)!;
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext("2d"); ctx!.drawImage(img, 0, 0); alter_red("canvas");
}
img.src = test;
});
}, []) return (
<div className="App">
<canvas id="canvas" width={400} height={400} />
</div>
);
}export default App;
Now, if you run the updated app, you should see an altered image on the screen. :)
Try commenting the alter_red
call to see the difference between original and altered image.
If you liked this article, subscribe here to get the complete code and updates for the entire collection: