Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In which format should I pass image from Rust to JS?

I'm trying to pass image from JS to Rust, process it and return back from Rust to JS. Please, help me to understand in which format should I return image from Rust.

My JS code look like this:

import { Image } from "image_processing";

const input = document.getElementById('image-input')
const image_canvas = document.getElementById('image-canvas')

input.addEventListener('change', async (event) => {
    const buffer = await event.target.files[0].arrayBuffer();
    const view = new Uint8Array(buffer);
    const image = Image.new(view);
    console.log('xxx1', view);

    const imageBlob = image.get_image_blob();
    console.log('xxx2', imageBlob);

    const blob = new Blob(imageBlob, { type: 'image/jpeg'});
    console.log('xxx3', blob);


    image_canvas.width = image.get_width();
    image_canvas.height = image.get_height();
    const imageBitmap = await createImageBitmap(blob, 0, 0, image_canvas.width, image_canvas.height);
    const context = image_canvas.getContext('2d');
    context.drawImage(imageBitmap, 0, 0);
});

And Rust Image.new and Image.get_image_blob functions looks like this:

#[wasm_bindgen]
impl Image {
    pub fn new(image_blob: Vec<u8>) -> Image {
        let reader = Reader::new(io::Cursor::new(image_blob))
            .with_guessed_format()
            .expect("Cursor io never fails");

        let extension = match reader.format() {
            Some(extension) => extension,
            None => panic!("Can't guess image extension")
        };

        let width;
        let height;
        let image = match reader.decode() {
            Ok(image) => {
                let (w, h) = image.dimensions();
                
                width = w;
                height = h;
  
                image
            },
            Err(error) => {
                panic!("Can't get image: {}", error)
            }
        };

        Image {
            image,
            width,
            height,
            extension,
        }
    }
    
    .
    .
    .

    pub fn get_image_blob(&self) -> Vec<u8> {
        match self.extension {
            x if x == ImageFormat::Png => self.image.to_rgba8().to_vec(),
            _ => self.image.to_rgb8().to_vec()
        }
    }
}

When I'm trying to process jpeg image in browser console I get this: browser console output

It's look like my returning blob from get_image_blob is incorrect. Before I process my image with Rust it has right file signature for jpeg: [255, 216, 255, ...]. But after processing it became [162, 162, 152, ...]. I assume that I should try changing to_rgb8 method on something else, but I can't understand why. Can you help me and explain what I'm doing wrong?

EDIT: Turns out that signature changes when I call decode method, but I still don't know why.

like image 205
reshnaut Avatar asked Jan 26 '26 20:01

reshnaut


1 Answers

The decode method take a JPEG file and returns the raw pixels as an uncompressed block of memory. In other words, the [162, 162, 152...] means that the top right pixel has value red=162, green=162, and blue=152. You can make image from raw byte data by using ImageData or by encoding that data with help of image::codecs::jpeg::JpegEncoder.encode or save_buffer_with_format methods. For more information you can read this issue.

like image 128
reshnaut Avatar answered Jan 29 '26 08:01

reshnaut



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!