HTML5 Collage Creator


This week I started playing around with colour analysis in html5. I used it to create an image collage of your Facebook profile from your Facebook friends photos. I was quite surprised at how well it preformed particularly on mobile. As its nearly Christmas I managed to role this experiment into an interactive Christmas app. You can check it out here.


Creating this experiment was surprisingly easy. Here is an explanation of the technique.

First you need to load all your photos you want to use to create the collage into a Canvas element. One annoying gotcha of Html5 is that you cannot write images from a different domain to the Canvas due to security limitations. To get around this I used a simple php proxy to load the images via the local domain. Once loaded you can then get the average colour of the photo. To get the average colour I re-wrote some Flash code I had for doing this and modified it slightly to work with Canvas pixels. The photos are then stored in an array along with their corresponding average colour.

Next I load your Facebook profile pic into the canvas. Instead of getting the average colour of this image, I loop through every pixel of the image and get the pixel colour. This colour is then matched with the closest average colour from my previous list. Again is some Flash code which I re-wrote. Then I use easeljs to create a larger canvas image. The image is redrawn where each pixel is represented by the a friend image with the closest matched average colour to the pixel colour.
Finally the zooming effect at the end is achieved using a CSS3 transition. Interestedly this transition runs much faster when apply to a canvas element then when applied to a image element.

If you are interested in the code for this experiment you can view the javascript on the site as its un-compressed. The colour functions are also available below.

function getCanvasAverageColour(canvas, width, height) {
    var context, data, r,g,b, len, color = {r:0,g:0,b:0};
    context = canvas.getContext('2d')
    try {
        data = context.getImageData(0, 0, width, height);
    } catch(e) {
        alert('security error, img on diff domain? '+e);
        return color;
    len =;
    for (var i = 0; i < len; i += 4) {
        r +=[i];
        g +=[i + 1];
        b +=[i + 2];
    color.r = ~~(r / len);
    color.g = ~~(g / len);
    color.b = ~~(b / len);
    return color;
function getCanvasPixelColors(canvas, width, height){
    var bmp = canvas.getContext('2d').getImageData(0, 0, width, height);
    var pixels =;
    var colors = [];
    var i = 0;
    for (i = 0; i < pixels.length; i += 4) {
        colors[i / 4] = {r:pixels[i],g:pixels[i + 1],b:pixels[i + 2],a:pixels[i + 3]};
    return colors;
function similarColor( rgb1, rgb2, tolerance)
    tolerance==null? tolerance=0.01 : tolerance

	tolerance = tolerance * ( 255 * 255 * 3 ) << 0;

	var distance = 0;

	distance += Math.pow( rgb1.r - rgb2.r, 2 );
	distance += Math.pow( rgb1.g - rgb2.g, 2 );
	distance += Math.pow( rgb1.b - rgb2.b, 2 );

	return distance <= tolerance;

See more , ,


There are no comments yet...Kick things off by filling out the form below.

Leave a Comment