Image Dithering: Eleven Algorithms and Source Code
tannerhelland.com
tannerhelland.com
A few years ago there was a need for 15-bpp or 16-bpp color images on phones rather than the 24-bpp images we usually work with, and dithering was a great way of producing them. No idea how much need there is today though.
I typically use Sierra Lite.
I've recently been experimenting with error diffusion along continuous space-filling curves (I forget where I saw this technique first), and using color difference functions (CIEDE2000) to gauge quantization error. These are overkill, but it sure beats doing it the same boring way forever.
Frankly, I would like it if the CRTCs attached to modern GPUs had some ability to apply dither (even just ordered dither) to buffers as they're scanned out, while exposing more precision to applications.
I found the thing which inspired my space filling curve exploration: https://www.compuphase.com/riemer.htm
The Butteraugli score between the standard lena and the Riemersma dither is about 0.5 better than the standard Floyd-Steinberg one.
Approaches like this come closer to back-propagation of errors, the lack of which is where some of the artifacts of unidirectional dither come from. In practice, any decent (full bleed) error diffusion dither works perfectly fine going between 16 and 8 bit planes, but why shouldn't I try some things out which (as you are quick to point out) may have very little value.
Heck, even gamma correction isn't strictly necessary when you're going from 16 to 8 bit sRGB.
Why do you think this Riemersma method does better at that metric? Maybe it just keeps the diffused errors spatially closer to the original pixel?
I can understand that it would become less useful, because error diffusion does less if you have more levels. But (I expect) it's still useful at 6 bits (64 values), is 8 not just an arbitrary treshold?
8 bits is not just an arbitrary threshold, it's the number of bits you need so that a 1 bit difference is just about the "just noticeable difference", assuming you've handled gamma and color reasonably well. 9 bits is more lightness resolution than you can normally see, and 7 bits is too few. If you want to geek out super hard, check out figure 238 here: http://www.telescope-optics.net/eye_intensity_response.htm
The JND of Weber's law is 0.4 - 0.5% for print and monitors most of the time, which is between 1/200 and 1/250. This is why 8 bits is so super popular, it has a 1-bit step of 1/256, which is normally just barely below what we can see with our eyes.
You may need to dither at 6 bits, banding could start to become pretty obvious. Whether you need error diffusion, I don't know, I doubt it would always useful at 6 bits, but I'm sure it would sometimes. I'd say try it on some images and compare to random dithering. Random dithering only sucks on really small palettes like 2 or 16 total colors. It's not that bad on a 256 color gif, and it becomes hard to tell the difference when you're above 4 bits per channel or 12 bits per pixel. 6 bits per channel is decent color resolution, and random will sometimes be good enough. If it's a photograph from a digital camera that's older than a year or two, chances are pretty good you can threshold the image without even dithering, because it's already noisy enough.
Lots, if you're into printing. Banding that's invisible on a monitor can become a monster when printed. An expensive monster mistake if you're printing a poster sized giclee.
This is a big reason why Photoshop dithers by default when going from a higher range down to 8 bits per channel.
Another reason the need for dither might be even increasing today is that digital cameras have only very recently gotten better than an 8 bit signal to noise ratio. We've had 16 bit RAW formats for a long time, but most cameras still had noise that was greater than 1/256. I tested one of my old Canon EOS cameras and found even in very well lit conditions, it's signal was a little over 5 bits, even though I could get a 16 bit image file out.
With the newest cameras, the signal to noise is sometimes exceeding 12 stops, so photographers might be running into banding issues in RAW images more often. Except a lot of them never notice because Photoshop quietly handles it.
A lot of artifacts are easier to deal with on a hexagon-pixel grid. Halftoning and error-diffusion dithering work really well.
I'd guess that the need for error diffusion and half-toning might wane in the future. (Not sure about that, but that's what I'd guess.) Are there other benefits you get with hex images?
The downside is that there are a zillion implementations of everything you can imagine w/r/t a square grid, whereas implementations on a triangular grid of hexagonal pixels are fewer and further between, often some crappy matlab code written by a grad student, so you’d maybe need to reimplement, optimize, debug, etc. a whole pile of tools, or even invent some new algorithms for doing stuff that hasn’t been tried on such a grid before.
There have been lots of papers written about the topic, and at least one book. http://www.springer.com/us/book/9781852339142
* * *
It’s similar to the advantages you get from tri-axial fabric: it’s better but requires custom machinery, so in practice is only used for bullet-proof stuff, space suits, and art projects. Hexagonal pixels end up getting used in medical imaging, astronomical imaging, and the like, where pixels are individually expensive.
http://www.redblobgames.com/grids/hexagons/
It's written with game design in mind, but many of the techniques are useful just the same.
A bit of description, and ancient but working GPL'ed code here: http://www.levien.com/artofcode/eventone/
A paper containing the basic output-dependent feedback idea: http://levien.com/output_dependent_feedback.pdf
For one-dimensional signals like audio, the underlying sample frequency is usually increased while decreasing the sample resolution (often to 1 bit per sample). This keeps the effective Nyquist frequency where it needs to be while pushing noise much higher in frequency where it's very easy to remove with an analog filter. Delta-sigma modulation is perhaps the most common method of audio dithering (although the delta-sigma literature rarely uses the D word).
The reason images and audio usually use dithering in opposite ways is that images are usually post-processed for lower true sample resolution (and higher effective sample resolution) after sampling, while audio is often sampled initially at much higher than the Nyquist frequency because dithering is a planned part of the audio processing chain. But not always! Those are merely common use cases.
https://bjango.com/images/articles/gradients/dithering-extre...
Illustrates the same signal dithered or not. No sampling rate involved.
And please correct me if i'm wrong, but you can not trade sample accuracy for sampling rate.
"The size of the map selected should be equal to or larger than the ratio of source colors to target colors. For example, when quantizing a 24bpp image to 15bpp (256 colors per channel to 32 colors per channel), the smallest map one would choose would be 4x2, for the ratio of 8 (256:32). This allows expressing each distinct tone of the input with different dithering patterns."
Same idea applies to 1D signals (from https://www.wikiwand.com/en/Delta-sigma_modulation : " used to convert high bit-count, low-frequency digital signals into lower bit-count, higher-frequency digital signals")
same idea: https://www.wikiwand.com/en/Class-D_amplifier https://www.wikiwand.com/en/Pulse-density_modulation
Dithering noise has the special feature of depending very strongly on the sampling rate and (statistically) very weakly on the input signal being dithered.
Dithering allows replacing high-accuracy sampling (typically constrained by computer word lengths) with high-sample rate sampling (typically cheap): without using more accurate arithmetic, analog and often completely free lowpass filtering (such as looking at a dithered image from far enough) makes N samples, with M bits of accuracy each, equivalent to one sample with M+log N bits of accuracy.
Look at the image you posted; on the right, the effective "pixels" have become larger while each has acquired more gray levels. That's a lower sample frequency traded for higher quantization resolution.
Audio and image dithering are the same thing, they only become different when you add error diffusion.
The modern image dithering that you use when going from an HDR image down to an 8-bits per pixel PNG or JPG uses exactly the same (very simple) algorithm you'd use to dither an audio file during mastering.
I don't understand your point about audio and image dithering being different when error diffusion is present. You can use error diffusion on both; in delta-sigma audio modulation, the error is diffused in only one dimension but it's still error diffusion.
Yes, absolutely right. Just making clear the distinction between dither and diffuse. Dither is always a local operation on a sample, diffuse is the spatial spreading to make the neighborhood more pleasant for humans.
I was reacting to the statement "images and audio usually use dithering in opposite ways". The article here is about error diffusion, but it's pretty hard to say whether adding error diffusion to the dither process is the 'usual' choice, for either images or audio. It's very very common to not use error diffusion in both cases.
Diffuse is more much important when the destination resolution is well above human perceptible just-noticeable differences. For example, going from 8 bits per channel to 1 bit per pixel, or for audio when going from 16 bit samples down to 8 bit samples.
http://users.eecs.northwestern.edu/~pappas/papers/pappas_ist...
I have never used a laser printer that did implement anything like this, the usual halftoning sucks. Once I handcrafted a file with a 600 dpi Floyd-Steinberg image (the native resolution of the printer I hadd) and it resulted in much better results, I didn't bother calibrating the gray levels though.
Specifically, I used the ImageMagick operations "-dither FloydSteinberg -monochrome" for more contrast or "-dither FloydSteinberg -remap pattern:gray50" for more fidelity to the original image.
I was surprised that the prints were better without adjusting for gamma. If I converted the image to a linear color space before the dither operation, the print came out too dark. I'm guessing that the gamma in the non-linear color space compensated for the dot gain on the printer to cancel out the effect.
Ha, it was the same for me. I used imageworsener where I had to explicitly specify -nogamma for this effect.
An other place where wrong gamma handling accidentally works is text anti-aliasing. It turns out that for small font size the wrong handling of colorspace results in more readable text than the gamma-correct method only for dark text on light background [1]. No wonder people don't like to use light fonts on dark background (like terminals).
[1] https://www.freetype.org/freetype2/docs/text-rendering-gener...
I've been playing with dithering recently to create braille art[0] and this series of articles[1] by the libcaca developers has been a huge help. It also goes over model based dithering algorithms which tend to give the best results.
[0]: Example https://pastebin.com/raw/cRt4GL8j
- Tone mapping hdr to display colors
- Alpha style transparency in deferred rendering
Also one case I heard about but don't know much details is audio.
Dithering is important and powerful any time some precision is discarded.
This is a little different than the article though -- all the article's dithers are good at half-toning, or 1bpp images. If your destination is 16bpp images, or 16-bit audio, you don't need error diffusion, just a decent sequence of random numbers.
When taking an image from a higher range down to 8-bits per channel, there are two specific cases where you tend to see bad banding problems. When doing high quality poster prints like a giclee or photo print, the printer's color gamut is drastically different from a monitor, so banding that you don't notice on a monitor can suddenly become a plainly visible eye sore in a print. This is a big problem if you're paying $100 for your large format print.
The other problem is when resizing an image down. The resampling process smoothes out noise in an image. Normally, a DSLR photo has a signal to noise ratio that is less than 8 bits, meaning even 16 bit RAW photos have noise that is stronger than the lower 8 bits. You can usually truncate the lower 8 bits without noticing. But if you resample the image and downscale it, the noise is smoothed and banding can appear. This can happen with photos of any large flat field of color, like a wall or the sky.
Temporal dithering is actually an issue with DVI over ethernet products as a still image on the screen is no longer static.
Another good page on image dithering: http://bisqwit.iki.fi/story/howto/dither/jy/
See this image : http://bisqwit.iki.fi/jutut/kuvat/ordered_dither/jittest_flo...
now see the whole article at http://bisqwit.iki.fi/story/howto/dither/jy/ , it's really good.
With a 1MB SVGA card, you could pick between 16-bit color at 800x600, or 8-bit (256 colors) @ 1024x768. Did you value higher resolution, or not having to palette shift every time you switch apps?
The following images have the same amount of colors, namely black and white.
https://i.imgur.com/stQUl5E.gif
https://i.imgur.com/mw8IX9N.gif
Source image:
You’ll get a diff layout that shows the GIF.
Done with imageworsener[1].
imagew -cc 2 -dither f -grayscale diR72k2.jpg diR72k2_dither.png
[1] http://entropymine.com/imageworsener/I wonder what artifacts of the limitations of modern technology will be remembered with nostalgia by those growing up with today's equipment.
(obligatory NN comment :-))