kornelski / cavif-rs

AVIF image creator in pure Rust
https://lib.rs/cavif
BSD 3-Clause "New" or "Revised" License
582 stars 29 forks source link

Dithering in RGB-YUV conversion #27

Closed ghost closed 3 years ago

ghost commented 3 years ago

https://github.com/kornelski/cavif-rs/blob/c0ea29e30ac696c9491f25e142ab8a0c0c491ef7/ravif/src/av1encoder.rs#L66

Hi. Currently rounding is used in the RGB to YUV conversion. This can make banding sometimes. Any chance dithering could be used in the conversion? (Maybe related: #10)

kornelski commented 3 years ago

For conversion to YUV definitely not, as this would only add noise that may be costly to encode, or get lost in the encoded image anyway.

I think increasing bit depth is the best way.

ghost commented 3 years ago

Well it’s my mistake. encode_rgb takes rgb8 so definitely no dithering is needed. But how about PNG sources with higher bitdepth? If RGB48 -> YUV8/10, I think dithering is necessary. (I didn’t find dithering in loadpng.)

kornelski commented 3 years ago

But that would be dithering before encoding, and you end up asking the encoder to encode the dithering pattern for you. That's a very subtle pattern, so I expect in 99% of cases it will be blurred away (either by quantization or actual blurring filters). And when it's not blurred away, it will cost a lot to encode by adding subtle high-frequency components on top of everything.

ghost commented 3 years ago

After some tests, I become agree with you. AV1 (both aom and rav1e) just cannot well preserve dither noises, even with a high quality setting, at 8/10 bit YCbCr.

ghost commented 3 years ago

avif-test.zip

An example