maxnov.com » $.getImageData Follow @maxnovakovic Follow @maxnovakovic A tiny jQuery plugin that, in conjunction with a Google App Engine back-end, allows cross-domain getImageData with the HTML5 Canvas.

About¶ This project is aimed at developers who don't have the ability, don't want to or don't have time to create a proxy script on their server to get images from different domains or origins. It enables pixel level access to images from different origins. It works by sending a JSONP request with the URL of the image to Google's servers via the Google App Engine1. The server then converts the image into base64 encoded data URL and sends the image back as a JSON object. This means that the image can be locally included on the website and therefore it can be edited by the canvas tag.

Installation¶ Once you have downloaded $.getImageData, you need to do the following; Include jQuery and the $.getImageData source in your HTML document right before the last body tag, like this: <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> <script src="js/jquery.getimagedata.min.js"></script> </body>

Usage¶ Once you have installed the plugin, you are ready to call the $.getImageData function. The function expects one parameter which must be an object consisting of three properties: url, success and error. url is a string containing the URL of the image you are trying to fetch. success and error are callback functions that are called on successful fetching of the image or failure. $.getImageData({ url: "http://farm4.static.flickr.com/3002/2758349058_ab6dc9cfdc_z.jpg?zz=1", success: function(image){ // Do something with the now local version of the image }, error: function(xhr, text_status){ // Handle your error here } });

Examples¶ Getting an image from another domain and then inverting it¶ View demo In the example below, the image (London Skyline from Altitude 6 by Annie Mole) is specified as the url property. The success property is a function that receives one argument, which is the requested image. This callback is called once the image has been loaded locally into the DOM. This means that it can now be put on to the canvas and getImageData can be used on it. $.getImageData({ url: "http://farm4.static.flickr.com/3002/2758349058_ab6dc9cfdc_z.jpg?zz=1", success: function(image){ // Set up the canvas var can = document.getElementsByTagName('canvas')[0]; var ctx = can.getContext('2d'); // Set the canvas width and heigh to the same as the image $(can).attr('width', image.width); $(can).attr('height', image.height); // Draw the image on to the canvas ctx.drawImage(image, 0, 0, image.width, image.height); // Get the image data var image_data = ctx.getImageData(0, 0, image.width, image.height); var image_data_array = image_data.data; // Invert every pixel for (var i = 0, j = image_data_array.length; i < j; i+=4) { image_data_array[i] = 255 - image_data_array[i]; image_data_array[i+1] = 255 - image_data_array[i+1]; image_data_array[i+2] = 255 - image_data_array[i+2]; } // Write the image data to the canvas ctx.putImageData(image_data, 0, 0); }, error: function(xhr, text_status){ // Handle your error here } });



Loading images from flickr and analysing the colour¶ View demo This example loads photos from the flickr public feed. It then takes those images and fetches them using $.getImageData so their data can be read using the canvas. The data is then averaged to get the average colour in each images. The images are then added to the page with their average colour displayed next to them. This is an example of the beginning of an interesting mashup that could be achieved by using flickr as a source of images. // Get the flickr stream $.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=colour&tagmode=any&format=json&jsoncallback=?", function(data){ // For each image $.each(data.items, function(i,item){ $.getImageData({ url: item.media.m, // This is the URL of the flickr image success: analyseAndDraw, // Run this function when image has been fetched error: function(xhr, text_status){ // Handle your error here } }); }); }); // This creates a canvas, draws the image on to it, gets the average colour of the image and then adds // the image to the DOM with the average colour as a background colour to its container function analyseAndDraw(image) { // Create the canvas and context var can = document.createElement('canvas'); var ctx = can.getContext('2d'); // Set the canvas dimensions $(can).attr('width', image.width); $(can).attr('height', image.height); // Draw the image to the canvas ctx.drawImage(image, 0, 0, image.width, image.height); // Get the image data var image_data = ctx.getImageData(0, 0, image.width, image.height); var image_data_array = image_data.data; var image_data_array_length = image_data_array.length; // Array to hold the average totals var a=[0,0,0]; // Accumulate the pixel colours for (var i = 0; i < image_data_array_length; i += 4){ a[0]+=image_data_array[i]; a[1]+=image_data_array[i+1]; a[2]+=image_data_array[i+2]; } // Divide by number total pixels a[0] = Math.round(a[0]/=(image_data_array_length/3)); // R a[1] = Math.round(a[1]/=(image_data_array_length/3)); // G a[2] = Math.round(a[2]/=(image_data_array_length/3)); // B // Create the container, set its background colour and add it to the DOM var imageContainer = $(' '); $(".images").append(imageContainer); // Insert the image to the container $(imageContainer).append(image); }

Specification¶ Technical Specification¶ The main function that $.getImageData provides is the server-side image fetching. This is done using a Django project hosted on the Google App Engine1. It is a very simple project and could easily be recreated in PHP or any server-side language. The purpose of $.getImageData is to enable people to get images across domains without the need for any server-side code.

$.getImageData consists of one function that uses the jQuery JSONP Core Plugin (written by Julian Aubourg) which is packaged with this plugin. The reason for using this JSONP plugin is so that an error callback can be called if the server does not return an image for whatever reason. As mentioned above, initialising the plugin is very similar to calling getJSON: $.getImageData({ url, server, success: callback(image){}, error: callback(xhr, text_status){} }); url String The URL of the image you want to fetch. Ideally PNG, JPEG or GIF, however, the server will accept other image types. server String This is optional. It is the URL of the server you want to get the image data. Please see using your own server success: callback(image) Function This function is called on successful fetching of the requested image. It receives one argument which is an Image() object that consists of the image and it's width and height as the properties width and height. error: callback(xhr, text_status, error_throwdown) Function This function is called if the server returns an error code or takes more than 10 seconds (10000 ms) to execute. It receives two arguments which are xhr: the XMLHttpRequest and text_status: the status returned by the server (usually error or no_url). Server Specification¶ $.getImageData provides a simple wrapper around the server-side code that allows callbacks to be added when the image has been loaded or if it fails. You can, however, directly query the server and get the same result. The server addresses are: http://img-to-json.appspot.com/ And for secure requests: https://img-to-json.appspot.com/ The call to the server can be made using an XMLHttpRequest to one of the above URLs. The server expects two things: url String The URL of the image you want to fetch. Ideally PNG, JPEG or GIF, however, the server will accept other image types. callback String The callback function to be called on server response. Default should be ?. This is to enable cross-domain JSON serving. The server will respond with a JSON object consisting of data: the image data as a base64 encoded data URL, width: the width of the image and height: the height of the image. Example request without the plugin or jQuery:¶ // Image to be fetched var img_url = "http://farm4.static.flickr.com/3002/2758349058_ab6dc9cfdc_z.jpg?zz=1", // JSON callback function callback = "image_loaded_callback", // URL of the server server_url = "//img-to-json.appspot.com/?url=" + escape(img_url) + "&callback=" + callback, // Script container script = document.createElement('script'); // Set the URL to the JSONP and then append to document script.src = server_url; document.body.appendChild(script); // Callback function function image_loaded_callback(data) { // Create the image and set its src to the data URL var image = new Image; image.src = data.data; // When the image has loaded image.onload = function(){ // Set its width and height image.width = data.width; image.height = data.height; // Insert it to the DOM (this is where you could put the image on to the canvas) document.getElementById('image_container').appendChild(image); }; } Server HTTP status codes¶ If the your request fails for whatever reason, the server will respond with the following HTTP status codes: 400 - Bad Request This is usually because of a invalid URL has been sent or no URL has been sent. 413 - Request Entity Too Large The image you are trying to fetch is too large. The limit for image size is 1MB. 415 - Unsupported Media Type The type of the URL you are requesting is not supported by the server. XXX - Anything else If any other status code is sent, this is forwarded from the server that hosts the image.

Using your own server¶ If you don't want to rely on Google App Engine to server your images back as data URLs or if you would like to host a mirror server for use in the plugin then it is possible to run your own server. On GitHub in the server-examples folder you can find three different examples of the server written in Node.js, PHP and Python.

For documentation on the Node.js server, please go here.

If you are willing to run a mirror of the Google App Engine project, please email me at maxnull@maxnov.com.

Notes¶ 1 Google app engine is free to use up to a point. If the daily usage exceeds their preset limits then the plugin won't work until the next day. Unless you decide to use your own server.

License¶ The plugin is licensed in the same way as jQuery is: a dual MIT and GPL license. You can choose which license suits you best. For more information, please see: MIT License (More Information)

GPL (More Information)

$.getImageData was created by Max Novakovic in association with