Hacker News new | ask | show | jobs
by fstark 1875 days ago
I looked at several approaches, but I absolutely wanted to do floyd-steinberg, as this is what were, for me, "realistic" images on my Mac back in the 80s.

The example on the website are identical to the ones in the first video, as the simple looping gif is a by-product of the encoding.

On the second video (the one with sound), you cannot compare, as the video is compressed and not all the parts of the image are updated. But the algo is the same.

The swimmy bits come from the fact that I encode images using the preceeding one, and use the pixels from the preceeding images to "control" where the error gets diffused, to try to get some temporal stability in error diffusion (I have a long blog post that explains that, but I never got around finishing it, it seems people were more interested by having me coding sound).

I am not completely sure why the swim effect seems to always be in the north-west direction (I understand why pixels go in that diagonal, but no why they always seem to crawl on the top-left, and never the bottom-right).

The dithering code can be found in the encoder, on github:

https://github.com/fstark/macflim/blob/main/flimmaker.cpp#L3...

If you have other dithering ideas, let me know. I am happy with the one I have, which matches what I was looking for, but we never know. Also, for the compressed version (the one with sound), the dithering have a huge impact on the ability to play on slow machines.

(Btw, I tried ordered dithering, but I have always found it awful looking. Maybe in motion it would fare better?).

4 comments

Another period-accurate approach would be Atkinson dithering, which is similar to Floyd-Steinberg but slightly simpler in implementation. I did a writeup about this technique a while back:

https://beyondloom.com/blog/dither.html

Cool, yeah Floyd Sternberg is definitely period appropriate!

This article on dithering made the rounds a few months ago, and was a fascinating read; the hilbert curve method at the end (Riemersma) might be a good fit and get rid of some of the line effects (if that's of interest). And the Atkinson error diffusion sounds like it even has some history in old macs.

https://surma.dev/things/ditherpunk/

There's a really nice blog post on video stable dithering in Return to the Obra Dinn, but in that case it's a 3d game, and they've got direct access to the scene geometry. I'm curious if there's a nice way to use video encoding pixel tracking vectors to reduce swimminess...

You made the right call.

I think there should be a clipping of the lower-grayscale coming into your filter. A black-point cut-off.

I think that would get rid of most of the "swimming pixels" in the very dark areas (would become completely black areas).

Some loss of detail of course in the dark areas ... but what details was there anyway?

Interesting. I tried some light posterization (splitting into discrete levels), but it made the image uglier. Your approach would make nice blacks and whites. Grays would still suffer, but it is an interesting take.
Floyd-Steinberg was usually the better choice for rendering an image.

It might be an option to offer Ordered by a menu option?

The dithering is performed by the C++ linux encoder. I could add it as an encoding stage option...