raw code

It was once again one of those nights where I hacked like on drugs with no end in sight. Sure, 5 years ago you had loved me with such a project, but in times of HTML5 with the canvas element it is hard to impress you. So take it as proof of creating client side images without canvas, SVG, or server side rendering and AJAX processing.

But how is this possible? Well, I've implemented a client-side JavaScript library like libpng which creates a PNG data stream. The resulting binary data can be appended to the data URI-scheme using Base64 encoding.

The next step would be implementing shapes and forms to allow an easier image manipulation, but I think this is not necessary. I just wanted to learn the PNG file format, who wants to use the library can implement the rest by himself. At the moment it's only possible to write colors to a certain pixel position. I do not recommend a production use of this lib without input validation. The class is really spartanic, but it works :)

But enough of preface, let's dig a little deeper on how we can use the library. I wrote a little example which looks like this:

The implementation is quite simple, but there is still no setter method to set a pixel. You have to access the internal buffer directly with

obj.buffer[obj.index(X, Y)] = obj.color(r, g, b, a);

The complete source of the above example looks like this:

var p = new PNGlib(200, 200, 256); // construcor takes height, weight and color-depth
var background = p.color(0, 0, 0, 0); // set the background transparent

for (var i = 0, num = 200 / 10; i <= num; i+=.01) {

	var x = i * 10;
	var y = Math.sin(i) * Math.sin(i) * 50 + 50;

	// use a color triad of Microsofts million dollar color
	p.buffer[p.index(Math.floor(x), Math.floor(y - 10))] = p.color(0x00, 0x44, 0xcc);
	p.buffer[p.index(Math.floor(x), Math.floor(y))] = p.color(0xcc, 0x00, 0x44);
	p.buffer[p.index(Math.floor(x), Math.floor(y + 10))] = p.color(0x00, 0xcc, 0x44);
}

for (var i = 0; i < 50; i++) {
	for (var j = 0; j < 50; j++) {
		p.buffer[p.index(i + 90, j + 135)] = p.color(0xcc, 0x00, 0x44);
		p.buffer[p.index(i + 80, j + 120)] = p.color(0x00, 0x44, 0xcc);
		p.buffer[p.index(i + 100, j + 130)] = p.color(0x00, 0xcc, 0x44);
	}
}

document.write('<img src="data:image/png;base64,'+p.getBase64()+'">');
Download PNGlib source

The source of the library is based on the libpng and libgd library as well as the PNG documentation. The implementation is licensed under BSD, so feel free to modify and use it in any way.