Log In  


I'm not sure if this was a style choice, but the PNG format is a container format and supports ancillary tags for proprietary meta data. This is how Spore stored creature data inside the picture.

This will give you more flexibility in the future when it comes to storage size, color depth, and not losing fidelity when it comes to the screenshots in the container.



Interesting, but I think I know the reason zep made it the way it is now: Steganography is just easy and can be done by just modifying texture data, then saving it. You don't need to figure out how to use those metadata (which may be cut out by some software during transfer to webserver or imagehost) plus if that metadata would be used, webplayer wouldn't work anymore as you can't access it from under JS.

And frankly, with Pico-8's impressive color palette of just 16 colors, and the fact that you really can't see the difference between say, RGBA(255,0,0,0) and RGBA(253,0,0,0) (it uses two least significant bits of every channel byte which gives you 1 byte per pixel) means that I wouldn't worry about "losing fidelity when it comes to the screenshots in the container."


Sadly, I'm fairly certain he's doing full PNG decode inside of javascript from the raw file. Javascript makes it basically impossible to get the binary value of the alpha channel of an Image object. The only real way around it is to decode it in software, and rip the data out by hand.

Note: Javascript uses the same permissions model for accessing pixel data from an Image object as it does for using an XHR and setting the response type to array buffer.

as far as the webhosting thing, I don't know of any webhosts that strip down your PNGs on upload, and most of the local tools can be configured to leave specific chunks in the file. This is obviously something that could have greater ramifications though.


I know imgur strips down files of any unnecessary data. Prior to that update that added animated gifs to the site, it even made all gifs static.


Oh dang, that sucks. That explains the giflib credit in the manual.


No, I meant imgur.com, not pico!


"Javascript makes it basically impossible to get the binary value of the alpha channel of an Image object."

This is not true. You can write the image to a canvas and run getImageData() on its 2d context to get the individual channel values of an image, 8 bits each, 4 channels. Not that the PNG decode isn't possible...

You're right about the cross site scripting thing, but it doesn't apply here since all the carts are hosted on site.


Spore doesn't store creature data in ancillary tags.

It compresses the creature data (XML), scrambles and obfuscates it, and stuffs it in the low-order bits of each pixel (4bpp @ 128x128 gives a limit of 8KB compressed XML).

Here's an (old!) decoder for it: http://pastebin.com/SXBBZqJ8


Anaander Mianaai gets revenge in... Ancillary Chunks.


@Rhys: Sadly, you can only draw an Image object to the canvas using the drawImage call, which uses the alpha channel to blend the pixel data onto the surface. Trust me, I've fought long and hard to try to get the raw pixel data from a remote loaded PNG file. You could probably use some creative math to extract figure out what the alpha value was when it was blended in, but it wouldn't be viable for the screenshot section of the picture.

@Scaevolus: Thanks for the info! I think I was just misinformed, or playing off old assumptions (I used PNG aux data in an old flash project)

Has anyone checked if the zTXt block gets removed by imgur? some programs use that to store copyright information, and should probably not be stripped by CDNs. If that is still there, it could totally be used to store a normal p8 block.


Works perfectly if your canvas starts completely blank (0,0,0,0 all channels) which is like, the base setting? Is your canvas starting filled white or something?


@Rhys: Nope. It was default clear. Maybe that behavior is browser dependant?

	fromImage (url, cb) {
		var img = new Image();
		img.src = url;

		img.onload = function () {
			var cvs = document.createElement("canvas");
 			cvs.width = img.width;
			cvs.height = img.height;

			var ctx = cvs.getContext("2d");
			ctx.clearRect(0, 0, img.width, img.height);
			ctx.drawImage(img, 0, 0);

			var sten = new Uint32Array(ctx.getImageData(0, 0, img.width, img.height).data.buffer);
			cb(sten);
		};
	}

That's what I was doing, if you know something I don't.


Remove clearRect thing and watch the magic happen.


@darkhog: Still no workie. Returns 0x00000000 for the first RGBA always. I believe my browser might be doing a premultiply on the RGB channel. Either way, I'm derailing the forums (LUA!)



[Please log in to post a comment]