Atkinson Dithering (2021)
beyondloom.com
beyondloom.com
I think in the old days you got CG know how from a few books or you went to comp.graphics.algrithms where more experienced people would gladly explain stuff to you.
Today people watch YT videos and read blog posts produced by people who also lack these basics.
It's like an error that get accumulated. But no dithering will help diffusing it. ;)
This still happens in mature software as well, including contemporary web browsers.
Just open this image in your favorite browser and zoom out:
Oh yeah, let me add from the audio synthesis world that this disease is prevalent here too
These days you can at least find references to it when you look things up.
I think one of the reason is that in the "old days", in many cases, performance mattered more than correctness. Models were, overall, very wrong, but they were fast, and gave recognizable results, which was more than enough. And working in gamma space as if it was linear saved time and wasn't that bad. That gamma space somehow matched CRT monitors response curve was an added bonus (one less operation to do).
But things have changed, with modern, ridiculously powerful GPUs, people are not content with just recognizable shapes, we want some degree of realism and physical correctness. Messing up color space in the age of HDR is not acceptable, especially considering that gamma correction is now considered a trivial operation.
Already in the old days there was Digital Fusion (now integrated as 'Fusion' into DaVinci Resolve, I think it was e.g. used on "Independence Day") and Wavefront Composer (SGI/Irix, later ported to Windows NT but I may misremember).
Also depends where "the old days" start. I got into CG around 1994 and then "the bible" was "Computer Graphics'?" from Foley et al.
And aforementioned newsgroup and also comp.graphics.rendering(.renderman)
Software that was written in VFX facilities and then became OSS didn't suffer from this as most color computations happened in f32/float, not u8/char per-channel and colors were expected to be input linearly.
Often the DCC apps didn't do the de-gamma though. So there was an issue at the user interface layer.
But in the early 2000's the problem was understood my most people working professionally in CGI for the big screen and all studios I worked at had proper color pipelines, some more sophisticated than others.
As far as OSS 3D renderers go, there were Aqsis and Pixie.
Krita was linear from the beginning, AFAIR. I.e. I recall using it for look development/texture paint on "Hellboy II" -- that was 2007 though.
Beyond efficiency, is there any reason to avoid bringing everything into "some wide gamut linear space using doubles to represent each channel" for the computations and then converting back to the desired color space for any final output or export? Are there other things or alternative things you can do to meaningfully increase the final quality too/instead of?
Outside of stylistic choices, I think the only technical reasons to use fewer bits are space & bandwidth efficiency, meeting the requirements of a given output device or file format.
There are reasons to avoid doubles, just because they’re so big. 64 bits is unnecessary and wasteful for almost all color handling. Doubles are slow on most GPUs, where a lot of image processing has moved. 16 bits per channel is usually way more than enough for basic capture & display, especially if the output color range matches the input color range, i.e. little to no editing needed. (That ACES page says “Most ACES compliant image files are encoded in 16-bit half-floats, thus allowing ACES OpenEXR files to encode 30 stops of scene information.”) Even 32 bit floats is vast overkill for most things, but offers a much wider safety net in terms of using very small or very large ranges, and reduces the possibility of clipping error or visible degradation from quantization and rounding error when converting multiple times.
Note while a lot of cameras offer things like HDR outputs and high bit rate RAW, even the best photo cameras in the world are getting around 8 effective bits per channel signal-to-noise ratio. (I’m getting this from the SNR measurements on dxomark.com) 8 bits per channel also happens to be close to the limits of human perception, when handled carefully, i.e., not linear but a more perceptually uniform color space.
You could re-dither the output, but the required amount of dither to eliminate banding artifacts is great enough to be obvious and often annoying.
I think you also hardly could avoid being annoyed if you got it wrong, because the dynamic range of display devices was much smaller.
1. Since our 'raw' formats are non-linear, processing in that space is what happens when you don't know otherwise.
2. It's much more computationally efficient to not convert into linear and back out again.
3. Given the low bitdepth of our image data, going in and out of linear space and doing even minimal processing can easily produce banding artifacts in smooth areas.
4. Due to the human CSF scaling in e.g. sRGB can give results that preserve the apparent structure in the image better, while a linear scale can look bad by comparison. sRGB levels also more correctly represent perceived levels, so thresholds based on sRGB ratios will work more consistently across brightness levels.
I'm sure plenty of people have seen internet comments about linear processing, went and implemented and found the results looked worse for reasons they didn't understand and abandoned it (and plenty of others who didn't notice it looked worse and crapped up their code without knowing it. :) )
(I believe I've read that Atkinson's dithering didn't come about until scanner software was needed for the Macintosh and so he wrote his own dithering code.)
That 512x342 monochrome world was really kind of special. I used to spend hours carefully tweaking every pixel in my little 32x32 program icons, trying to make them fit the overall aesthetic.
When I made Glider in color for the first commercial release, I used only the 16 colors of the Macintosh palette - I guess to keep the performance up, memory footprint down.
There was a good deal of experimenting with hand-dithering to get more muted colors — like maybe a checkerboard pattern of brown & grey to get a mustier-looking wood.
https://apps.apple.com/us/app/retro-dither-b-w-is-beautiful/...
"Return of the Obra Dinn" looks fantastic. I keep meaning to purchase/play that game but the intention keeps slipping down my ToDo list while I'm distracted.
[1] Demo on CodePen (will ask to use your device's camera) - https://codepen.io/kaliedarik/pen/OJOaOZz
Micropolis Web Space Inventory Cellular Automata Music 1
https://youtu.be/BBVyCpmVQew?t=291
Micropolis Web is the browser based version of Micropolis (open source SimCity), that uses WebAssembly, WebGL, and SvelteKit. Based on the original SimCity Classic code, designed by Will Wright, ported by Don Hopkins. This first video has music by Juho Hietala, Blamstrain, and the Space Inventory Cellular Automata is performed by Don Hopkins.
https://MicropolisWeb.com (tap the "space" bar a few times, even though it warns you not to)
The error diffusion dithering is most noticeable when there's not a lot of heat change in the system (strong enough heating or cooling rotates the tiles towards the extreme, then they wrap around, producing chaotic boiling lava lamp blobs).
Without the error diffusion dithering, the heat diffusion produces much more geometric less organic patterns (sharp diagonal triangular crystals that melt away quickly, instead of fuzzy dithered curvy gradients that smoothly organically diffuse and stay around for a long time).
Strictly it's not actually a "cellular automata" because of the error diffusion: information travels further than one cell locally each frame -- the leftover energy can "quantum tunnel" in the direction of scanning (serpentine left/right / right/left) into cells downstream arbitrarily far away. So when you draw in one part of the image, the dither fingers in all parts of the image wiggle in response. A true cellular automata has no "action at a distance" and the flow of information respects the "speed of light" (one cell or so per frame, depending on the radius of the neighborhood).
https://en.wikipedia.org/wiki/Circuit_bending
>Circuit bending is the creative, chance-based customization of the circuits within electronic devices such as low-voltage, battery-powered guitar effects, children's toys and digital synthesizers to create new musical or visual instruments and sound generators. >Emphasizing spontaneity and randomness, the techniques of circuit bending have been commonly associated with noise music, though many more conventional contemporary musicians and musical groups have been known to experiment with "bent" instruments. Circuit bending usually involves dismantling the machine and adding components such as switches and potentiometers that alter the circuit.
The dithering techniques like Floyd Steinberg and Atkinson taking 8 or 4 bits per channel down to 1 bit per channel are definitely anachronistic, but not dithering where the goal is 8 bits per channel.
I’ve made very expensive mistakes printing poster-sized art without using dithering, and you can end up with visible color-banding in gradients in the print that aren’t visible on a display. This is why we still need and still have dithering. This is the reason that Photoshop quietly dithers by default when you convert from 16 or 32 bits per channel down to 8 bits per channel.
There appears to be active research on new dithering techniques. I ran across libdither [1] which implements more dithering algorithms that you can imagine.
I have noticed that if you get up close to the surface of a car in a lot of modern racing games it has a very noisy/sparkly shader. I know some paint does look like this, but I always suspected this was to prevent banding by creating sub-pixel noise.
I once used Floyd-Steinberg dithering to make 3D voxel prints from brain MRI scans [0]. You just convert the scan to full white and black values to represent different inks, and it means you don't have to do any segmentation and can represent fine structures much more accurately.
May be interesting to try with Atkinson dithering too, although the loss of detail may be an issue.
Ie. Imagine a country with hundreds of elected officials, each of which represents a town or city. Each official is part of a party.
A dithering-like system could be used during the vote so that the country as a whole is fairly represented, and most towns also are represented by who the majority of their population wants.
It would work by, during an election, whenever a candidate is chosen for a location, any votes for other parties get transferred to neighbouring towns and cities. That is done repeatedly until every towns seat is filled, and nearly every voters vote has an impact (if not in their local town, then it gets to help a candidate of the same party nearbyish)
https://en.wikipedia.org/wiki/Proportional_representation
It's extremely common in Europe, and there are a lot of different precise methods for it. But the point is exactly what you're describing -- every vote has an impact.
I've always been baffled that not only has the idea never taken off in the US, virtually nobody except political scientists seems to be even aware of it.
First we need to get “one person, one vote” to be the actual goal (https://en.wikipedia.org/wiki/One_man,_one_vote). In the US, the electoral college was specifically designed to not have one person, one vote as the primary goal, and we haven’t been able to change it yet. For presidential elections, we don’t really need dithering so much as simple majority winner, plus run-off vote counting.
Maybe run-off voting already is a type of vote dithering?
You don't need randomness. Dithering looks random, but is fully deterministic.
It does suffer from the 'butterfly effect' - a few extra votes in one place can change the assignment of a lot of nearby seats.
The reason I bought it up is because deterministic dithering can definitely be gamed by gerrymandering, so if you want to avoid that you might need to introduce randomness, but then you will have an even harder time getting people to buy in than with a deterministic algorithm.
The Atkinson dithering makes the image appear overexposed/blown-out (not true to the original image).
Was a 2x speedup for dithering even important at the time, especially if it involved a sacrifice of quality? It's not like dithering images was something people did regularly, in the first couple generations of Macs.
You'd dither a few images for a game or something you were building, that you were lucky to get from a scanner. It was a pretty rare thing. Speed wasn't really relevant, as far as I remember.
I only used a B&W Mac a few times, but I do remember Windows 3.1 doing on-the-fly ordered dithering when running with palettized color (and being very surprised at NOT seeing the dithering on the blue gradient of a setup program once I started using high color modes). Windows 1.0 apparently was capable of doing it as well.
Do you have a source for that? That's very much the opposite of what I remember. If you had 16 colors or even 256 colors, I don't remember anything in the Windows UX being dithered. Like I don't think you could pass an RGB color to GDI to draw a light pink line and it would dither it for you.
The only dithering I remember was indeed the background of blue gradients in Setup, and I always assumed that was custom code. After all, it's not like GDI had commands for gradients either.
I don't get the appeal of Atkinson dithering at all -- it makes the noise more "clumpy" or "textured" and thereby inherently reduces the amount of detail you can perceive. I don't think that's something subjective.
And if you want the "richer contrast" that the article describes Atkinson as providing, then easy -- just increase the contrast of the grayscale image before dithering. Then you actually have control over whatever final contrast you want -- it can be whatever you want! But you won't lose detail the way Atkinson does.
https://uwspace.uwaterloo.ca/bitstream/handle/10012/3867/the...
Among the things it covers is the design of a noise shaping filter with a more symmetrical response than the Floyd-Steinberg one.
I made a ruby script that can take a graphic and scale it to whatever size, then it uses a closest color match to substitute colors for the _very_ limited Pico* palette and applies dithering to make it look attractive. I like Stenberg the most, but have played with Atkinson and am still feeling around a bit.
I recall using Macsbug to show it.
You can create one online here[2], but it doesn't seem to support Atkinson for whatever reason.
[0]: https://en.wikipedia.org/wiki/X-Face
And this is a naive question, but could one construct a kernel that diffuses the error across all surrounding pixels, not just the bottom+right? I get that this will cause recursion difficulties as error bounces back-and-forth between neighboring pixels, but is that resolvable?
That way the errors get spread out more evenly, and you don't get 45 degree diagonal flowing artifacts down and to the right.
The In-Laws (1979): Getting off the plane in Tijuara:
https://www.youtube.com/watch?v=A2_w-QCWpS0
"Serpentine! Serpentine!!!"
https://brucebcampbell.wordpress.com/wp-content/uploads/2013...
Also whether you apply the dithering in a linear colorspace.
From their About page:
"Thus, instead of using full-colour high-resolution images, we chose to convert all images to black and white, with four levels of grey in-between. These black-and-white images are then coloured according to the pertaining content category via the browser’s native image manipulation capacities. Compressed through this dithering plugin, images featured in the articles add much less load to the content: compared to the old website, the images are roughly ten times less resource-intensive."
An interesting aspect about the game is how it required making the dithering stable to changing viewpoints, not something typical dithering algorithms care about.
Does that account for the repeated post processing done by every client?
That being said, I doubt the post processing adds much in this case.
[1]: "Low-tech Magazine questions the belief in technological progress and highlights the potential of past knowledge and technologies when it comes to designing a sustainable society" - https://www.patreon.com/lowtechmagazine/about