Experiments in image corruption

Written by Ash on Filed in programming Tags: rust images pc glitchart

I recently saw a post from Daniel Aleksandersen about bitrot in modern image formats, which included a method to quantify how different a corrupted image is from its original. Daniel used random bitflips, but this got me thinking about glitch art - what if we could generate every possible corrupted image and quantitatively state which ones are the best?

The method

Okay, so let’s just generate every corruption of some image file and run it through that algorithm. By “corruption”, I mean bitflips, so for a.. randomly selected test image:

A Mario Kart 8 promotional image

That’s 173KiB, so 1.417×10^6 bits, which is.. how many bitflips?

A Wolfram Alpha calculation showing that 1.417×10^6 factorial is 1.869×10^8101099

Nice. Given that the DSSIM algorithm used in the original post, which I would also like to use, takes a few hundred milliseconds to process an image, I’m sure we’ll get some rad glitch art at around the time of the heat death of the universe.

Clearly we need a better strategy, so how about only flipping one bit at a time?

bitflipper - a program to generate somewhat interesting glitch art

bitflipper is a program I wrote to take an image, test each possible bitflip (each file only differs from the original by one bit), and see if dssim thinks it’s interesting. You can set the starting and ending range of the search, and a threshold for dssim. Any images deemed cool get saved for you to look over later and pick out your favorites - thanks to the analysis, there’s no duplicates of the original or plain corrupt images in the output folder.

Since dssim is a Rust library, I also wrote bitflipper in Rust, a language I’ve been trying to learn more of anyway. I quite liked the library ecosystem and being able to Just Add Stuff (which can be quite the ordeal in C/C++, even when using submodules), though dealing with different kinds of Results and ? was a bit strange and felt ugly. I’m sure there’s some secret technique I don’t understand yet.

Once all was said and done though, the code only ended up being 150 lines in a single file, including guff like parsing the commandline arguments, which is pretty cool considering the complexity of what it actually Does. I like!

How well does it work?

Running on the above test image on default settings for an hour or so, bitflipper wrote out a few hundred images. Since each bitflip is sequential, they tend to cluster together in different categories, with one corruption getting more and more intense or moving around in the image.

Let’s look at some of the results! Remember that each of these files only differ from the original JPEG by a single flipped bit.

“Classical” JPEG corruption

This is the kind of stuff you expect to see when you hear about a half-overwritten image file or a errant cosmic ray corrupting some photographer’s collection. It’s pretty cool, but a bit overdone.

Note: Some of these .jpg files are “unstable” and render differently on different systems. Where I’ve noticed instability, the embedded images are re-encodes of how they appear for me, but you can click to see the original .jpg.

An image with large, horizontal, coloured bands covering the entire frame An image that vaguely resembles the original, with colours affected in large bands and pixels offset left or right. The squid eye's from the original are still visible An almost unrecognisable image, with maybe the vaguest outline of the original in some places, but is otherwise dominated by striking colour bands

Weird Macroblocking Stuff

In these ones, the structure of the JPEG file itself starts to show itself, with unique corruptions inside each compression block. There’s some unique effects here that I haven’t seen before!

An image with increased contrast and strange artefacting in a grid shape An image with even more contrast, blowing out the blacks, and with each grid square almost a single colour An image with vertical artefact lines in each block, with pixels being shifted up or down within each column An image with horizontal bands of corruption and noise, making the image hard to make out behind the artefacts

Colours

These ones play with the intensity of colours, almost making straight lines look curved. Very cool [smiley with a content expression emoji]

An image with significantly oversaturated colours, causing a bloom effect around some objects A completely absurd image, with completely nonsensical colour information in a grid. The brightness is preserved, however, so the features of the image can still be made out

Lastly, my absolute favourite image:

An image mostly in grayscale, with some shifted pixels being a subtle red or cyan, similar to a chromatic abberation effect

Let me know if you have a go and get cool results, I’d love to see them.

Until next time! [CRT showing a colour test pattern emoji]

I've disabled comments until I can come up with a good, privacy-respecting way to implement them.