Update: The solution is to enable willReadFrequently: true
on the canvas in Chromium so that getImageData()
will consistently return values. Please refer to the answer below for more details.
Currently, I am working on a program that selects a pixel from a canvas where an image has been loaded using canvas.getImageData()
, analyzes the RGB values of the pixel, and performs calculations based on the blue and red values.
I have noticed an unusual behavior only in Chrome, Chromium, and Edge browsers: when an image is loaded for the first time, the value returned for a specific pixel is RGB(181,1,1)
. However, if I reload the exact same image onto the canvas using canvas.drawImage()
and select the same pixel multiple times using canvas.getImageData()
, I now get RGB(181,1,2)
.
HTML:
<canvas id="canvas" width="500" height="500"></canvas>
JavaScript:
var ctx = document.getElementById("canvas").getContext("2d", {alpha: false,});
const IMG = new Image();
IMG.src = "myImage.jpg"
ctx.drawImage(IMG, 0, 0, 500, 500);
console.log("First image draw: " + ctx.getImageData(66, 27, 1, 1).data);
ctx.drawImage(IMG, 0, 0, 500, 500);
console.log("Second image draw: " + ctx.getImageData(66, 27, 1, 1).data);
ctx.drawImage(IMG, 0, 0, 500, 500);
console.log("Third image draw: " + ctx.getImageData(66, 27, 1, 1).data);
ctx.drawImage(IMG, 0, 0, 500, 500);
console.log("Fourth image draw: " + ctx.getImageData(66, 27, 1, 1).data);
ctx.drawImage(IMG, 0, 0, 500, 500);
console.log("Fifth image draw: " + ctx.getImageData(66, 27, 1, 1).data);
Results in Chrome:
"First image draw: 181,1,1,255"
"Second image draw: 181,1,1,255"
"Third image draw: 181,1,2,255"
"Fourth image draw: 181,1,2,255"
"Fifth image draw: 181,1,2,255"
Results in Firefox:
"First image draw: 181,1,2,255"
"Second image draw: 181,1,2,255"
"Third image draw: 181,1,2,255"
"Fourth image draw: 181,1,2,255"
"Fifth image draw: 181,1,2,255"
This behavior only occurs in Chromium-based browsers; in Webkit and Firefox, I consistently get RGB(181,1,2)
regardless.
I have replicated this behavior on CodePen: open it in Chrome and Firefox to observe the difference: https://codepen.io/sh4kman/pen/qBgaNbe
What I have tried:
- Disabling antialiasing (context.imageSmoothingEnabled = false)
- Clearing the canvas (canvas.clearRect()) before/after every
getImageData()
call
I understand that different browsers can render/round colors differently for images, but in this case, I am seeing different values on the same browser, consistently following the same pattern.