Live data from Hacker News

Dithering in Colour

obrhubr.org

41–50 of 68 posts

Re: Dithering in Colour

#42

Dithering is something of a lost art now that our displays can handle millions of colors in high definition, but it can be a striking artistic effect. If anyone thinks their websites are too colorful, I made a pure JavaScript web component to dither images on client in real time, taking into account the real pixel size of the current display. https://sheep.horse/2023/1/improved_web_component_for_pixel-...

I think dithering should still be considered, since a super high detailed game otherwise pretty engine that then has banding in the sky is pretty ugly. 32-bit RGBA can still have visible banding which dithering can fix. 256 brightness levels per channel isn't all that much when it comes to subtle variations in sky colors, the eye is more sensitive than that 12-bit per channel color might be enough to never have visib…

With 100+Hz displays it's not that hard to do temporal dithering as well. Your cones are surprisingly low bandwidth (why old color TVs even worked at 30Hz), while your rods provide danger/flicker cues outside the fovea.

Getting an extra 2bits of hue (ab) while maintaining luminance (L) is quite doable except at the chroma and brightness extremes where your eye mostly ignores them anyway. That could be done pretty high in the display stack. I'd also say that the DACs in many displays are capable of higher chroma resolution, but gamma non-linearity eats up a bit dynamic range.

Re: Dithering in Colour

#43

Earlier quoted context omitted.

I moved my canvas library's reduce-palette filter over to OKLAB calculations a while back. The calculations are more computationally intensive, but worth the effort. https://scrawl-v8.rikweb.org.uk/demo/filters-027.html

I quite like the look of the blue noise dithering on this. Are you using just a texture as a mask, or something else?

It's an array of pre-calculated values that I extracted from an image donated to the Public Domain by Christoph Peters (the link is an interesting read about bluenoise - recommend!) - http://momentsingraphics.de/BlueNoise.html

No textures or masks, just brute computing on the CPU.

Re: Dithering in Colour

#44

Error diffusion dithering is kind of old fashioned. It is a great algorithm where you only need to go though the image once, pixel by pixel. But it doesn't work well with todays hardware, especially GPUs. Would be fun to come up with new algorithms that are better parallelizable.

Blue noise threshold map works really well on GPUs.

Re: Dithering in Colour

#45
post #10

> Dithering a black-to-white gradient will be wrong without linearising first. TBH both look wrong to me. If I squint, neither dithering patterns match the original gradient... but the non-linearized one looks the most similar. What could be causing this?

I don't know where they got the idea you don't dither in srgb, the point of dithering is to map it to the nearest bit pattern with a random adjustment so that it could go either way(aside from artistic choice), you should dither in srgb if you are going to display it in srgb, which is probably why the "not linearized" version looks more accurate. See: Dithering should happen in sRGB https://www.shadertoy.com/view/Nss…

The OP example is clearly wrong, but this doesn't sound right either. The point of dithering is eg, if you have a pixel value of .5, to recreate the brightness of that with black and white pixels. The naive approach would do that with one black and one white pixel. But depending on how the display usually renders .5, then it might be better to replicate it with, say, 2 white pixels and 3 black pixels.

Re: Dithering in Colour

#46
post #10

> Dithering a black-to-white gradient will be wrong without linearising first. TBH both look wrong to me. If I squint, neither dithering patterns match the original gradient... but the non-linearized one looks the most similar. What could be causing this?

They seem to be using some kind of error diffusion. And getting error diffusion to play nice with linear colour space is nontrivial. I remember I had quite a bit of discussion with madshi when MadVR tried implementing it. You can do something that comes close by modifying the colour space into something that is gamma light in the integer part and linear light in the fractional part. If the value of a pixel is x you t…

Thank you for pointing that out. The Atkinson dithering I was using was indeed messing with the results. I'll be updating the post shortly :)

Re: Dithering in Colour

#47
post #2

They may not want to imply that didder's linearized rabbit is wrong, but I'm comfortable saying so. It's not just a little dark, it's way dark, to the point of hiding detail. The linearized RGB palette is similarly awful. It clobbers a whole swath of colors, rendering them as nearly black. Purples are particularly brutalized. Yellows disappeared and became white. On my phone, the middle palette doesn't appear too bri…

Yeah, every time I see articles about importance of linear color space for gradients, and see images there, I observe the opposite of what’s written in the text of these articles. Gradients in sRGB color space look better. I have a suspicion that might be because I usually buy designer-targeted wide gamut IPS displays. I also set up low brightness on them, e.g. right now I’m looking at BenQ PD2700U display with brigh…

Your monitor and your browser 100% affect the appearance. After calibrating your monitor, try opening the image in full resolution and take a few steps back.

For me, viewing the images on my phone makes them look off.

Re: Dithering in Colour

#49
Didn't try error diffusion, but I had good results with Bayer for the ZX Spectrum Raytracer [0]. Bayer only ever looks at the pixel it's considering, doesn't do math beyond comparing a value to its threshold, it was surprisingly easy to implement, and looks nice. A great choice for ridiculously underpowered devices :)

https://gabrielgambetta.com/zx-raytracer.html#fourth-iterati...

Re: Dithering in Colour

#50
post #9

It might be worth using a lightness estimate like OKLab, OKLrab[1], or CIE Lab instead of the RGB luminance weighting, as it should produce a more perceptually accurate result. The other issue with your code right now, is that it is using euclidean distance in RGB space to choose the nearest color, but it would be probably also more accurate to use a perceptual color difference metric, a very simple choice is euclide…

If you want to do true arbitrary palettes you also need to do projection of the unbound Oklab space onto the convex hull of the palette points. This is a tricky thing to get right, but I've found that the Oklab author's published gamut clamping for sRGB also translate well to arbitrary convex hulls.

If anyone's curious I've implemented this here: https://github.com/DDoS/Cadre/blob/main/encre/core/src/dithe... I use it to map images from their source colour space to the lower gamut palettes of E Ink colour displays.

Post reply on HN