Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Spore allows player-created creatures to be shared by exporting a .png file. That .png is a photo of the creature, but if it's imported into the game, the creature's information (such as textures, size, and shape) also come with it.

How can I implement such a feature?

share|improve this question
4  
Should have a much higher score, that is a very interesting question. –  Arlaud Pierre Apr 1 at 8:19
2  
The alpha channel could be partially abused for this... –  Tobias Kienzler Apr 2 at 8:44
2  
Of use possibly: stackoverflow.com/questions/9542359/… –  logic-unit Apr 2 at 12:58
    
I think it's better to store this data in another file. In this file, there should be the name of the texture file that is related to an entity you want to have data stored. First for the sake of explicity (png format is for graphics - "Portable Network Graphics"), secondly: consider a situation where you wanted to store more images with an entity, you could simply add references to it from that custom file. You probably will have problem storing different images (differently sized, different depth etc..) in one PNG. –  lukasz1985 Apr 2 at 16:54
    
@ArlaudPierre, even if interesting, this questions shows really no effort in solving their own problem. By all means, it should actually have lower score! At least how things should theoretically be in StackOverflow (which in practice still aren't) –  Shahbaz Apr 5 at 17:53

4 Answers 4

up vote 33 down vote accepted

If all you truly needed was the PNG file, chances are they just simply added the information into the file. This is actually a practice of Steganography. A lot of the times, this is used to hide payloads or secret messages in things that are seemingly public facing. However, it is likely in this case that this method is what was used. Typical Stegongraphy will go out of the way to hide the contents, but there is no reason why one could not simply append the data out of the image in the end of the file and retrieve it.

Several tools encode this data for you, a google search brings up at least this and this.

A PNG has the byte signature $89 at the start, so it is possible that the information was inserted after the PNG structure itself and simply parsed by the SPORE game.

However, further research given by the other answers and a search on google reveals that Spore was actually using just a version of Stegongraphy to hide the information in the alpha bits. With this in mind, we can rule out the possibility of appended data or meta-data.

It should be noted that meta data is still a very viable choice, if the data is being parsed locally. If that information might be shared around the web or re-encoded, the export is not guaranteed to keep all your information. When pixel data is used, it can survive losless conversions without an issue.

share|improve this answer
1  
As far as I know, spore stored metadata inside of the PNG's alpha channel. –  Dudeson Apr 2 at 12:57
19  
Why use the alpha channel or steganography when PNG supports arbitrary metadata chunks? –  Russell Borogove Apr 3 at 2:20
6  
“A PNG has the byte signature "89" at the start, so it is very likely that the information was inserted before or after the PNG structure itself and simply parsed by the SPORE game.” If that was the case, then it wouldn't be a PNG file anymore. I.e. common image viewers wouldn't be able to display it. –  svick Apr 3 at 12:58
1  
@RussellBorogove one fairly good reason: if the PNG is decoded/encoded by something besides Spore, arbitrary metadata chunks are more likely to be ignored or lost than actual image data. Encoding the data in the image improves the likelihood that if you can see it, you can load it. –  Tim S. Apr 4 at 20:08
    
@svick Actually, I have played with a file which was both a valid PNG and RAR. The RAR header started after the PNG, and RAR extracters were fine. It can work fine the other way too. –  iamthepiguy Apr 5 at 10:06

The PNG format has support for more-or-less arbitrary metadata. The PNG standard defines a PNG file, essentially a series of chunks, some of which are required (and contain the image data). Others, however, are optional. For example, there's a chunk for storing gamma information or histogram data.

In particular, there is a tEXt chunk that can be used to store arbitrary key/value text pairs. This can be used to ship around any kind of arbitrary data you want, provided you can represent that data as text (which is fairly likely).

You will need a PNG library that allows you access and manipulate these additional chunks (such as the reference library), or you'll need to write one yourself. Then it's just a matter of choosing how to encode the data you want as key/value pairs. I'd suggest the following:

  • choose key names that are prefixed with your project's name or code name as a way of creating a crude "namespace" system and avoid potential conflicts with other application's uses of the data
  • don't try to store actual textures this way, store references to those textures that point within your game's own asset database
  • data such as creature or object size, weight, et cetera -- simple scalars, basically -- can be trivially stored

In the interests of making a more complete answer, I'll also point out that there is another approach (previously documented by the @Vaughn and @Alexis's answers): encode the additional data you want directly in your image pixels, distributing your data across the low-order bits of the color channels. This approach doesn't require the use of extra metadata, which means you can implement it entirely without relying on it or worrying about external programs incorrectly handling that metadata. It's also got a very high "cool" factor, and because you only use low-order bits the image will still look correct to the human eye. However, it does mean your image size is a primary controlling factor for the amount of data you can store; if you need more storage you'd need to allocate more pixels to the image.

As others have pointed out, this process is known as steganography.

share|improve this answer
1  
+1 I didn't know about that section of the file. –  Vaughan Hilts Apr 1 at 0:54
2  
One could simply send the data through Base64 and store it as a single value –  CodesInChaos Apr 1 at 8:58
22  
Why isn't this the accepted answer? –  Gerstmann Apr 1 at 13:44
9  
@da4c30ff As practical as metadata is, steganography has a certain spy-fantasy cool factor that's hard for our crowd to resist. If I were doing this myself, I'd use Josh Petrie's proposed method for scalability, but I'd be sorely tempted to use steganography to hide a checksum in the image itself to verify that the image and text belong to each other - not because this is useful or secure, but just because it's cool. ;) –  DMGregory Apr 1 at 14:46
1  
I updated the answer with a link to the standard for the text chunk; but basically, the text is interpreted as per ISO 8859-1 (8-bit, single-byte, Latin-1 characters). –  Josh Petrie Apr 3 at 15:14

The developer of Monaco actually made an excellent article on how both they and Spore accomplished this.

The basic summary of what they do is fairly simple:

  • Convert your data into binary
  • Convert your target image into a raw bitmap
  • Walk along the pixels of the image in some predictable pattern (they simply do left-to-right from the top-left corner).
  • Write one bit to the lowest order bit of each color channel of each pixel
  • Export the modified bitmap to png again

Simply do this in reverse to retrieve your data.

The basic idea behind the process is that there are a lot of pixels in an image, and the lowest order bits of each color channel don't make a big difference. In addition, about half of the bits you write will just be what the bit in the image already was. What you get back is essentially the right image, but with weird artifacts. He takes time to note that these artifacts are only really noticeable if you really crank the contrast/saturation and zoom in. He does have source images with lots of initial noise, though.

From the article:

Notice in the last image how there is a barely discernible horizontal line in the noise. That's the end of the level data. What this means is that I can actually fit all level data into a 265x120 pixel image, only using the least significant bit.

A TRICKY ADDENDUM:

Something I could do, and I believe that the Spore folks did as well, is actually use ALL of the color bits in pixels that are 100% transparent. Since those pixels are transparent, it doesn't matter what color you set them to.

I can't do this, however, since I am using the entire image, which means that I have no transparent pixels to work with.

Why favor this technique over just storing it in the metadata?

  • It's funner! :)
  • Services may mangle metadata (possibly as a privacy/security feature), but shouldn't mangle your png's pixels unless they have aggressive image-hosting requirements (looking at you, facebook). But if they're completely re-exporting your image there's nothing you reliably can do.

Extra credit: to reduce the noticeability of noise, you could use a PRNG with a fixed seed to select the pixels to modify. You could also only modify some of the color channels in a similar manner.

share|improve this answer
4  
There are steganographic algorithms that are more robust against image scaling/colour adjustment than the Monaco method. (Though they generally store data at a substantially lower density) One example is the watermarking used in World of Warcraft screenshots: ownedcore.com/forums/world-of-warcraft/… –  DMGregory Apr 1 at 14:56
    
@DMGregory Nice find! The precise algorithm you choose should of course be decided by your specific usecase (space, durability, secrecy, etc). –  Alexis Beingessner Apr 1 at 15:11
1  
As cool as this may sound, it's a bad idea. PNG images use lossless image compression; fiddling around with the low bits of the image will likely make the file bigger at the same time as it (slightly) reduces the image quality. Absolutely any information can be encoded as "text", so using a metadata chunk is the obviously-correct way to do this; someone fiddling image bits without actually needing steganography is just popping wheelies. –  dfeuer Apr 3 at 4:50
1  
@dfeuer - Apparently both Spore and Monaco were using game frameworks that have an asset loading pipeline that strips the .PNG down to a bare bitmap, so the metadata chunks weren't making it through. –  Russell Borogove Apr 3 at 17:41
1  
@dfeuer I did some naive tests. Metadata approach appears to add about 80% of the size added by the stenographic approach when writing 100kB of random bits to a 1920x1080px image. Tested on a blank image and desktop screenshot. Not exactly a catastrophic difference, but meatadata is certainly better (and more consistent) if you're really concerned over 40kB. Note that metadata was still pretty inefficient. I gained 181kB for writing 100kB of data! Could be room to optimize how the string is encoded or something. –  Alexis Beingessner Apr 3 at 22:37

I downloaded and examined a few Spore creatures from Sporepedia. From those I learned that:

  • The images contain no information in addition to the standard image data.
  • The stenographic data have been stored with no consideration for the image, one could imagine that the transparent parts were used exclusively, but they are not.
  • The storage use depend on the amount of information that needs to be stored, some of the images used only the least significant bit for data storage, some used the two least significant bits, some might use more.
  • The Spore format avoids using a bit on only part of the image, the least significant bit changes throughout the whole image, if the second least significant bit is used, it is used on the whole image. This is presumably done using random padding. This avoids a shift in quality that might be more disturbing to the viewer than the noise itself.
  • All four channels are used equally, the opacity channel is given no special treatment, thus some of the transparent pixels are slightly opaque while some of the opaque pixels are slightly transparent.

It is worth noting that this is just what Spore does, it is a method that puts simplicity before most other concerns.

The choice of using stenography rather than an additional data block means that the data will survive if the image is re-encoded, for instance by a website, though it will not survive scaling or Jpeg compression.

I think that the most prominent alternative is actually to only encode an id in the image, and let the actual data be stored on a central server where this id can be exchanged for the exact creature data. Such an id would be short enough that it could be encoded in a scaling- and compression-tolerant stenography format.

Possible simple improvements to the Spore format include:

  • Use only or prefer using the the colour values of transparent pixels, they don't make a visual difference.
  • Use the blue channel more and the green channel less, the blue colour has a lower perceived impact on the image.
  • Keeping the luminance of each pixel close to unchanged and encode the data in chroma, a little noise in this parameter is virtually undetectable to humans.
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.