Compressing javascript into PNGTags: javascript — 10th of September 2010

What?

PNGStore is all about embedding your javascript/css file into a PNG file, and then opening it back up to read the data. Since PNG uses lossless compression our PNG file should be smaller then the actual javascript file and still remain intact once extracted. Once I read up on this neat trick from PNGStore I just had to give it a shot for the js1k competition.

From javascript to png base64 (Python using PIL):

You can do better compression by not wasting the 8th bit, since visible ascii only requires 7bits
import Image, base64, StringIO
def pngstore(input):
	input = open(input, "r").read()
	pixels = len(input) / 3
	
	img = Image.new("RGB", (pixels, 1), (0,0,0))
	
	bytes = []
	for character in input:
		bytes.append(ord(character))
		
	while len(bytes) % 3 > 0:
		bytes.append(0)
			
	for x in range(0, pixels):
		img.putpixel((x, 0), (bytes[x*3], bytes[x*3 + 1], bytes[x*3 + 2]))
		
	output = StringIO.StringIO()
	img.save(output, format="PNG")
	output.seek(0)
	return base64.b64encode(output.read())

From png base64 to browser (Javascript)

var img = document.createElement("img");
img.onload = function {
	var canvasContext = document.createElement("canvas").getContext('2d');
	canvasContext.drawImage(img, 0, 0);
	var data = canvasContext.getImageData(0,0,img.width,1).data;			
	var result = [];
	for (var i = 0; (i < data.length); i += 4)
	{
		for (var i2 = 0; (i2 < 3); i2++)
		{
			result.push(String.fromCharCode(data[i + i2]));
		}
	}		
	eval(result.join(''));
};
img.src = "data:image/png;base64,BASE 64 data goes here";

Summary

Its useless in a 1k competition, the overhead for reading the data back is just too much. And also the better your code is minified, the worse the PNG compression ratio gets. In the js1k competition external files were not allowed, so to load a png file you have to use Data URI and compress the png data into base64, this takes away all the good work the PNG compression does. If you however can use external images or your competition has a higher bytes limitation this might come in handy.

Usage in real world applications

I wouldn't. Let the web server compress it. Older generation of browsers do not support canvas so well and png compression uses the same compression technology as your web browsers. So there is no good reason to use png compression if you can compress through web server.