For StarWright, my super-awesome spaceship building game I'm making, I added more awesome to how spaceship designs are saved to files. Take a look at this PNG image:
If you download the file to your computer -- and of course have the latest version of StarWright -- you can simply load that PNG straight into the game and it will be fully playable and customizable. I'm hoping this will make ships easier and more fun to share, and it has the added bonus that I don't need to generate an in-game preview of the ship.
There's no fancy image-analysis going on. I'm simply embedding the ship data into the least significant bit of each of the red, green, and blue color channels of each pixel in the PNG (which is 32bpp ARGB). That's 3 bits per pixel, which means a 512x512 image can store about 98KB of data, which is more than enough for the largest ship I currently allow. Since only 1 very-insignificant bit is used per color channel, it's very difficult to see any visual difference. This is a kind of "Steganography" (hiding one message inside another), and Spore and the upcoming game Monaco use the same technique for creatures and custom levels.
The basic process in StarWright works like this:
- Save the ship layout to a proprietary data format.
- Compress the data using GZIP. Since the data is highly repetitive, I get about a 20:1 compression ratio.
- Take a 512x512 screenshot of the ship at 32bpp.
- Embed the compressed data into the least significant red, green, and blue bit of each pixel in the screenshot. I could use the alpha channel as well but that'd probably be more visually noticeable.
- Save as PNG! Done!
There are some drawbacks to this method, but nothing really major:
- Save files are much larger than plain compressed text files. But the largest ship I have is still only 116KB on disk.
- Any alterations to the PNG file will almost certainly corrupt the embedded data.
- Theoretically the ship data may not fit in the image, but I can always increase the image size or use more bits per pixel. At first I was using 1024x1024 at 6bpp which was way more than I needed.
- Supposedly embedding already-compressed data inside a PNG will reduce the PNG compression, but I've seen virtually no file size increase vs screenshots without embedded data.
Okay, I'm done nerding out now. ;-)