0

I have an image tag in my HTML code with src containing the path to a local image.

<img alt="abc" src="./images/abc.png" />

Upon clicking the image, I want to call a JavaScript method that will return the buffer data of the image.

Example buffer:

(23234)[234,345,786]

How is it done in pure JavaScript?

Sean Francis N. Ballais
  • 2,338
  • 2
  • 24
  • 42
Maanas Hegde
  • 67
  • 2
  • 9

2 Answers2

0

You can not read pixels from an image, but you can draw an image to a canvas, and use getImageData to extract an array of the RGBA pixel data. Then it is possible to get color under the mouse cursor.
Notes about the example below:

  • the image is tiny because getImageData has cross-origin protection, and as uploading images for examples does not seem to be possible, the image is encoded in a data URI
  • however data URI-s also have cross-origin issues in certain browsers, like IE (it will not with IE as far as I remember). I tested the code with Chrome, so that works for sure, and I think it should work with Firefox too
  • none of these matters with real life code, so if you get this code out from here, and just write <img src="something.jpg" ... (so hosted locally), it can be a large image and it will work with IE too
  • there is some race condition here, sometimes I get messages about missing imgready function, so StackOverflow may load the HTML first and inject the scripts later. If you see that message, run the snippet again. With more "traditional" code order (scripts located in head) it could not happen

var imgdata;

function imgready(){
  var img=document.getElementById("you");
  var cnv=document.createElement("canvas");
  var w=cnv.width=img.width;
  var h=cnv.height=img.height;
  var ctx=cnv.getContext("2d");
  ctx.drawImage(img,0,0);
  imgdata=ctx.getImageData(0,0,w,h);
}

function mmove(event){
  if(!imgdata)return;
  var x=event.clientX-event.target.offsetLeft;
  var y=event.clientY-event.target.offsetTop;
  var offset=(x+y*imgdata.width)*4;
  var r=imgdata.data[offset];
  var g=imgdata.data[offset+1];
  var b=imgdata.data[offset+2];
  document.getElementById("logdiv").innerText=x+","+y+" ("+offset+"): r="+r+" g="+g+" b="+b;
  var cnv=document.getElementById("colorcnv");
  var ctx=cnv.getContext("2d");
  ctx.clearRect(0,0,cnv.width,cnv.height);
  ctx.fillStyle="rgb("+r+","+g+","+b+")";
  ctx.beginPath();
  ctx.arc(10,10,10,0,Math.PI*2);
  ctx.fill();
}
<img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4QAqRXhpZgAASUkqAAgAAAABADEBAgAHAAAAGgAAAAAAAABHb29nbGUAAP/bAIQAAwICAwICAwMDAwQDAwQFCAUFBAQFCgcHBggMCgwMCwoLCw0OEhANDhEOCwsQFhARExQVFRUMDxcYFhQYEhQVFAEDBAQFBAUJBQUJFA0LDRQUFBQUExQPFBQUFBQUFBQUFBQUFBQUEBUUFBQVDxQUFA4UFBQVFBEVFBQTFBQUERQU/8AAEQgAFAAUAwERAAIRAQMRAf/EABoAAAEFAQAAAAAAAAAAAAAAAAgEBQYHCQP/xAAnEAABAwMEAQMFAAAAAAAAAAABAgMFBBEhAAYHEmETIjEII0FCof/EABkBAAIDAQAAAAAAAAAAAAAAAAQGAwUHAv/EACwRAAEDAwIDBgcAAAAAAAAAAAECAxEABCExUQUGEkFhweHw8RMiMnGBsdH/2gAMAwEAAhEDEQA/AM6GuRZOaplxjVGyh2oQWkuNEhQxm3m2NVhtUNHrJwKPDql/KBVkO/SDPDa9DKRM9QyMm+EOCLbSUOtNFQBeKrmyR83tnqbXItpbb5nZLpbeaKUyROudojt98VZq4QtKAptYJ1inWqjEsVC2i428WyUF1o3Qu2OyTYYPyNGJV1CRiuYjFRSf4KmuERszcM49RvOzdIJOgj2qhtai0W0KBc6LUW7esgWUkEnsAD1JDOi3evVFgCJ7Z8KqSWmEhwKk7R40SXB3M8NOcPbm2puGoVB1VLQ1b7zTTQSiqZKlOKSwv9VdlC4JTg4CsqTn/HuWb3h9wi4t09SCpIB1IOAOoffAORvGlMVpxVm5a+C4YUAZ79Tj1/aGyOl9xGjbK32XV2ytbIyfFrY8/nW0K5aszmFD8+RpUTfORSrdG5ZvccjGtzM7LTbVBQKYo25Svdq00rVh9toOKV6aPan2psMDGg+GmHFK2FDOfTXCnYQaZN09u1yQrOQQR/dPgSClJ7/36mgN6WvrU2vrcqsPk6kccKVECpUiRX//2Q==" id="you" onload="imgready()" onmousemove="mmove(event)">
<canvas id="colorcnv" width="20" height="20"></canvas><br>
<div id="logdiv"></div>
tevemadar
  • 12,389
  • 3
  • 21
  • 49
0

Modified version of tevemadar's answer that might be usefull:

function imgToBuffer(e){
  let cnv=document.createElement("canvas"), w=cnv.width=e.width, h=cnv.height=e.height, ctx=cnv.getContext("2d");
  ctx.drawImage(e,0,0);
  return getImageData(0,0,w,h)
}

This function simply draws the image element to canvas and returns the image buffer. No extra HTML needed.

To get the ArrayBuffer out of it, use

imgToBuffer(el).data.buffer