A Flickr Mosaic

There are times you are going back home with an idea in your head, and you know you won't go to bed until you've come up with it.

Vincent Van Gogh - Sunflowers [oil on canvas, 1889 - jpegs on , 2010]

Well I was coming back from university thinking about those photo mosaics made up of little pictures as tiles, which resemble the actual subject; my idea was to browse the internets for the billions of pics it holds and to make the mosaic of the picture I wanted.

But what to ask for? My assumption was to inspect original picture pixel info locally, calculating the mean color of all the tile areas, then to search for pictures with that features. I managed to make that analysis in a canvas + processing.js framework inside my browser, and it worked. I saved my color palette matrix in hex, and I proceeded for gathering real pixels.

First, I thought about querying googlepics or picasa, hoping they had info about any color cached, but just a bunch of most common ones were classified. Then I ran into Multicolr Search Lab and things suddenly turned perfect - tell it a color, he returns pages of colorful pics!

But how to access such precious data? First I thought about parsing the page, but it would have been so painful for the system - 20x30 tiles = 600 full html pages to parse? No way sir. I firebugged a bit to inspect the http requests, and I found that data was actually retrieved through JSON - so I made my own query url, and called it from my script.

End of the story? Problems come in waves, even if you are doing a totaly unuseful stuff like this. AJAX calls have restrictions [the so called same-domain policy], and I couldn't parse the json data coming from Multicolr: give it up? Well if you can't enter from main entrance, use the backdoor - I filtered the json data with a PHP script, just to make the ajax call from the same domain. Then I added the tiles to an empty div gradually. Got it? Not yet, because the requests resolved in a casual order, and so the pics were added. How to solve? First, I filled up the mosaic div with little black tile-divs, each labeled with id "i_j", where i and j were te matrix indexes in the color palette matrix. Then with each call, I told to set the image as background for the (i,j)-th div.

Yes now it was all, and the mosaic slowly began to appear - very slowly actually, because it's still about hundreds of jpegs to get and place, and I'm sure this can be optimized a lot, but I don't think I will develop it further, because there is no way to get variance or autosimilarity info from web pictures, at least if you don't want to crawl the whole flickr and analyze every single photo.

I would have uploaded the script here so you could have had a try, but I had server issued with the php script, so I can only show you a couple of mosaics I made, hope you enjoy.

King Crimson - In the Court of the Crimson King [album cover, 1969 - flickr mosaic, 2010]

Barack Obama - yes, I can [do cool stuff].

Oh, here it is the code, if you want to have a look.

var drawingCanvas = document.getElementById("mosaicDrawer");
var context;
var myImage;

color[][] palette = null;

int cols, rows, bw, bh;

void setup(){
 
 rows = 40;
 cols = 40; 

 setPalette("img/crimson.jpg",rows,cols); 
}

void getPics(){ 

 for(int j=0;j> 16 & 0xFF);
 g = (palette[i][j] >> 8 & 0xFF);
 b = (palette[i][j] & 0xFF); 

 $.getJSON("json_decode.php?ij="+i+"_"+j+"&color="+r+"."+g+"."+b,function(data){ 
 $("#o_"+data.ij).css("background-image", "url('"+data.result[(int)(10*Math.random())][1]+"')");
 $("#o_"+data.ij).hover(function(){
 var imgurl = $(this).css("background-image").split('"')[1];
 $("#inspector").html("");
 var pos = $(this).offset();
 $("#inspector").css("top",pos.top-5);
 $("#inspector").css("left",pos.left-5);
 $("#inspector").show();
 setTimeout(function(){
 $("#inspector").hide("slow");
 },2000); 
 });
 });
 }
 } 
 
}

void setPalette(String url, int rows, int cols){
 if(drawingCanvas.getContext){
 context = drawingCanvas.getContext('2d');
 myImage = new Image();
 myImage.onload = function() {

 bw = (int)(myImage.width / cols);
 bh = (int)(myImage.height / rows); 
 
 size(myImage.width,myImage.height);
 context.drawImage(myImage, 0, 0);

 loadPixels();

 palette = new color[cols][rows];
 
 for(int j=0;j> 16 & 0xFF);
 g = g + (rgb >> 8 & 0xFF);
 b = b + (rgb & 0xFF);
 
 i++;
 if((i%img.width)%w==0){
 i=i+img.width-w;
 j++;
 } 
 } 
 return color(r/(w*h),g/(w*h),b/(w*h));
}

What people said

No comments yet.

Write yours!

( * = required field. )

I want to be notified by e-mail about new comments ->