Pixel manipulation with canvas:
width
The width of the image in pixels; this is a read only unsigned long.
height
The height of the image in pixels; this is a read only unsigned long.
data
A CanvasPixelArray object containing the image data.
The CanvasPixelArray object can be accessed to look at the raw pixel data; each pixel is represented by four one-byte values (red, green, blue, and alpha, in that order; that is, "RGBA" format). Each color component is represented by an integer between 0 and 255. Each component is assigned a consecutive index within the array, with the top left pixel's red component being at index 0 within the array. Pixels then proceed from left to right, then downward, throughout the array.
The
CanvasPixelArray contains height x width x 4 bytes of data, with index values ranging from 0 to (height x width x 4)-1.Create an Image data object:
To create a new, blank
ImageData object, you should use the createImageData() method. This creates an ImageData object optimized for best performance with the other ImageData manipulation methods. There are two versions of the createImageData() method:var myImageData = context.createImageData(cssWidth, cssHeight);Getting the pixel data for a context
To obtain an
ImageData object containing a copy of the pixel data for a context, you can use the getImageData() method:var myImageData = context.getImageData(left, top, width, height);This method returns an
ImageData object representing the pixel data for the area of the canvas whose corners are represented by the points (left, top), (left+width,top), (left, top+height), and (left+width, top+height). The coordinates are specified in canvas coordinate space units.Painting pixel data into a context:
You can use the
putImageData() method to paint pixel data into a context:context.putImageData(myImageData, dx, dy);The
dx and dy parameters indicate the device coordinates within the context at which to paint the top left corner of the pixel data you wish to draw.For example, to paint the entire image represented by
myImageData to the top left corner of the context, you can simply do the following:context.putImageData(myImageData, 0, 0);
Example:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Untitled Document</title>
<script type="text/javascript">
function draw()
{
// Create some graphics.
var canvas = document.getElementById("MyCanvas");
var ctx = canvas.getContext("2d");
if (canvas.getContext)
{
ctx.fillStyle="white";
ctx.beginPath();
ctx.rect (5,5,300,250);
ctx.fill();
ctx.stroke();
ctx.arc(150,150,100,0,Math.PI, false);
ctx.stroke();
}
}
function imgData()
{
var canvas = document.getElementById("MyCanvas");
var ctx = canvas.getContext("2d");
var myImageData = ctx.getImageData(50, 50, 50, 50);
ctx.putImageData(myImageData, 300, 300);
}
</script>
</head>
<body onLoad="draw()" bgcolor="lightgray" >
<canvas id="MyCanvas" width="400" height="400" > </canvas>
<input type="button" value="create image object" onclick="imgData()" />
</body>
</html>
Retrieving Pixel Data
You can’t directly manipulate pixels in a canvas. In order to make changes to the data in a canvas you first need to copy the data out, make changes, and copy the changed data back to the target canvas.
The getImageData call lets you copy a rectangle of pixels out of a canvas. A call to get all of the pixel data out of a canvas looks like this:
var canvas = document.getElementById('myCanvasElt');
var ctx = canvas.getContext('2d');
var canvasData = ctx.getImageData(0, 0, canvas.width, canvas.height);
The canvasData object contains the pixel data. It has the following members:
canvasData {
width: unsigned long, // the width of the canvas
height: unsigned long, // the height of the canvas
data: CanvasPixelArray // the values of the pixels
}
The data is a flat array of values that has one value for each component in a pixel, organized left to right, top to bottom, with each pixel represented as four values in RGBA order.
For example, in a 2×2 canvas, there would be 4 pixels represented with 16 values that look like this:
0,0 0,1 1,0 1,1RGBA RGBA RGBA RGBASo you can calculate the length of that array with the following formula: width * height * 4.
var x = 10;var y = 10;var blue = canvasData.data[(y * width + x) * 4 + 2];Note that each RGB pixel has a value of 0..255 with the alpha bit being 0..255 with 0 being completely transparent and 255 fully opaque.
Create a new set of pixels
If you want to create a new matrix from scratch, just use the createImageDatacall which needs two arguments: the height and the width of the matrix.
Note that the createImageData call does not copy pixels out of the existing canvas, it produces a blank matrix of pixels with the values set to transparent black (255,255,255,0).
Here’s an example you want to create a set of pixels that fits the canvas size:
var canvas = document.getElementById('myCanvasElt');
var ctx = canvas.getContext('2d');
var canvasData = ctx.createImageData(canvas.width, canvas.height);
Note that this is the method that you should use to create pixel data. Previous versions of Firefox allowed you to create a canvasData object out of a simple JavaScript object and use it in later calls to update the canvas data. This call was added to maintain compatibility with WebKit which under the hood uses a specialized object instead of a generic JavaScript object.
Update the pixels
Once you have the canvasData object you can update the pixel values through the array. Here’s one example of how to walk through the array reading and updating the values.
for (var x = 0; x < canvasData.width; x++) {
for (var y = 0; y < canvasData.height; y++) {
// Index of the pixel in the array
var idx = (x + y * width) * 4;
// If you want to know the values of the pixel
var r = canvasData.data[idx + 0];
var g = canvasData.data[idx + 1];
var b = canvasData.data[idx + 2];
var a = canvasData.data[idx + 3];
//[...] do what you want with these values
// If you want to update the values of the pixel
canvasData.data[idx + 0] = ...; // Red channel
canvasData.data[idx + 1] = ...; // Green channel
canvasData.data[idx + 2] = ...; // Blue channel
canvasData.data[idx + 3] = ...; // Alpha channel
}
}
Update the canvas
Now that you’ve got a set of pixels updated you can use the simpleputImageData call. This call takes the canvasData object and the x,y location where you would like to draw the rectangle of pixel data into the canvas:
var canvas = document.getElementById('myCanvasElt');
var ctx = canvas.getContext('2d');
var canvasData = ctx.putImageData(canvasData, 0, 0);
Full example for getImageData
Here is code that transforms a color image to a grey scale version of the image. You can also see a live version of this demo on Paul’s site.
var canvas = document.getElementById('myCanvasElt');
var ctx = canvas.getContext('2d');
var canvasData = ctx.getImageData(0, 0, canvas.width, canvas.height);
for (var x = 0; x < canvasData.width; x++) {
for (var y = 0; y < canvasData.height; y++) {
// Index of the pixel in the array
var idx = (x + y * canvas.width) * 4;
// The RGB values
var r = canvasData.data[idx + 0];
var g = canvasData.data[idx + 1];
var b = canvasData.data[idx + 2];
// Update the values of the pixel;
var gray = (r + g + b) / 3;
canvasData.data[idx + 0] = gray;
canvasData.data[idx + 1] = gray;
canvasData.data[idx + 2] = gray;
}
}
ctx.putImageData(canvasData, 0, 0);
Full example for createImageData
This bit of code will draw a fractal into a canvas. Once again, you can see a livedemo of this code on Paul’s site.
var canvas = document.getElementById('myCanvasElt');
var ctx = canvas.getContext('2d');
var canvasData = ctx.createImageData(canvas.width, canvas.height);
// Mandelbrot
function computeColor(x, y) {
x = 2.5 * (x/canvas.width - 0.5);
y = 2 * (y/canvas.height - 0.5);
var x0 = x;
var y0 = y;
var iteration = 0;
var max_iteration = 100;
while (x * x + y * y <= 4 && iteration < max_iteration ) {
var xtemp = x*x - y*y + x0;
y = 2*x*y + y0;
x = xtemp;
iteration++;
}
return Math.round(255 * iteration / max_iteration);
}
for (var x = 0; x < canvasData.width; x++) {
for (var y = 0; y < canvasData.height; y++) {
var color = computeColor(x, y);
// Index of the pixel in the array
var idx = (x + y * canvas.width) * 4;
// Update the values of the pixel;
canvasData.data[idx + 0] = color;
canvasData.data[idx + 1] = color;
canvasData.data[idx + 2] = color;
canvasData.data[idx + 3] = 255;
}
}
ctx.putImageData(canvasData, 0, 0);
Example for getPixel from canvas element and put it another canvas element:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Untitled Document</title>
<script type="text/javascript">
function draw()
{// Create some graphics.
var canvas = document.getElementById("source"); var ctx = canvas.getContext("2d");if (canvas.getContext)
{ctx.fillStyle="white";
ctx.beginPath();
ctx.rect (5,5,300,250);
ctx.fill();
ctx.stroke();
ctx.arc(150,150,100,0,Math.PI, false);
ctx.stroke();
}
}
function imgData()
{ var canvas = document.getElementById('source');var ctx = canvas.getContext('2d');var canvasData = ctx.getImageData(0, 0, canvas.width, canvas.height);
for (var x = 0; x < canvasData.width; x++) { for (var y = 0; y < canvasData.height; y++) {// Index of the pixel in the array
var idx = (x + y * canvas.width) * 4;
// The RGB values
var r = canvasData.data[idx + 0];
var g = canvasData.data[idx + 1];
var b = canvasData.data[idx + 2];
// Update the values of the pixel;
var gray = (r + g + b) / 3;
canvasData.data[idx + 0] = gray;
canvasData.data[idx + 1] = gray;
canvasData.data[idx + 2] = gray;
}
}
var canvas = document.getElementById('destination');var ctx = canvas.getContext('2d');ctx.putImageData(canvasData, 0, 0);
}
</script>
</head>
<body onLoad="draw()" bgcolor="lightgray" >
<canvas id="source" width="400" height="400" > </canvas>
<canvas id="destination" width="400" height="400" > </canvas>
<input type="button" value="create image object" onclick="imgData()" />
</body>
</html>