Teaching IE8 a bit of Canvas with DataURIs: ducie8.js

Demo Link (ducie8.js uses a native Canvas implementation if found, so you can only really test it in IE8)

I’m still looking for ways to apply this to previous IE versions (which is pretty hard considering that there are no DataURIs, just a bunch of bugs which influence each other is such ways that they might be able to provide similar functionality), but even only with IE8 compatibility this could prove valuable, seeing as IE8 is the highest version that you can ask IE users to update to without a change of operating system or browser.

I was exploring DataURIs in IE a while back with Joseph Huckaby when he published his article on palette animation, since altering the palette in a BMP data url is faster than doing it manually for every pixel through JS and works in IE8 as well. We gave up when we realized that WebKit would simply leak all memory associated with our DataURIs and never release it (2GB can pile up quite quickly if you use about 20MB per second). I still have the source around if anybody is interested, but I’m afraid I don’t have any public domain images to put together a demo.

Anyway, this didn’t really lead anywhere, but it gave me the idea to try emulating Canvas with BMP DataURIs. Now, DataURIs in IE8 are severely limited. Most notably they can’t go beyond 32kb (in fact, no URL can in IE8). The solution is pretty obvious: Use multiple small ones (we already had to do that for the palette animation). Other than that you need a base64 encoder since IE8 doesn’t have an btoa() function and that’s pretty much it.

Of course, when it comes to actually implementing something like that things are never simple and there are a few obstacles that ducie8.js will very likely never overcome. Like the facts that trying to emulate a 32bit Canvas with transparency would require using PNG DataURIs, which in turn would mean that we can’t recalculate the base64 value for an individual pixel (since base64 strings can only be split every 24bits) and would have to recalculate the checksum for the PNG on every change (maybe there are some bugs that allow us to get away with a corrupt checksum, we’ll see). Or that drawImage won’t be able to access normal HTML Image elements (since we can’t access their pixel data), but will require a special Image-like element which will internally use XMLHttpRequest and responseBody (and will only be able to read uncompressed formats unless somebody manages to do an incredibly fast PNG decoder in IE8). Or that we never know when the JS has finished drawing a single frame (which is why ducie8.js right now uses a timeout and updates the BMPs with 1 frame delay). Or that it will never be fast enough for anything but Minesweeper (it’s still surprisingly fast considering that the code is still pretty unoptimized). Or that you have to use the setProp method for setting properties since we often need to run a setter (ducie8.js adds setProp to a real Canvas implementation if found, so that you can at least use the same code for both).

What it can do is provide Canvas in cases where using the server is simply not possible or very undesirable, but the result is mostly static once rendered. Graphs. Buttons. The current version of ducie8.js is very light on features. width, height, fillStyle and fillRect. That’s it. enough for a simple drawing program to test the speed and the architecture, but little else. However the vast majority of Canvas features could be implemented in a pretty straight-forward way and I’ll be happy to set up a project if there’s any interest.

P.S. I should probably stress that the current version uses a triple-cache (nummeric pixel data > base64 pixel data > data url) that’s actually very slow for solid rectangles and really meant for per-pixel access with transparency. So don’t think the current speed is the limit: Internally these are all Arrays and can be made a lot faster by using Array methods instead.