Closed vincent-herlemont closed 3 months ago
I think it will be more easy if you use image
crate to encode and save an image as JPEG-file.
Or do you need a heif
container with a JPEG-encoded image inside? libheif
doesn't create JPEG-files. It creates HEIF-files with somehow encoded images inside.
You can get &[u8]
buffer with pixels data from corresponding plane(s). For ColorSpace::Rgb(RgbChroma::Rgb)
it is interleaved
plane:
let planes = image.planes();
let interleaved_plane = planes.interleaved.unwrap();
assert_eq!(interleaved_plane.width, 1024);
assert_eq!(interleaved_plane.height, 800);
assert_eq!(interleaved_plane.stride, 0);
let buffer: &[u8] = interleaved_plane.data;
In simple case (stride == 0) DynamicImage
is created easy:
let rgb_image = image::RgbImage::from_raw(
interleaved_plane.width,
interleaved_plane.height,
buffer.to_vec(),
).unwrap();
let dyn_image = image::DynamicImage::ImageRgb8(rgb_image);
I'm not sure if the image
crate supports images with stride > width * pixel_size. So in that case you have to copy image rows one by one (without extra bytes at the end of each) from buffer
to Vec<u8>
.
Thank you for your suggestions! It works perfectly (I adapted width
, height
, stride
) to the image I have locally.
Here is the final code:
#[test]
fn convert_to_jpg_with_image_crate() -> Result<()> {
let read_ctx = HeifContext::read_from_file("./data/IMG_0832.HEIC")?;
let handle = read_ctx.primary_image_handle()?;
let lib_heif = LibHeif::new();
let image = lib_heif.decode(&handle, ColorSpace::Rgb(RgbChroma::Rgb), None)?;
let planes = image.planes();
let interleaved_plane = planes.interleaved.unwrap();
assert_eq!(interleaved_plane.width, 4032);
assert_eq!(interleaved_plane.height, 3024);
assert_eq!(interleaved_plane.stride, 12096);
let buffer: &[u8] = interleaved_plane.data;
let rgb_image = image::RgbImage::from_raw(
interleaved_plane.width,
interleaved_plane.height,
buffer.to_vec(),
).unwrap();
let dyn_image = image::DynamicImage::ImageRgb8(rgb_image);
let mut file = File::create("./data/IMG_0832.jpg").unwrap();
dyn_image.write_to(&mut file, image::ImageFormat::Jpeg).unwrap();
Ok(())
}
I'm not sure if the
image
crate supports images with stride > 0. So in that case you have to copy image rows one by one (without extra bytes at the end of each) frombuffer
toVec<u8>
.
I feel like the image
library does not take stride
into account; the image result does not seem to be affected.
I am trying to convert a HEIC file to JPEG using the library. Here is my test:
Here is the error I encountered:
By adding logs in the C++ binder library, I discovered that the logs stop at this line
jpeg_create_compress(&cinfo);
encoder_jpeg.cc#L369, then the error is returned here encoder_jpeg.cc#L354.I might be configuring the encoder incorrectly. Do you have any suggestions for solutions or investigations?
Note that the same image converts very well with similar code using
Av1
by utilizingCompressionFormat::Av1
.