How can I use JavaScript or jQuery to read a pixel of an image when user clicks it?

How can I use JavaScript or jQuery to read the color of a pixel of an image when the user clicks on it? (of course we have the (x,y) value of this pixel by subscribing to the click event).


Solution 1:

If you can draw the image in a canvas element then you can use the getImageData method to return an array containing RGBA values.

var img = new Image();
img.src = 'image.jpg';
var context = document.getElementById('canvas').getContext('2d');
context.drawImage(img, 0, 0);
data = context.getImageData(x, y, 1, 1).data;

Solution 2:

This solution will be much faster if you need to read the pixels repeatedly.

The magic ®

function getPixel(imgData, index) {
  var i = index*4, d = imgData.data
  return [d[i],d[i+1],d[i+2],d[i+3]] // [R,G,B,A]
}

function getPixelXY(imgData, x, y) {
  return getPixel(imgData, y*imgData.width+x)
}

Where do you get imgData?

  1. create <canvas>
  2. get canvas context
  3. copy <img> to <canvas>
  4. get canvas image data (an array of values [r,g,b,a,r,g,b,a,r,g,..])
  5. do `The magic`®

le code:

var cvs = document.createElement('canvas'),
    img = document.getElementsByTagName("img")[0]   // your image goes here
    // img = $('#yourImage')[0]                     // can use jquery for selection
cvs.width = img.width; cvs.height = img.height
var ctx = cvs.getContext("2d")
ctx.drawImage(img,0,0,cvs.width,cvs.height)
var idt = ctx.getImageData(0,0,cvs.width,cvs.height)

// The magic®
getPixel(idt, 852)  // returns array [red, green, blue, alpha]
getPixelXY(idt,1,1) // same pixel using x,y

For a working example see source code of http://qry.me/xyscope/



PS: If you plan to mutate the data and draw them back on the canvas, you can use subarray

var
 a = getPixel(idt, 188411), // Array(4) [0, 251, 0, 255]
 b = idt.data.subarray(188411*4, 188411*4 + 4) // Uint8ClampedArray(4) [0, 251, 0, 255]

a[0] = 255 // does nothing
getPixel(idt, 188411) // Array(4) [0, 251, 0, 255]

b[0] = 255 // mutates the original imgData.data
getPixel(idt, 188411) // Array(4) [255, 251, 0, 255]

// or use it in the function
function getPixel(imgData, index) {
  var i = index*4, d = imgData.data
  return imgData.data.subarray(i, i+4) // returns subarray [R,G,B,A]
}

You can experiment with this on http://qry.me/xyscope/, the code for this is in the source, just copy/paste it in the console.