Have you ever played Spot the difference game? If you did not have childhood, it's a type of puzzle in which the object is to find a certain number of minor differences between two pictures, usually printed side by side, that are otherwise identical. Sometimes this game can become a really big headache.
Check the following example and try to search the differences by yourself (in case you have time, otherwise just keep reading and we can guarantee that there are totally 4 differences):
But, really ? It seems a little complicated image and it would take a while to discover them by ourself. What about writing some JavaScript that could spot the difference for us and that as result it should generate an image like:
Much better, there are the differences in our images! The differentiation of images is a really awesome task that can be easily achieved thanks to js-imagediff. js-imagediff is JavaScript / Canvas based imagediff utility that can be used in the browser and with Node.js. For more information about this library, please visit the official repository at Github here.
In this article we are going to show you how to get started with this library and how to differentiate images with it or to check if 2 images are equal or not.
1. Installation
The first you need to do to, is to download the js-imagediff library script either minified or the source code and include it in your HTML document using a script tag:
<!-- Include the image-diff library -->
<script src="image-diff.min.js"></script>
Once the library is included, you will be able to access it in the browser with window.imagediff
or just imagediff
.
2. Spot the differences
This library is pretty easy to use, to get started you will obviously need at least 2 images to compare. Then create respectively a variable from the image element and retrieve its value, this value can be either the <img>
element or an instance of the Image
class of JavaScript (you will need to set the src attribute manually with JavaScript).
Then use the diff method of imagediff that expects as arguments the images to differentiate. This method is synchronous and will return immediately an ImgData that contains an image that highlights the differences between the providen images. This ImgData can be drawn on a canvas (putImageData method of the canvas) in order to show to your user the differences:
// Instance of the first image
var ImageA = document.getElementById("image-element-1");
// or
// var ImageA = new Image();
// ImageA.src = "image1-file.png";
// Instance of the second image
var ImageB = document.getElementById("image-element-2");
// or
// var ImageB = new Image();
// ImageB.src = "image2-file.png";
// Create the image that shows the difference between the images
var diff = imagediff.diff(ImageA, ImageB);
// Create a canvas with the imagediff method (with the size of the generated image)
var canvas = imagediff.createCanvas(diff.width, diff.height);
// Retrieve the 2d context
var context = canvas.getContext('2d');
// Draw the generated image with differences on the canvas
context.putImageData(diff, 0, 0);
// Now you can do whatever you want with the canvas
// for example render it inside a div element:
document.getElementById("some-div-id").appendChild(canvas);
By the otherside you can verify to wheter an image is equal to other using the equal method of imagediff:
// Instance of the first image
var ImageA = document.getElementById("imageA");
// or
// var ImageA = new Image();
// ImageA.src = "image1-file.png";
// Instance of the second image
var ImageB = document.getElementById("imageB");
// or
// var ImageB = new Image();
// ImageB.src = "image2-file.png";
// Create the image that shows the difference between the images
var isEqual = imagediff.equal(ImageA, ImageB , 0);
// True or False according to the images
console.log(isEqual);
The third parameter specifies the tolerance in pixels.
Note
The only problem that you need to deal is they way you verify if the images were loaded or not (as you can't get the difference from 2 images that aren't available). In our examples we'll use a flag variable that increments its value when an image is loaded. It's incremented by assigning the same onload callback for all the images (when the flag variable reachs 2, the same number of images then it will proceed with the diff).
Example: Loading images via img tag
The following example shows how to differentiate 2 images that are being loaded through <img>
tags in the document. The onLoad callback will be only executed once the images were loaded (to verify check the load event of the images) and once the differentiation finishes, it will append the canvas to the same div where the images are:
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<!-- Div to show the images -->
<div id="result-container">
<img src="example_a.png" id="imageA"/>
<img src="example_b.png" id="imageB"/>
</div>
<!-- Include the image-diff library -->
<script src="image-diff.min.js"></script>
<script>
// A flag variable to indicate wheter the 2 images were loaded or not
var loadedImages = 0;
// Create a variable from the first image
var ImageA = document.getElementById("imageA");
// Create a variable from the second image
var ImageB = document.getElementById("imageB");
/**
* Callback that should be executed when the images are finally loaded.
*
**/
var onImagesLoaded = function () {
// Increment the images loaded flag
loadedImages++;
// Skip execution of the callback if the 2 images have been not loaded
// Otherwise continue with the diff
if(loadedImages != 2){
return;
}
// Create the image that shows the difference between the images
var diff = imagediff.diff(ImageA, ImageB);
// Create a canvas with the imagediff method (with the size of the generated image)
var canvas = imagediff.createCanvas(diff.width, diff.height);
// Retrieve the 2d context
var context = canvas.getContext('2d');
// Draw the generated image with differences on the canvas
context.putImageData(diff, 0, 0);
// Add the canvas element to the div element to show
document.getElementById("result-container").appendChild(canvas);
// Display some alert !
alert("Done!");
};
// Set the onLoad callback of the images
ImageA.addEventListener("load", onImagesLoaded, false);
ImageB.addEventListener("load", onImagesLoaded, false);
</script>
</body>
</html>
With some example images, the result would be something like:
Example: Loading images with JavaScript
If you aren't working in the document with the images but manipulating them directly and abstractly with JavaScript, then you won't have any <img>
tag, which means that you will need to handle your images with the Image
class of JavaScript.
However, in the same way you do with images loaded via HTML, you will need to check whether the image has been loaded or not through the onload
callback. Once the differentiation finishes, a canvas will be appended to the result-container
div to show the result graphically:
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<!-- Some div to append the result canvas later -->
<div id="result-container"></div>
<!-- Include the image-diff library -->
<script src="image-diff.min.js"></script>
<script>
// A flag variable to indicate wheter the 2 images were loaded or not
var loadedImages = 0;
// Create a variable from the first image
var ImageA = new Image();
ImageA.src = "./example_a.png";
// Create a variable from the second image
var ImageB = new Image();
ImageB.src = "./example_b.png";
/**
* Callback that should be executed when the images are finally loaded.
*
*
**/
var onImagesLoaded = function () {
// Increment the images loaded flag
loadedImages++;
// Skip execution of the callback if the 2 images have been not loaded
// Otherwise continue with the diff
if(loadedImages != 2){
return;
}
// Create the image that shows the difference between the images
var diff = imagediff.diff(ImageA, ImageB);
// Create a canvas with the imagediff method (with the size of the generated image)
var canvas = imagediff.createCanvas(diff.width, diff.height);
// Retrieve the 2d context
var context = canvas.getContext('2d');
// Draw the generated image with differences on the canvas
context.putImageData(diff, 0, 0);
// Add the canvas element to the div element to show
document.getElementById("result-container").appendChild(canvas);
// Display some alert !
alert("Done!");
};
// Set the onLoad callback of the images
ImageA.onload = onImagesLoaded;
ImageB.onload = onImagesLoaded;
</script>
</body>
</html>
Our example would generate the same black image as the previous example:
Happy coding !