4 ms·
I’ve spent a lot of time thinking about this because of the Playable Quotes [0] project that I worked on with @rndmcnlly. First off, I love embedding data into
by jf 5y ago
I’ve spent a lot of time thinking about this because of the Playable Quotes [0] project that I worked on with @rndmcnlly.
First off, I love embedding data into images. It’s surprising how useful it is to do this! The main reason that I like embedding data into an image is because you get a “thumbnail” essentially for free.
In the future, I hope to see a more widespread use of this technique, especially for images that are the output of a set of data. Imagine a chart with the source data embedded into it! Or an SVG embedded in a PNG.
This is what we did for Playable Quotes, each quote is a PNG of the framebuffer at the time the quote was started. All of the data needed to play that moment in the game is embedded into the PNG.
That said, there are at least three main approaches that can be used to embed data into a PNG. Each has various trade offs:
The approaches are as follows:
1: Concatenate the PNG with a ZIP file
2: Use PNG chunks (this is what is done in the article)
3: Embed data using a stenography
Here are the pros and cons of each approach:
Option 1: Concatenate the PNG with a ZIP file
This is a clever technique because (in short) PNGs have length information in them and zip software will attempt to read files from the end of the file if they can’t read from the start.
Pros:
- Super easy to do: “cat original.png file.zip > new.png”
- Easy to work with. You can extract data by using the “zip” command or renaming the new.png to new.zip
Cons:
- The data is lost when sharing the image. Most image hosts and even some chat programs will strip out the zip data from the image.
Option 2: Use PNG chunks (this is what is done in the article)
This approach is nice and clean, as the PNG specification explicitly allows for this. In essence, a PNG is a little key/value database where the keys are four ASCII printable bytes.
Pros:
- Complies with the PNG standard
- Data is usually maintained, but not always!
Cons:
- Requires special tooling to use. Standard PNG command line tools don’t offer easy ways to get chunk information out of PNGs
- The extra chunks are SOMETIMES removed. Especially by services like Twitter which will try and optimize the images before hosting them
Option 3: Embed data using a stenography
This is the approach that PICO-8 uses for its game “cartridges” and what we ultimately used for Playable Quotes
Pros:
- The most durable way to keep the data attached to the image
Cons:
- The amount of data you can store is limited by the size of the image
- Special tooling is needed to extract the data
In general, my personal favorite is option 1, as it is the most useful. However, it’s sadly not a practical solution to use in a world where the tools we use to share images (Twitter, Imgur, etc) modify the images in transit.
Footnotes:
0: https://tenmile.quote.games https://tenmile.quote.games
- lifthrasiir 5y agoThere are three variants of option 2: - 2a: Use a new ancillary chunk (the OP's solution, here atCh) - 2b: Use officially dedicated PNG chunks (tEXt, zTXt, iTXt; draw.io/diagrams.net approach) - 2c: Put extra data to IDAT after the last DEFLATE block (most famously used by HTML-PNG polyglots, common in size-limited JavaScript demos) I think 2c is most robust among those options, because to my knowledge implementations that recompress IDAT without actual transcoding are rare. 2c does result in some libpng warnings [1] but doesn't seem to cause real-world issues. Also, special tooling requirement of option 2 can be slightly reduced by adopting ZIP approach: you can put magic bytes that are long enough and unlikely to appear by chance, so the reader can simply look for those bytes instead of parsing PNG chunks. This approach is most appropriate for options 2a and 2b (IDAT can be splitted, so there is no real guarantee that magic bytes remain intact) and it is recommended to reuse the existing PNG chunk structure, so that first 4 bytes of magic bytes are also PNG chunk types. It wouldn't fix the writer complexity though. [1] For example, https://github.com/glennrp/libpng/blob/a37d483/pngpread.c#L730-L735 https://github.com/glennrp/libpng/blob/a37d483/pngpread.c#L7...
- sp332 5y ago*steganography
- TAForObvReasons 5y ago> zip software will attempt to read files from the end of the file if they can’t read from the start. Technically all readers are supposed to start from the end of file (to find the end of central directory). Some readers cheat and others like `funzip` use heuristics to scan for the first valid file.