tiny-skia
tiny-skia copied to clipboard
Add dithering support
Makes gradients nicer, afaiu.
It's enough to add 0.5 * random([0..1]) to the value before rounding it. This is from an unpublished crate with color utilities I'm working on atm:
use clamped::Clamp;
use core::ops::Mul;
use num_traits::{float::Float, identities::Zero};
use oorandom;
pub fn quantize<T>(
value: T,
one: T,
min: T,
max: T,
dither_amplitude: T,
rng: &mut oorandom::Rand32,
) -> T
where
T: Float + Mul<f32, Output = T>,
{
(one * value + dither_amplitude * rng.rand_float())
.round()
.clamped(min, max)
}
To go from 0..1 to 0..255 with dithering:
let quantized_value = quantize::<f32>(value, 255.0, 0.0, 255.0, 0.5) as u8;
min/max are for conversion of HDR with headroom and you may not need this. For example, going to 15 bit with one bit of headroom:
let quantized_value = quantize::<f32>(value, 32767.0, 0.0, 65535.0, 0.5) as u16;
If deterministic results are not needed, the rng can be initialized inside the function ofc.
I plan to use Skia's implementation.
Yes, that one will work for many cases. Not sure if those bitshift ops will end up being faster than a rng lookup though.
However, after you add #12 and someone wanted to use tiny-skia for creating art exported e.g. as OpenEXR and which is color-graded afterwards, they don't want the dither pattern to show up.
I.e. for generative art etc. (check e.g. valora).
I'd suggest making the dither algo pluggable somehow – if that's not too much work (closure, maybe?).
I'd suggest making the dither algo pluggable somehow
Not possible. The rendering pipeline is very low-level and vectorized.