Tuesday, August 4, 2015

Making Obama Gray and Inverted

Now we're going to grayscale Obama. To do this we average out the r, g, b values of each pixel, then assign that average back to each color.

var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); var imgData; var img = new Image(); img.src = "/img/obama.png"; img.onload = function handleLoad() { ctx.drawImage(0, 0, img.width. img.height); imgData = ctx.fetchImage(0, 0, img.width, img.height); //make obama gray handleData(); //draw gray obama back to canvas ctx.putImageData(imgData, 0, 0); } function handleData() { var i, d = imgData.data, leng = d.length, //declare variable to hold avg avg; for (i = 0 ; i < leng ; i+=4) { //caculate avg avg = (d[i] + d[i+1] + d[i+2])/3; //assign avg to each color //we can leave the alpha value alone d[i] = avg; d[i+1] = avg; d[i+2] = avg; } }

Nice, yes we can make Obama gray.

Or we can make Obama trippy by inverting him. To do this we assign the result of subtracting each color from 255:

var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); var imgData; var img = new Image(); img.src = "/img/obama.png"; img.onload = function handleLoad() { ctx.drawImage(0, 0, img.width. img.height); imgData = ctx.fetchImage(0, 0, img.width, img.height); //make obama alien handleData(); //draw alien obama back to canvas ctx.putImageData(imgData, 0, 0); } function handleData() { var i, d = imgData.data, leng = d.length, //declare variable to hold avg avg; for (i = 0 ; i < leng ; i+=4) { //invert each color d[i] = 255 - d[i]; d[i+1] = 255 - d[i+1]; d[i+2] = 255 - d[i+2]; } }

There is so much you can do with image data, these are just two examples.



The ImageData Object And Looping Through Pixel Data

The ImageData object holds three properties: width, height, and data.

var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); var imgData; var img = new Image(); img.src = "/img/obama.png"; img.onload = function handleLoad() { ctx.drawImage(0, 0, img.width. img.height); imgData = ctx.fetchImage(0, 0, img.width, img.height); // imgData.width // imgData.height // imgData.data }

We care about the data. The data property is an array that holds 4 consecutive values for each pixel in the image, the r (red), g (green), b ( blue ), and alpha values:

// imgData.data[0] <- red value of first pixel from 0 to 255 // imgData.data[1] <- green value of first pixel from 0 to 255 // imgData.data[2] <- blue value of first pixel from 0 to 255 // imgData.data[3] <- alpha value of first pixel from 0 to 255 (not 0 to 1 !!!)

You can run through the data values like so:

//i variable in for loop var i, //direct reference to data d = imgData.data, //leng of data leng = d.length; //increment 4 indices at a time to go from pixel to pixel for (i = 0 ; i < leng ; i+=4) { //do something to each pixel by accessing: // d[i] : r // d[i+1] : g // d[i+2] : b // d[i+3] : a }

Lets store the loop in a separate function:

var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); var imgData; var img = new Image(); img.src = "/img/obama.png"; img.onload = function handleLoad() { ctx.drawImage(0, 0, img.width. img.height); imgData = ctx.fetchImage(0, 0, img.width, img.height); //call handleData() here } function handleData() { var i, d = imgData.data, leng = d.length; for (i = 0 ; i < leng ; i+=4) { //do something to each pixel } }

Now we can try manipulating the data!



Extracting Data From An Image Loaded Onto Canvas

Previously we loaded and drew an image onto the canvas. Now we can extract some data. First, declare a variable to assign the data to once it's extracted:

var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); //we're storing our data here var imgData; var img = new Image(); img.src = "/img/obama.png"; img.onload = function handleLoad() { ctx.drawImage(0, 0, img.width. img.height); }

Then use the getImageData function to extract pixel data from the canvas once the image is loaded:

var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); var imgData; var img = new Image(); img.src = "/img/obama.png"; img.onload = function handleLoad() { //important: we can only extract pixel data from the canvas, and not directly from the image object, //so we drew the image first ctx.drawImage(0, 0, img.width. img.height); //getImageData takes in four parameters, here it's the same as the four from drawImage: //x - x coordinate at which to fetch data //y - y coordinate at which to fetch data //width - width of pixels to fetch //height - height of pixels to fetch //extract data and store it into variable declared earlier. imgData = ctx.getImageData(0, 0, img.width, img.height); }

Now we're ready to manipulate the pixels we've extracted from the image!



Loading Images For HTML5 Canvas

First, make sure you've declared the canvas and its 2d context:

//the canvas element var canvas = document.getElementById("canvas"); //the set of canvas tools your working with var ctx = canvas.getContext("2d");

Then we have to load the image with a new image object and give the object a callback to execute once the image is loaded:

var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); //new image object var img = new Image(); //give it the path to the image you're loading img.src = "/img/obama.png"; //callback to execute once image is loaded //side-note: you can name anonymous functions img.onload = function handleLoad() { }

Once your image is loaded you can draw it onto your canvas inside your callback:

var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); var img = new Image(); img.src = "/img/obama.png"; img.onload = function handleLoad() { //draw the image onto the canvas //in this example the drawImage takes in four parameters: //x - x coordinate on the canvas to render image //y - y coordinate on the canvas to render image // width - the width to draw the whole image // height - the height to draw the whole image //img width and height are properties you can access from the object ctx.drawImage(0, 0, img.width. img.height); }

Your image should appear on the upper left corner of the canvas. Now we're ready to extract some data!