1

If I have 2 images that are the same except i change 1 pixel, it says there is 131 different changes in my array. Why is this happening? I'm creating 2 arrays using getcanvasdata and a loop to compare both.

var c = document.getElementById("myCanvas");
var c2 = document.getElementById("myCanvas2");
var ctx = c.getContext("2d");
var ctx2 = c2.getContext("2d");
var img = new Image();
var img2 = new Image();
var diffpixels = [];
var imgData;
var imgData2;
img.src = "avengers2.jpg";
img2.src = "avengers1.jpg";
img.onload = function() {
  ctx.drawImage(img, 0, 0);
  imgData = ctx.getImageData(0, 0, 1920, 1080).data;

  img2.onload = function() {
    ctx2.drawImage(img2, 0, 0);
    imgData2 = ctx2.getImageData(0, 0, 1920, 1080).data;
    console.log(imgData2.length);
    for (var i = 0; i < imgData.length; i++) {
      if (imgData[i] === imgData2[i]) {} else {
        diffpixels.push(i);
      }
    }
    console.log(diffpixels);
  }
}
<canvas id="myCanvas" width="1920" height="1080" style="border:1px solid #d3d3d3"></canvas>
<canvas id="myCanvas2" width="1920" height="1080" style="border:1px solid #d3d3d3"></canvas>
  • How did you create the image files? If you change a pixel and then save the file the JPG lossy compression algorithm could account for more differences, couldn't it? – nnnnnn Mar 17 '17 at 03:27
  • 1
    Just note that you're not counting different pixels, but different channels (ie. pixels x 4). –  Mar 17 '17 at 04:28

1 Answers1

2

I suspect your problem here is actually in the use of .jpgs for your image files, as these contain artifacts from compression. Changing even one pixel and/or recompressing a .jpg image by saving it as a new file frequently causes more than one pixel to change due to the rather lossy compression method. I suggest you try using .png images instead, since they are a (mostly, usually) lossless format. The rest of your method here seems solid.

Alternatively, for the purposes of testing your code to make absolutely sure it works, you could load just one of the images into both canvases, then pick an arbitrary point (for this example, the point (100, 100) in myCanvas2) on one and do a quick one-pixel rectangle of an unexpected colour (say, #FF0080)

ctx2.fillStyle = "#FF0080";
ctx2.fillRect(100, 100, 1, 1);

right before comparing the two canvases. That may not work for the eventual case you are going for, but it should accurately test the function you've written.

GameGibu
  • 106
  • 9
  • 1
    Even for png, you can't actually be sure it would return the same values, there could be some discrepancy in e.g the color-profiles. Also, one should remember that testing images from canvas is actually a no-go (https://en.wikipedia.org/wiki/Canvas_fingerprinting, http://stackoverflow.com/questions/36273990/canvas2d-todataurl-different-output-on-different-browser/36274211) – Kaiido Mar 17 '17 at 05:39