The challenge was to write a short script in a scripting language of choice that takes in an image of mixed up uniform sized shreds and pieces them back into the unshredded and reconstituted image. That means the original image was divided into an even number of columns of same size and than those columns were shuffled randomly. Additionally the script should auto-detecting how wide the uniform strips are.
Before I started on my solution, I made some quick assumptions to simplify things:
- I wanted to code it in Ruby, simply because it's a great language and I'm quite productive in it.
- I wanted to define a simple distance measure which can be used for auto-detecting the column size and putting the shredded image back into its original state.
- I used ChunkyPNG, a pure ruby library for read/write access to PNG images.
- This solution was only tested with a few pictures. It is by now means perfect, but just a quick hack, which I had fun on. Feel free to improve or suggest improvements to it.
Key to my solution is a simple distance measure slightly based on ΔE, which simply is a metric for the difference or distance between two colors. But instead of using LAB color space I adapted the measure for the RGB color space. My distance measure takes two 1px wide columns end compares pixel to pixel from top to bottom. The sum of different pixels for a certain pair of columns is the distance between these two. To ease the result a little bit, a threshold is used. This threshold was obtained by trial and error using a few test pictures, like every good programmer would obtain it (^_^). However, please note, taking this measure makes it difficult to unshred images which are not very saturized. It could be improved by increasing the width of the 1px wide columns for comparison.
This distance measure is used in shred_with function, which compares 2 neighboring columns until two columns are found, which distance is greater than
Finally the unshred function crops the image into equally sized shreds. For each shred the first and last column of pixels are stored into respective arrays. Then every last column is compared with every first column in terms of their distance. The pair with the least distance are combined first. Then the best matching next shred is either appended to the left or to the right until no shreds are left.