Pixels

It is possible to read and write to individual pixels on a canvas.

The getImageData() function allows us to read rectangular areas from a canvas.

imageData = ctx.getImageData(x, y, width, height);      

 

Example of reading and writting pixels on a canvas (Run Example).

<!-- Author: Derek O Reilly, Dundalk Institute of Technology, Ireland. -->

<!DOCTYPE html>
<html>
    <head>
        <title>Course notes example code</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> #gameCanvas { /* the canvas styling usually does not change */ outline:1px solid darkgrey; width:500px; height:500px; } </style> </head> <body> <canvas id = "gameCanvas"></canvas> <script> let img = new Image(); // note that the offscreen image must be declared OUTSIDE of the window.onload() function img.src = "images/city.png"; window.onload = function () { let canvas = document.getElementById("gameCanvas"); canvas.width = canvas.clientWidth; canvas.height = canvas.clientHeight; let ctx = canvas.getContext("2d"); // draw an image on the canvas ctx.drawImage(img, 0, 0, canvas.width, canvas.height); // get the pixels from the canvas // NOTE: getImageData() will only work if the image in drawImage is // on the same server as the webpage let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); let data = imageData.data; const RED = 0; const GREEN = 1; const BLUE = 2; const ALPHA = 3; for (let i = 0; i < data.length; i += 4) { data[i + RED] = 255 - data[i + 0]; data[i + GREEN] = 255 - data[i + 1]; data[i + BLUE] = 255 - data[i + 2]; data[i + ALPHA] = 255; } ctx.putImageData(imageData, 0, 0); }; </script> </body> </html>
                let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
                let data = imageData.data;

The above two lines of code above copy the selected pixels into a one-dimensional array.

                const RED = 0;
                const GREEN = 1;
                const BLUE = 2;
                const ALPHA = 3;

                for (let i = 0; i < data.length; i += 4)
                {
                    data[i + RED] = 255 - data[i + 0];
                    data[i + GREEN] = 255 - data[i + 1];
                    data[i + BLUE] = 255 - data[i + 2];
                    data[i + ALPHA] = 255;
                }

The for-loop above steps through each of the selected pixels. Each pixel has a red, green, blue and alpha value, each of which is in the range 0-255.

ctx.putImageData(imageData, 0, 0);

The putImageData() function allows us to write the selected pixels on the canvas.

Write code to place coloured text on a grayscale image, as shown here.

Read/Write part of a canvas

The getImageData() and putImageData() functions allow us to read/write onto any rectangular area of a canvas, as shown here.

<!-- Author: Derek O Reilly, Dundalk Institute of Technology, Ireland. -->

<!doctype html>
<html>
    <head>
        <title>Course notes example code</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> #gameCanvas { /* the canvas styling usually does not change */ outline:1px solid darkgrey; width:500px; height:500px; } </style> </head> <body> <canvas id = "gameCanvas"></canvas> <script> let image = new Image(); image.src = "images/city.png"; window.onload = function () { let canvas = document.getElementById("gameCanvas"); canvas.width = canvas.clientWidth; canvas.height = canvas.clientHeight; let ctx = canvas.getContext("2d"); ctx.drawImage(image, 0, 0, canvas.width, canvas.height); // get the pixels from the canvas // NOTE: getImageData() will only work if the image in drawImage is // on the same server as the webpage let imageData = ctx.getImageData(canvas.width / 3, 0, canvas.width / 3, canvas.height); // x,y position and regtangle width and height let data = imageData.data; const RED = 0; const GREEN = 1; const BLUE = 2; const ALPHA = 3; // Manipulate the pixel data for (let i = 0; i < data.length; i += 4) { imageData.data[i + RED] = 255 - imageData.data[i + RED]; imageData.data[i + GREEN] = 255 - imageData.data[i + GREEN]; imageData.data[i + BLUE] = 255 - imageData.data[i + BLUE]; imageData.data[i + ALPHA] = 255; } ctx.putImageData(imageData, canvas.width / 3, 0); }; </script> </body> </html>
imageData = ctx.getImageData(canvas.width / 3, 0, canvas.width / 3, canvas.height); // x,y position and regtangle width and height

The code above shows that we only manipulate the middle one-third of the canvas.

Write code to display a greyscaled image with a coloured border, as shown here.

Accessing One Pixel

We can read/write any single canvas pixel by selecting a rectangle of size 1 pixel. The code below reads a single pixel.

let imageData = someOffscreenCanvas.getImageData(x, y, 1, 1); 
let data = imageData.data;

if (data[ALPHA] !== 0)
{
    // This pixel is not transparent
}

We can use an offscreen canvas to test the mouse pointer against the transparent and non-transparent parts of an image. This is especially useful for accurate collision detection. We shall look at this in more detail later.