Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting the wrong RGB values from canvas pixel data

Im drawing 4 rectangles on a canvas. Each has a different colour:

enter image description here

Rectangle 1: rgb(38, 94, 33)
Rectangle 2: rgb(96, 231, 42)
Rectangle 3: rgb(190, 152, 213)
Rectangle 4: rgb(57, 93, 254)

Now if I get the rgb values of the pixels where these rectangles are drawn using ctx.getImageData(). The RGB values do not correspond to the ones that I set.

let imgData1 = ctx.getImageData(50, 50, 1, 1).data;
let imgData2 = ctx.getImageData(150, 50, 1, 1).data;
let imgData3 = ctx.getImageData(250, 50, 1, 1).data;
let imgData4 = ctx.getImageData(350, 50, 1, 1).data;
rgb(39, 94, 32)     --> should be rgb(38, 94, 33)
rgb(97, 231, 43)    --> should be rgb(96, 231, 42)
rgb(191, 152, 212)  --> should be rgb(190, 152, 213)
rgb(56, 92, 254)    --> should be rgb(57, 93, 254)

Any idea why?


Update:

Apparently it's a browser issue. I was using Brave (Version 1.23.75 Chromium: 90.0.4430.93 (Official Build) (x86_64)). Seems to be working find in chrome, ff, and safari.


let width = 400;
let height = 300;

let canvas = document.getElementById('canvas');
canvas.width = width;
canvas.height = height;

let ctx = canvas.getContext('2d');

let c1 = 'rgb(38, 94, 33)';
let c2 = 'rgb(96, 231, 42)';
let c3 = 'rgb(190, 152, 213)';
let c4 = 'rgb(57, 93, 254)';

ctx.beginPath();
ctx.rect(50,50,50,50);
ctx.fillStyle  = c1;
ctx.fill();

ctx.beginPath();
ctx.rect(150,50,50,50);
ctx.fillStyle  = c2;
ctx.fill();

ctx.beginPath();
ctx.rect(250,50,50,50);
ctx.fillStyle  = c3;
ctx.fill();

ctx.beginPath();
ctx.rect(350,50,50,50);
ctx.fillStyle  = c4;
ctx.fill();

let imgData1 = ctx.getImageData(50, 50, 1, 1).data;
let imgData2 = ctx.getImageData(150, 50, 1, 1).data;
let imgData3 = ctx.getImageData(250, 50, 1, 1).data;
let imgData4 = ctx.getImageData(350, 50, 1, 1).data;

console.log(`rgb(${imgData1[0]}, ${imgData1[1]}, ${imgData1[2]}) --> Should be ${c1}`);
console.log(`rgb(${imgData2[0]}, ${imgData2[1]}, ${imgData2[2]}) --> Should be ${c2}`);
console.log(`rgb(${imgData3[0]}, ${imgData3[1]}, ${imgData3[2]}) --> Should be ${c3}`);
console.log(`rgb(${imgData4[0]}, ${imgData4[1]}, ${imgData4[2]}) --> Should be ${c4}`);
<canvas id="canvas"></canvas>
like image 923
Ivan Bacher Avatar asked Apr 30 '21 09:04

Ivan Bacher


1 Answers

You've been farbled by Brave

(Answer courtesy @CBroe & @KenHerbert)

Brave applies some small, repeatable randomizations to "the output of semi-identifying browser features" to defeat fingerprinting efforts. They call this farbling.

Observable behavior (from that link):

  • a site will get the exact same value each time it tries to fingerprint within the same session
  • different sites will get different values
  • the same site will get different values on the next session

Farbling is applied to these canvas capabilities:

  • getImageData
  • measureText
  • isPointInPath
  • isPointInStroke
  • toDataURL
  • toBlob
like image 167
Tom Avatar answered Nov 09 '22 23:11

Tom