Using turbojpeg with fast_image_resize

I'm making a function to resize a jpeg image using turbojpeg.
It works as intended when using resize (docs.rs/resize) but I was hoping to make is faster so I'm trying to use fast_image_resize instead.
When shifting over from resize to fast_image_resize the code runs/works but the output image is garbage/distorted.
If I don't use turbojpeg::decompress() but instead use the example code from fast_image_resize then everything works, even when using turbojpeg::compress() at the end.

This works:

let img = image::io::Reader::open(img_path_in)
.unwrap()
.decode()
.unwrap();
let width = std::num::NonZeroU32::new(img.width()).unwrap();
let height = std::num::NonZeroU32::new(img.height()).unwrap();

let mut src_image = fr::Image::from_vec_u8(
  width,
  height,
  img.to_rgba8().into_raw(),
  fr::PixelType::U8x4,
).unwrap();
....

This does not work:

let jpeg_data = std::fs::read(img_path_in).unwrap();
let img = turbojpeg::decompress(&jpeg_data,turbojpeg::PixelFormat::RGBA).unwrap();

let mut src_image = fr::Image::from_vec_u8(
  width,
  height,
  img.pixels.to_vec(),
  fr::PixelType::U8x4,
).unwrap();
....

I don't think the code after this matters, but if needed I can post it.

I don't know what the problem is but I'm guessing that the image data is in the wrong format when I add it to the src_image struct.
I have tried to change turbojpeg::PixelFormat::RGBA to other values and do something with img.pixels.to_vec() but without any progress.

Anyone that knows how to fix this or has a guess?

Are you sure it's natively an RGBA8 image? This may be doing a conversion for you:

  img.to_rgba8().into_raw(),

Where as this presumably takes what you tell it as gospel:

let img = turbojpeg::decompress(&jpeg_data,turbojpeg::PixelFormat::RGBA).unwrap();

No, I'm not sure about much when it comes to handling images. I'm rather new to it.
But the turbojpeg line works when using resize instead of fast_image_resize so I assume that it works.
But maybe I need some more converting, that .into_raw() does, somehow.

Maybe try this:

let jpeg_data = std::fs::read(img_path_in).unwrap();
let mut decompressor = turbojpeg::Decompressor::new().unwrap();
let header = decompressor.read_header(&jpeg_data).unwrap();
let mut image = turbojpeg::Image {
    pixels: vec![0; 4 * header.width * header.height],
    width: header.width,
    pitch: 4 * header.width, // size of one image row in memory
    height: header.height,
    format: turbojpeg::PixelFormat::RGBA,
};

decompressor.decompress(&jpeg_data, image.as_deref_mut()).unwrap();

And then

let turbojpeg::Image { width, height, pixels, .. } = image;
let src_image = fr::Image::from_vec_u8(
  width,
  height,
  pixels,
  fr::PixelType::U8x4
).unwrap();

(Untested.)

That looks interesting, I'll give it a try.

No, that code seem to return the same result as simply using let img = turbojpeg::decompress(&jpeg_data,turbojpeg::PixelFormat::RGBA).unwrap();

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.