Sketch This Page! Image Processing with the Canvas Tag
March 26, 2009 – 10:46 pmI have been quietly impressed with the progress web browsers have been making in recent years towards the goal of supporting a wide variety of applications. The promise of web-apps rivaling traditional desktop applications seems within reach after nigh-15 years of ballyhoo. Most recent browsers have extremely fast Javascript support and highly optimized DOMs, allowing a good level of interaction.
Of course, there a times when moving <div>s around just doesn’t cut the mustard. The canvas tag is not well used but is nothing less than a surface you can draw on using Javascript. It supports all the normal primitives (lines, arcs, fills, etc) and allows (indirect) access to the pixel data. While some people (eg: Project Bespin) are using the canvas tag in to offer extended functionality, I am busy fooling around.
Check out the fruit of my labour – Sketch This Page!.
It’s a Javascript bookmarklet that replaces each <img> element in a page with a same sized <canvas>. It works by copying the image to a temporary canvas, extracting the pixel data for some hacky post-processing, and then blatting the pixel-data onto the final canvas. The Javascript could certainly be better, but it works well enough and I am impressed with the speed.
The biggest flaw is that browsers will not allow Javascript to access the pixel data of images that are loaded from a different domain than the main page. This is a great idea from a security standpoint, but it does limit the usefulness of the bookmarklet. It would be great if Sketch This Page! worked on sites like Flickr, but sadly it is not to be.
For those interested, here is the function that actually dithers the image. I was going for a hatched look with the diagonal lines.
{
var srcContext = src.getContext(”2d”);
var dstContext = dst.getContext(”2d”);
var srcImageData = srcContext.getImageData(0, 0, src.width, src.height);
var dstImageData = dstContext.getImageData(0, 0, dst.width, dst.height);
for (var y = 0; y < dstImageData.height; ++y)
{
for (var x = 0; x < dstImageData.width; ++x)
{
var index = (dstImageData.width * 4) * y + (x * 4);
var g = (0.30 * srcImageData.data[index]) +
(0.59 * srcImageData.data[index+1]) +
(0.11 * srcImageData.data[index+2]);
if (g > 200)
{
g = 255;
}
else if (g > 150)
{
if (((y % 6) – x % 6) == 0)
g = 0;
else
g = 255;
}
else if (g > 75)
{
if (((y % 4) – x % 4) == 0)
g = 0;
else
g = 255;
}
else
g = 0;
dstImageData.data[index] = g;
dstImageData.data[index+1] = g;
dstImageData.data[index+2] = g;
dstImageData.data[index+3] = 255;
}
}
dstContext.putImageData( dstImageData, 0, 0 );
}
Related posts:
- Safari 4 is Pretty Good Safari 4 has been out for a couple of days...
- The HTML5 Video Tag’s Fatal Flaw Back in the day there was no standard way to...
- WordPress Upgrade Time I have just upgraded to the latest version of WordPress....
Related posts brought to you by Yet Another Related Posts Plugin.