Lossless Image Compression in O(n) Time (2021)
phoboslab.org
phoboslab.org
QOI: Lossless Image Compression in O(n) Time (2021-11-24, 293 comments) https://news.ycombinator.com/item?id=29328750
The QOI File Format Specification (2021-12-20, 54 comments) https://news.ycombinator.com/item?id=29625084
QOI – The “Quite OK Image Format” for fast, lossless image compression (2021-12-23, 103 comments) https://news.ycombinator.com/item?id=29661498
QOI – The Quite OK Image Format (2022-04-02, 97 comments) https://news.ycombinator.com/item?id=30885668 [after the official domain has been set up]
I strongly disagree with characterization that JPEG is overcomplicated, especially in a controlled situation where you only need to support files you encode yourself (as is the case with QOI), and not edge cases like Adobe's CMYK extension.
JPEG's design is brilliant for the level of compression it's capable of. libjpeg API is crufty, and C dependencies are a pain, but you can use other implementations and languages.
At some point, I was asked to write code to save images on live systems to be downloaded and used for... CV stuff. Also, the images had to be (although weakly) encrypted for IP reasons. The issue being that those cameras run at 200fps when there's anything of interest and use their compute to do image processing. The flash memory used also isn't made for this kind of write speed.
All that is to say: JPEG is insanely efficient. It takes a moment to compress the image, but only encrypting 10% of the data saves a lot more and the flash memory can keep up way longer than with raw images.
I had to generate some difference images though to convince some CV and management people that we don't need raw images. If our analysis results would depend on a dozen pixels not being off 1-2 gray values, it's broken. There's more noise in every single image than JPEG-induced errors.
TBH that sounds like a job for a video codec.
The discussion is not about the quality of the API, but the amount of work an actual machine will have to do to compress/decompress.
I think the author is trying to capture an idea of “simple”, but has misidentified that as O(n). Any algorithm which operates in a single pass on a stream of data and has a fixed upper memory usage is O(n).
Most other compression implementations also use a hash table, at least on the faster settings. They may switch to something like a hash chain on slower settings, but that doesn't really change asymptotic complexity as it just evaluates more matches.
I don't think any implementation does a straight linear search across the window, as that's just stupidly slow, though maybe a "give me the best compression, I don't care about speed" compressor might.
LZW uses a hash table too (traditionally with a prime based capacity)
I think you oversimplified in the other direction? An algorithm can make 1 pass over data (say it's n bits), then flip through all possible states of those n bits, taking exponential time. Or if you consider that to violate having a "fixed" upper bound (not sure this is meaningful in any useful sense, especially given it would probably need at least log(n) bits to know how far it's read its input), consider that it can even loop infinitely if it wants to.
How do you do that in one pass?
You are right an algorithm doesn't have to be O(n), as it could enter an infinite loop and never finish.
Compare with algorithms that would like to be omniscient but make decisions at every step in order to produce streaming output and/or to forget old state and old inputs, like Viterbi decoding.
While porting to wasm, using something like stb_image became a little complicated, so I wrote a png-qoi converter, and then use the qoi assets in the game.
Writing a qoi decoder is a fun exercise, though i think most languages have their implementations already.
For me, an interesting use-case would be streaming webcam video from my Raspberry Pi.
I have some Raspberry Pi Compute Module 4, and some Raspberry Pi Camera Module 3. Along with some various USB webcams.
I would love to be able to stream video from my RPi CM 4 with the camera 3 modules connected, at the highest possible resolution and frame rate.
Beyond that I would like to stream to many clients at once without too much overhead.
But the initial goal would be to get something with top resolution and frame rate even for just 1 client.
And for that this kind of thing sounds interesting.
1. That an image is expected to be decompressed as a whole, and
2. That an efficient (de)compression is possible with generic compression algorithms.
Both are false. Even PNG does its own filtering, a pretty rudimentary model but much better than just DEFLATE. QOI is much better in this regard because it has a (fixed and also rudimentary) model; it was a clear demonstration that modeling is much important than entropy coding.