[HN Gopher] Grayscale on 1-bit LCDs (2022)
       ___________________________________________________________________
        
       Grayscale on 1-bit LCDs (2022)
        
       Author : _Microft
       Score  : 452 points
       Date   : 2023-01-12 14:47 UTC (8 hours ago)
        
 (HTM) web link (www.zephray.me)
 (TXT) w3m dump (www.zephray.me)
        
       | FullyFunctional wrote:
       | Nice final result but I would have skipped the PWM detour. PWM
       | sucks and has known bad aliasing issues. Sigma-Delta (AKA "1-bit
       | DAC") is error diffusing, cost the same to implement, and should
       | always be preferred IMO.
       | 
       | 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.
        
         | bee_rider wrote:
         | FWIW, as someone who doesn't really know anything about LCDs
         | but has messed around with circuits and LEDs, the digression
         | into PWM bridged the gap nicely for me at least. It probably
         | wasn't necessary from a technical point of view but it helped
         | tell the story.
        
       | _Microft wrote:
       | Here is a video by the author with explanations of the technique
       | and later on video playback on the display.
       | 
       | Demo of _" Sintel"_ playing at ~20min into this video:
       | 
       | https://www.youtube.com/watch?v=n7uxEaGB9t0
        
       | em3rgent0rdr wrote:
       | Very impressive. But frustrating having to read this great blog
       | post over a tiled background which obscured the text.
        
       | Tepix wrote:
       | Is it just me? I look at the screenshot below the sentence "
       | _Then bring in the noise-shaper._ " that shows the difference
       | between the _1st-order noise shaper_ and the _Sequence LUT_
       | and... i 'm seeing only a very small difference!
        
         | sbierwagen wrote:
         | It makes more sense in video:
         | https://www.youtube.com/watch?v=n7uxEaGB9t0
        
           | philsnow wrote:
           | Ah, thank you, the post says "But as you could see from the
           | video progress bar, I am not finished yet" but doesn't embed
           | the video or have a link to it anywhere that I could see.
        
       | aryaonearth wrote:
       | [flagged]
        
       | aryaonearth wrote:
       | [flagged]
        
       | aliqot wrote:
       | Man it's been so long since I've seen an 88x31 on a website. I
       | miss those.
        
       | ErikHuisman wrote:
       | Why are people doing this 30+ years to late? Imagine having this
       | as kids.
        
         | DSMan195276 wrote:
         | They actually gave an example that was, the Gameboy. I think in
         | that case the big issue for going beyond just 4 gray levels is
         | RAM and ROM space, and also potentially the speed of the PPU
         | and display driver in dealing with the extra data.
        
           | saboot wrote:
           | I'm trying to think of examples that used it on the gameboy.
           | 
           | The Gameboy Camera obviously did, any games though?
        
         | cameldrv wrote:
         | We were! When I was a kid 28 years ago I had an HP48 calculator
         | that people used the same techniques with for some games and
         | such.
        
         | dragontamer wrote:
         | There's a ton of monochrome screens available to EEs under $20,
         | even under $10.
         | 
         | This is still quite relevant.
        
         | ChuckNorris89 wrote:
         | The computational and engineering effort for these hacks to get
         | to those results in production would have made those price
         | sensitive consumer gadgets far more expensive. It just wasn't
         | economically feasible.
         | 
         | Also, if I'm not mistaken, those hacks look good on static
         | images but could produce nasty artifacts on moving images.
        
         | roywiggins wrote:
         | TI-83+ calculators were doing grayscale like this 20 years ago,
         | so a lot of people _did_ have this as kids. It was a bit
         | flickery but worked well.
        
         | Yhippa wrote:
         | Yep! I remember doing this on the HP 48G's in the mid-90's:
         | https://www.hpcalc.org/hp48/graphics/grayscale/
        
           | Grustaf wrote:
           | I remember those! PSA: there's a HP48G emulator for iphone, I
           | use it almost every day...
        
           | mmastrac wrote:
           | I only ever got four colors to display reliably on my HP48,
           | mostly through naive bank switching/mapping of GROB data.
        
       | seltzered_ wrote:
       | It's worth noting this person (Wenting Zhang aka zephray) is the
       | same one that's also worked on the eink drivers for
       | https://www.modos.tech/ -
       | https://twitter.com/zephray_wenting/status/15346412997054996...
       | 
       | See also https://news.ycombinator.com/item?id=31674373
        
       | starmole wrote:
       | Made a (very simple!) shader toy for temporal dither on your
       | webcam: https://www.shadertoy.com/view/clf3Rj
        
       | karmelapple wrote:
       | I thought it might be about dithering used in HyperCard, but
       | nope, very different approach.
       | 
       | I wonder if Apple ever tried this with its early CRTs for the
       | Mac?
        
         | marssaxman wrote:
         | I can't swear that nobody ever tried it, but such a demo would
         | have been very impressive, and I can't imagine how it could
         | have been done. Those original black-and-white Macintoshes had
         | an 8 MHz processor, and the screen was 512x342 pixels; just
         | performing a single cycle's worth of computation per pixel
         | would limit you to 45 Hz. Even if you could somehow
         | miraculously perform dithering in a single instruction per
         | pixel, you'd have no CPU left to run the animation or do
         | anything else.
        
         | adrianmonk wrote:
         | Would it have provided any benefit? CRTs have continuously
         | variable brightness. The bottleneck was having large enough
         | video RAM to even store the higher pixel depth, the processing
         | power to draw it, and the bandwidth to do the output.
         | 
         | 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.
        
       | tinglymintyfrsh wrote:
       | PWM those 1 bits to get grayscale and add dithering.
       | 
       | I'm sure this is what the Palm Handspring did.
        
       | londons_explore wrote:
       | OP comments on 'error diffusion dithering in 3d' in a few
       | places...
       | 
       | 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.
        
       | z2 wrote:
       | Immediately thought of the assembly-level hacking people did ~20
       | years ago on TI's graphing calculators to get reliable grayscale,
       | for instance this on the TI 83 series:
       | https://www.ticalc.org/archives/news/articles/7/77/77966.htm...
        
         | dpkingma wrote:
         | Haha, thanks for dredging this up, I made that :) It seems
         | quite related to the OP article. It's a library for making
         | grayscale games on the TI83 graphical calculator, which has a
         | monochrome display. The main challenge was optimizing the
         | interrupt routine, the z80 assembly code that performed the
         | flickering/dithering that achieves the grayscale effect, to fit
         | within the tiny amount of clock cycles available on the Zilog
         | Z80 6 MHz processor. Even after optimization, it took up
         | ~50%-75% of all available cycles. Some people managed to make
         | some pretty fun grayscale games with it (e.g. https://www.tical
         | c.org/archives/files/fileinfo/331/33153.htm...). This was
         | obviously in the pre-smartphone era, so the ti83 was quite
         | popular for playing games in class, and hand written assembly
         | code was the only way to make it fast.
        
           | andrepd wrote:
           | I knew immediately that the link was to Desolate before
           | opening it :) It blew me away the first time I played it, as
           | I was used to my shitty turn-based TI-BASIC games.
        
           | joshstrange wrote:
           | Holy crap! This takes me back. I used this (or something
           | based on it) on my TI84 SE+ to play around with grayscale
           | over a decade ago. It's the first thing that came to mind
           | when I saw this article. I never got into ASM on the TI calcs
           | but I wrote a TON of TI-Basic. I spent a ton of time on those
           | forums and posted a number of apps/games I wrote (though I
           | can't find them now).
        
           | modeless wrote:
           | Cool to see that one of the authors of the most cited paper
           | in machine learning also got their start hacking on TI
           | calculators. What a great learning environment that was!
        
         | gorkish wrote:
         | Not that anyone hadn't thought of it before, but I believe that
         | I may hold the first claim of a grayscale TI calculator demo. I
         | released a four-frame, 4-bit grayscale animation of beavis &
         | butthead headbanging for the newly minted Zshell on TI-85 in
         | 1992. I posted it to one of the listserves or usenet groups,
         | but I have never been able to find a copy in anyone's archives.
         | I'd love to see it again. It was not a fancy program. The
         | frames were stored as 4 x 4 x 64x128 bitmaps = 16KB so it
         | consumed like 2/3 of the calculator's memory. Fun times.
         | 
         | 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.
        
       | kqr wrote:
       | Wow, this is really impressive. I would have stopped at various
       | types of dithering, but these techniques are cool and the results
       | look like they really work!
       | 
       | I'm not a hardware person, but now I sort of want to try to
       | simulate this myself to see what it looks like.
        
         | londons_explore wrote:
         | Even modern color LCD's on laptops and stuff implement many of
         | these tricks.
        
       | fooblaster wrote:
       | Another excellent article on dithering:
       | https://news.ycombinator.com/item?id=25633483
        
       | Syzygies wrote:
       | My father Bryce Bayer studied this question fifty years ago at
       | Eastman Kodak; his approach is known as ordered dithering:
       | 
       | 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.
        
         | xattt wrote:
         | I really hope your childhood home had a stained glass window
         | with a Bayer pattern!
        
           | dylan604 wrote:
           | now that is something that could be interesting. maybe change
           | from squares to diamonds for effect, but i like the
           | suggestion! a stained Bayer glass window makes it sound like
           | it should be found in medieval cathedrals
        
         | dwringer wrote:
         | Seeing that brings back a lot of nostalgia for the old PC
         | Paintbrush that was once ubiquitous on DOS machines. The images
         | it turned out were really great for the time, and I sometimes
         | miss the aesthetic of those dithering patterns.
        
         | dylan604 wrote:
         | I think this is one of the better, well my dad can beat up your
         | dad type of stories. I know you absolutely didn't mean it that
         | way, but there's a part of me that read it that on the second
         | reading of it.
         | 
         | Oh yeah, well my dad...! kind of thing =)
        
           | benj111 wrote:
           | My grandad maintained that he has sorted out some issue with
           | the soon to be rover V8 when it was bought from GM.
           | 
           | My dad manufactured some nozzles to make bonio biscuits.
           | That's not quite as impressive though... Unless you have a
           | dog.
        
         | lizknope wrote:
         | Wow! I worked on digital camera chips and had coworkers writing
         | demosaic algorithms. We wouldn't have even had those jobs if it
         | wasn't for your father.
        
         | tinglymintyfrsh wrote:
         | I recall graphics programming books in the mid/late 90's about
         | dithering techniques.
         | 
         | 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.
        
         | _Microft wrote:
         | Your father invented the Bayer filter. HN never ceases to amaze
         | me :)
        
           | mbreese wrote:
           | If you think that's good, also check out further down in this
           | thread. Gotta love HN for finding people that wrote old
           | libraries. In the below case, it's a library for using
           | grayscale on a TI83.
           | 
           | https://news.ycombinator.com/item?id=34356244
        
         | WithinReason wrote:
         | To add to the above, an alternative dithering approach is error
         | diffusion, e.g.:
         | 
         | https://en.wikipedia.org/wiki/Floyd-Steinberg_dithering
         | 
         | The article mentions also doing this in the temporal domain.
        
           | bob1029 wrote:
           | I find this to be the most elegant way to handle dithering.
           | Been working with this on a side project.
           | 
           | I've been looking to build an engine/game that approximates
           | this art style: https://obradinn.com
        
             | tomxor wrote:
             | > I find this to be the most elegant way to handle
             | dithering
             | 
             | 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.
             | 
             | https://www.fxhash.xyz/generative/4686
        
               | bob1029 wrote:
               | > 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.
        
               | tomxor wrote:
               | > 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.
        
               | bob1029 wrote:
               | Think about it like this... In 1-bit dithered scheme, 1
               | machine word represents 64 entire pixels worth of values.
               | You can access 64 pixels at a time and use bit-wise
               | operations to manipulate the individual values.
               | 
               | 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.
        
               | cwmoore wrote:
               | Surely you intended a Moore neighborhood and not moor? No
               | relation.
        
           | adtac wrote:
           | One more relevant use case: I've found Floyd-Steinberg
           | dithering to be somewhat useful in compressing scanned JPEG
           | paper notes at 600dpi (~1.5-2.5MB per page) to 1-bit PNG
           | (100-300KB).
           | 
           | 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.
        
             | Nick87633 wrote:
             | This sounds really interesting. Can you share some
             | screenshots for us to see?
        
           | IIsi50MHz wrote:
           | And for 1-bit, Atkinson dithering can produce good effect.
           | Floyd-Steinberg and Atkinson are the only two I'd usually
           | consider for 1-bit dithering, with a preference for Atkinson
           | for most images.
           | 
           | Ordered dithering, even at 8-bit, is...not my cup of tea.
        
             | makapuf wrote:
             | For static images, yes. For animation, not so much as a
             | pixel moving can have huge implications on other sides of
             | the image due to error diffusion.
        
         | glitchc wrote:
         | Kudos to your dad! Every time I explain how a digital camera
         | works to people, invariably it's the concept and application of
         | the Bayer filter that causes their jaw to drop.
         | 
         | 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.
        
           | dylan604 wrote:
           | Yeah, realizing the actual image is only about 1/4 of the
           | resolution of the sensor is something not everyone grasps.
           | Marketing of course doesn't try to explain it either. I tend
           | to take it too far by then explaining the benefits of using
           | 3-chip monocolor sensors (or if not real-time, a single
           | sensor triple flashed) to get the full resolution for each
           | color channel. These are usually CCDs instead of CMOS, but
           | the theory is the same. This is how most astronomy things
           | work, like the Hubble, but instead of RGB, they use other
           | filters that get "colorized" into RGB-ish.
        
           | ISL wrote:
           | For a Foveon, the way you first think it works is the way it
           | works :).
           | 
           | https://en.wikipedia.org/wiki/Foveon_X3_sensor
        
         | ricardobeat wrote:
         | Must be such a good feeling to have this legacy. Your father
         | did great!
         | 
         | 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/
        
       | matt-attack wrote:
       | The PWM greyscale is commonly used in other other display
       | technologies like LED where controlling current is not feasible
       | as well as Texas Instrument's DMD which is a micro mirror that
       | can only be on or off.
        
         | dragontamer wrote:
         | > LED where controlling current is not feasible
         | 
         | 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.
        
           | error503 wrote:
           | It's "feasible" to use dynamic current sources per pixel, and
           | many LED pixel drivers do offer this for dot correction /
           | colour balance / global brightness, but PWM is almost always
           | used for pixel values; it's much easier to achieve the
           | necessary resolution staying in the digital domain, and
           | there's not really any downside. The other big issue with
           | current control is that the simple ways to do dynamic current
           | are linear, so effectively use constant power regardless of
           | pixel state, and also burn a lot of silicon area and might
           | start creating thermal issues in the driver. At high power
           | levels, current regulated switch mode DC-DC drivers start to
           | make sense, but doing that per pixel is definitely not
           | feasible.
        
           | matt-attack wrote:
           | I really meant for large 4K (4096x2160) arrays of LED pixels
           | like in this [1].
           | 
           | [1]: https://displaysolutions.samsung.com/led-signage/onyx
        
           | mananaysiempre wrote:
           | When I needed a beeper with a time delay for a fridge door, I
           | looked at retail prices for a dual-555 IC (a 556) and for a
           | dual-opamp IC (ended up going with a 6002) and was surprised
           | to find the opamp was something like three times cheaper,
           | even taking into account the hefty capacitor for the time
           | delay. (Active buzzers wouldn't run off a 3V cell so I did
           | need a dual IC for the delay and the square-wave generator.)
           | Is this just a retail-specific distortion?
        
             | londons_explore wrote:
             | All of the components you mentioned would be sub-cent in
             | large volumes and surface mount parts.
             | 
             | I'd imagine the retail price is a combination of 'what the
             | customer is willing to pay', and 'random'.
        
       | peterisza wrote:
       | Since we have the whole video in advance (we can look forward in
       | time) and we can also measure the response function of the
       | pixels, it would be possible to preprocess the whole video to
       | make it look even better (less ghosting).
        
       | drtse4 wrote:
       | AKA Bit banging PWM, never seen it working with this kind of
       | displays, nice project, it can be done even with higher frequency
       | signals too (requires an oscilloscope and a few tries to get a
       | smooth signal).
        
       | avodonosov wrote:
       | Good article, but the background beneath the text (the small paw
       | prints) makes reading difficult.
        
       ___________________________________________________________________
       (page generated 2023-01-12 23:00 UTC)