Grayscale on 1-bit LCDs (2022)
zephray.me
zephray.me
https://en.wikipedia.org/wiki/Ordered_dithering
One is effectively posterizing a grayscale image, and his primary goal was to reduce artifacts drawing unwanted attention to the borders between poster levels.
With improvements in hardware other approaches to dithering took over. The last time I saw my father's pattern was on a DEC box logo. He moved to the color group at Kodak, and designed the "Bayer filter" used in digital cameras.
Oh yeah, well my dad...! kind of thing =)
My dad manufactured some nozzles to make bonio biscuits. That's not quite as impressive though... Unless you have a dog.
Most people think 50 megapixels = 50 red, 50 blue, and 50 green megapixels, so it's quite eye-opening. That our eyes work similarly with cones tuned to specific frequencies is just icing on the cake after that.
I remember early CCD digital camera brochures stating "actual resolution", and "enhanced resolution" (or something similar), where the latter is ~3x the former number. I wonder if this was referring to the demosaicing procedure.
They used blurry language to thinly veil the fact that the 1024x768 image you got indeed started its life as 640x480 one out of the sensor.
Most JPEG uses subsampling on chroma channels anyway.
I couldn't help myself not to point out that the people being pedantic are pedants.
Thanks for the example though, as it was a simple way of mostly expressing a complicated concept.
If we were fine with getting 1/4 resolution output we'd just put one color filter for each sensor pixel and don't Bayer demosaic anything and call it a day.
https://en.wikipedia.org/wiki/Floyd–Steinberg_dithering
The article mentions also doing this in the temporal domain.
I've been looking to build an engine/game that approximates this art style: https://obradinn.com
Yes, it's so simple, it can be applied in a single pass on a single pixel buffer. Because in convolution kernel terms - it's only sampling from half of a moor neighbourhood, and that half can be from pixels not yet processed in the same buffer when moving through them in order.
It's so simple it fits in a dweet ;P
https://www.dwitter.net/d/24142
> I've been looking to build an engine/game that approximates this art style: https://obradinn.com
Killedbyapixel took the above dweet for inspiration in the style of some of his proc gen art, although I haven't dug into the how yet. I suppose deeper game/object awareness integration could produce better results than merely piping the output of the renderer into the dither algorithm, perhaps even the rendering could be optimized by targetting dithering specifically.
I was wondering about this possibility as well. I'm already up to my elbows in hand-rolled software rasterizer - which is already constrained to only using a luminance channel (8-bits).
I suppose I could still accumulate dither error and do a one-pass, 1-bit raster by combining the world-space 256-level luminance information with whatever error information is in the accumulator.
That would be interesting to see. I like the idea of renderers that give up things e.g resolution in exchange for something else. Pixel depth is just another. Would be interesting what gains in other areas might be possible if the rasterisation stage turns into 1-bit. Then again the cost of actually operating on single bit stored values might out weight any gains... unless this is done in hardware.
Compare to a typical 24-bit RGB array, you just reduced your full-scan array access requirements from 3 per pixel to 1/64 per pixel.
For 720p (1280x720), you'd only be talking about 14,400 loop iterations to walk the entire frame buffer.
You could almost get away without even compressing the frames in some applications. At 30fps, totally uncompressed, 720p 1-bit dither would come in right at 30 mbps.
Ordered dithering, even at 8-bit, is…not my cup of tea.
At full scale, there is no loss in readability and in fact I think I prefer the aesthetic quality of the 1-bit PNG. However, at <50% zoom, the dithered version was way less readable than a 2-bit PNG of slightly higher file size, so I ended up not compressing to 1-bit.
Edit: I was wrong, my (ex-) image viewer was at fault at 50% zoom. Viewing in other apps, the dithered version is visually no different from the 2-bit version. I bet the difference is even less with a HiDPI screen.
This reminds of this great article about creating a modern ordered dithering algorithm, and its effect on animations: https://bisqwit.iki.fi/story/howto/dither/jy/
It definitely was not Floyd-Steinberg or anything else using error diffusion (which however I also remember seeing in those days, from some Windows applications' splash dialog for example), because there were these very characteristic stable patterns.
During countless hours staring at the dithered blue gradient of InstallShield, for example.
There's also some fun related work on ASCII art rendering.
This sort of thing is/will still be useful for low-cost displays. I'm sure we'll have Wifi-enabled e-ink displays on cereal boxes soon.
If anyone is a usenet archive ninja, my program was called 'BBANIM' and there was a TI-basic POC and zshell asm version released.
I recall that the first game using PoV grayscale was "Plain Jump" (sic) shortly afterwards which apparently continues to be a popular project to clone.
Demo of "Sintel" playing at ~20min into this video:
A lot of "tricks" from the past were accommodating the slow processing powers, but if you are driving this from, say, an FPGA, you there's no reason for not just doing the best thing.
One thing I didn't see mentioned: the reason this all works is because the liquid crystals don't turn very fast so effectively they are providing a filter that implements the gray-scale output from a binary input. What I'm curious about is if this is a linear process. Based on the PWM result it looks pretty linear.
didn't the original sony prs ereaders have 32 grays as well?
If OP did that, but measuring and taking into account the slow rate of change of color of these pixels, then I think he could get far better results for watching a movie on the LCD, because it should get rid of much of the blurring for fast motion.
If the error signal is allowed to propagate both back and forward in time (which would require preprocessing), then you could probably reduce the blurring even further - effectively a pixel changing from one shade of grey to another can start the transition ahead of time.
https://forums.tigsource.com/index.php?topic=40832.msg136374...
Voltage-controlled current source is a pretty basic OpAmp circuit actually. There's also some tricks to turn some common voltage regulators into current controls. If your "information" is already encoded as current, you can somewhat current-mirror with a very basic BJT circuit (its not the best circuit, but if you don't care about accuracy its fine).
I'd say that current control is _more expensive_ than PWM though. PWM is just software or a 555 timer if you're oldschool, both are cheaper than OpAmps / Voltage Regulators.
Or maybe you mean, "not feasible for the costs people expect", which is probably true. PWM is just so much cheaper in practice.
I'd imagine the retail price is a combination of 'what the customer is willing to pay', and 'random'.
Some early games made that mistake. It sounds horrible in anything newer than the first A1000s.
"Ohh, that's just a gate-glitch, we'll discuss that in later courses!"
The way that physics interacts with hardware is incredible, and the dance that we all do back and forth between hardware and software really strikes me as magical. I love it.
I'm not a hardware person, but now I sort of want to try to simulate this myself to see what it looks like.
Also, if I'm not mistaken, those hacks look good on static images but could produce nasty artifacts on moving images.
The Gameboy Camera obviously did, any games though?
This is still quite relevant.
Lid – Lo-fi image dithering - https://news.ycombinator.com/item?id=34358828 - Jan 2023 (27 comments)
I wonder if Apple ever tried this with its early CRTs for the Mac?
Circuitry to convert a multi-bit value to a voltage doesn't seem to have been cost prohibitive. Even cheap devices (the predate the Mac) like the Atari 2600 could do that.
I'm actually not sure why they went 1-bit with the Mac. Maybe they felt having more pixels was so important that going monochrome was a reasonable trade-off.
The original NeXT had 2-bit greyscale (black, white, 2 shades of gray), and that looked pretty nice. It also had lots of pixels and was way more expensive.
bool dither(int time, int value) {
time *= value;
return (value + time ^ value ^ time) < 0;
}
where value is in the range 0 ... (int_max/2)I'm sure this is what the Palm Handspring did.