image
image copied to clipboard
Wrong byte-order when encoding DynamicImage with 16-bit depth
If I create a strongly typed image buffer ImageBuffer<Rgba<u16>, Vec<u16>>
with a single pixel with RGBA color [0x57d8, 0x48c9, 0xd555, 0x7eff]
(purple), I can encode it into a PNG file img16.png
and will have a purple image.
However, if I wrap my buffer inside a DynamicImage
and encode it into img_dyn.png
, I will get a yellow image.
Expected
Both img16.png
and img_dyn.png
should be purple images.
Actual behaviour
-
img16.png
is a purple image -
img_dyn.png
is a yellow image, more specifically it has RGBA[0xd857, 0xc948, 0x55d5, 0xff7e]
(swapped byte order)
Reproduction steps
let img16: ImageBuffer<Rgba<u16>, Vec<u16>> = ImageBuffer::from_raw(1, 1, vec![0x57d8, 0x48c9, 0xd555, 0x7eff]).unwrap();
img16.write_to(&mut std::fs::File::create("img16.png").unwrap(), ImageOutputFormat::Png).unwrap();
let img_dyn = DynamicImage::ImageRgba16(img16);
img_dyn.write_to(&mut std::fs::File::create("img_dyn.png").unwrap(), ImageOutputFormat::Png).unwrap();
Details
This happens on an x86_64 Linux system. This architecture uses a little-endian number representation but PNG expects a big endian ("network order") encoding; maybe it's related (I see some casts).
I am still investigating why the issue happens.
Okay, I found the issue:
- When using a typed image buffer, the encoding goes through
PngEncoder::write_image
which fixes the ordering before callingencode_inner
. - When using a dynamic image, it goes through the deprecated
PngEncoder::encode
which does NOT handle byte order before callingencode_inner
.
Shall this be fixed for future major releases? Like replacing PngEncoder::encode
with PngEncoder::write_image
?