Image filter application

With the basic setup for the Rust code done you can now write a function that applies the image filter to a given image.

✅ Start by importing the necessary modules and structs from the rustagram2 crate and the standard library in your src/lib.rs.

use rustagram::image::io::Reader;
use rustagram::image::ImageOutputFormat;
use rustagram::RustagramFilter;

✅ Next create a new function. It will get a slice of bytes representing the image and a filter name as a string. It should return a Vec<u8>, a vector of bytes representing the modified image in PNG format.

#[wasm_bindgen]
pub fn apply_filter(img: &[u8], filter: &str) -> Vec<u8> {
    log::debug!("image: {} bytes, filter: {:?}", img.len(), filter);
    // (to be filled in)
}

The code from the next steps will go in this function.

✅ You previously set up logging, use that and log something to ensure you get the data that you expect.

    log::debug!("image: {} bytes, filter: {:?}", img.len(), filter);

✅ The image data needs to be read from the buffer. The application allows multiple file formats, luckily the image format can guess the format and then decode it. The documentation for the Reader type goes into some detail.

    let img = Reader::new(Cursor::new(img))
        .with_guessed_format()
        .unwrap()
        .decode()
        .unwrap();

For now just unwrap on errors. As you have set up the panic handler you should see it in the browser's console if you hit an error.

✅ As you have done in the CLI application parse the filter name into a FilterType.

    let filter_type = filter.parse().unwrap();

Again if you compile everything at this point you will probably hit a type annotation error. That is expected and you can observe how this changes as you fill in the rest of the code in the next steps.

✅ You now have everything you need to apply the filter to the decoded image. This is exactly the same as in the previous tutorial.

    let out = img.to_rgba8().apply_filter(filter_type);

✅ But now instead of saving that changed image to a file you should store it in a buffer and return that buffer. ImageBuffer#write_to does just that. Don't forget to specify its format as PNG.

    let mut bytes: Vec<u8> = Vec::new();
    out.write_to(&mut Cursor::new(&mut bytes), ImageOutputFormat::Png)
        .unwrap();

    bytes

And that is already all the code you need to be able to apply an image filter to a passed in image.

✅ Again build all code and run wasm-bindgen to generate the JavaScript shim. If you are using the Makefile as above you can now run

make

Otherwise run the commands directly:

cargo build --release --target=wasm32-unknown-unknown
wasm-bindgen target/wasm32-unknown-unknown/release/image_filter.wasm --out-dir app --target web --no-typescript

The JavaScript shim (image_filter.js) and the wasm file (image_filter_bg.wasm) in your app directory should be updated.


In the next chapter you will work on the other side of this application: First the HTML frontend and then the necessary JavaScript code to load and run the WebAssembly module.