Encoding Problem Black level 17: maybe color space related
Hi,
I am attempting to encode some images in avif format using this package. However I am experiencing what appear to be color space issues? I am not really sure. I am running on flutter web.
using image: 4.5.2 using flutter_avif: 3.0.0
This code creates invalid encoded avif images
final image = img.Image(height: 100, width: 256);
image.forEach((pixel) {
pixel.r = pixel.x;
pixel.g = pixel.x;
pixel.b = pixel.x;
});
// return img.encodePng(image);
// https://github.com/yekeskin/flutter_avif/issues/39#issuecomment-1858844793
// https://web.dev/articles/compress-images-avif
final avifFile = await encodeAvif(img.encodePng(image),
// 0 (slowest/highest quality) - 10 (fastest/lowest quality)
speed: 8,
// 0 (lossless) - 63 (lowest)
maxQuantizer: 40,
minQuantizer: 25,
maxQuantizerAlpha: 40,
minQuantizerAlpha: 25);
img.encodePng(image) output:
avifFile: (uploaded renamed to avif_real.png since github does not allow avif files. download and rename to .avif. the file is NOT converted to png it is the exact avif binary)
I am confident that the image is being generated correctly, but the encodeAvif function is breaking the image. I suspect it is color space related but i am not sure. Since the "black level is 17, and white level is 234. I can find no option to fix it. This issue exists in real world test images, but this is for reproduction. I have used exif preserve to true, I have also tried switching the decoder in the encodeAvif class to not the web version (not sure why there are 2 separate implementations for that) to no success.
Images display the same in: firefox, my kde desktop using gwenview, and in GIMP.
GIMP says the avif image is using the: BT.601 sRGB-TRC RGB color space. This is the same for all of my test images (input of png, avif, and jpeg), along with the code above.
I have found no way to adjust the color space input and output. manually generating avif images in GIMP does not result in the raised blacks and lowered whites.
I am able to reproduce this issue on web. All other platforms seems to be working fine. My initial guess is that this might be realated to rgb to yuv conversion but I need to investigate some more.
I have also tried switching the decoder in the encodeAvif class to not the web version (not sure why there are 2 separate implementations for that) to no success.
This is because Flutter's internal image decoding is not reliable on web so I have to use an external decoder.
In my test image color saturation also is reduced during the encode, not just luminosity. If that is helpful.
I haven't looked in detail at the code yet, but i am not sure i would be qualified anyway. That makes sense! i have been doing some searching online about what might be causing the issue, and everything i can see points towards the colors being double converted to a Limited color space.
Assuming a start value of 0 and it is converted to a limited color space zero would get mapped to 16–235. and because the color space is now limited, after it gets mapped again, the resulting values are slightly off (due to 8 bit resolution), and we end up with a RGB black level of 17 and white level of 234 in the resulting image in all channels, rather than the expected 0, and 255 from only running a single conversion.
Let me know if I can assist in testing anything