This way the "glitching" happens inside the encoder algorithm, and then there's nothing to have to repair!
Reminds me a bit of a video codec technique to exaggerate the motion frames and compression ala "datamoshing".
Keyframes are removed which leaves only information from the previous frame to be updated by motion frames. Than update/motion frames are reiterated sequentially which creates an effect that just further saturates the previous frame and looks like a fluid melting effect.
in use: https://www.youtube.com/watch?v=mvqakws0CeU
how to via ffpmeg: https://www.youtube.com/watch?v=tYytVzbPky8
The approach is simple: just mess with the base64 string.
(more info: http://blog.soulwire.co.uk/laboratory/flash/as3-bitmapdata-g...)
The other image format that's worth knowing is TIFF, because it's an insanely simple and flexible format to write out if you don't have access to a library. It lets you re-order the image data by tiles or scan lines, and lets you put various tables almost anywhere in the file, which makes it great for outputting large images from a parallel renderer: you can chop it up however is suitable for the algorithm, write out the parts to disk as you get them, and then write out a table at the end describing the order at the end of the file, without having to seek.
More details of a similar case: http://morris-photographics.com/photoshop/articles/png-gamma...
These days it's basically "what libtiff supports".
As an experiment I just opened a screenshot in Preview.app and exported to PNG with and without an alpha channel - adding alpha makes it 335KB vs 300KB. Since the alpha contains no information, there's no excuse for it to be 30KB compressed!
ffv1 or your favorite video codec with a lossless mode will produce much smaller files and decode much faster than png.
Now you've got me curious what the compression ratio would be if you just re-ordered an image's pixels using a Hilbert curve (so that in e.g. a 100x100 image, the first 100px scanline contains the first 100px of the Hilbert path through the original image) before passing it to PNG for compression.
• Lenna.png (http://i.imgur.com/pPNbiyG.png): 475KB.
• Lenna.Hilbertized.png (http://i.imgur.com/kU8C3yG.png): 709KB.
Clearly, not a good idea, at least for photographic sources.
In this case, PNG's filtering makes it kind of 2D-aware, so that probably works better on the original. But if you tried splitting it into 8x8 blocks, then predicting each one from the left-upperleft-upper neighbors, well, you'd have the basics to modern DCT codecs.
Disregarding the cruft of headers and other file format overhead, there would be a direct relationship between the size of a PNG image, and the raw, uncompressed row-level data zipped up and handled in a similar way.
So first of all this whole article is essentially about the "filters" that are used to encode the data more efficiently based on the surrounding data, before it's passed to deflate. Basically compute some kind of a delta from the pixel compared to the pixel up of it, left of it, or a combination of the two, with the deltas generally compressing better than the raw data would have. That's already a big difference to compressing each row separately.
Second, the deflate compression does not happen individually for each row. It happens individually for each IDAT block, but those blocks can be of fairly arbitrary size. Using a separate IDAT block for each row would seem very odd. (Can you even use filters in that case, or does the state reset with each new block?)