Skip to content

Commit cfd9a63

Browse files
authoredApr 21, 2021
Test that two images are identical for the Seam Carving algorithm. (trekhleb#694)
* Test that two images are identical for the Seam Carving algorithm. * Tune the Seam Carving tests. * Tune the Seam Carving tests. * Tune the Seam Carving tests. * Tune the Seam Carving tests.
1 parent f0b246a commit cfd9a63

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed
 

‎.husky/pre-commit

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#!/bin/sh
22
. "$(dirname "$0")/_/husky.sh"
33

4+
# @TODO: Implement the pre-commit checks.
45
# npm run lint
56
# npm run test

‎src/algorithms/image-processing/seam-carving/__tests__/resizeImageWidth.test.js

+42-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,40 @@ import resizeImageWidth from '../resizeImageWidth';
44
const testImageBeforePath = './src/algorithms/image-processing/seam-carving/__tests__/test-image-before.jpg';
55
const testImageAfterPath = './src/algorithms/image-processing/seam-carving/__tests__/test-image-after.jpg';
66

7+
/**
8+
* Compares two images and finds the number of different pixels.
9+
*
10+
* @param {ImageData} imgA - ImageData for the first image.
11+
* @param {ImageData} imgB - ImageData for the second image.
12+
* @param {number} threshold - Color difference threshold [0..255]. Smaller - stricter.
13+
* @returns {number} - Number of different pixels.
14+
*/
15+
function pixelsDiff(imgA, imgB, threshold = 0) {
16+
if (imgA.width !== imgB.width || imgA.height !== imgB.height) {
17+
throw new Error('Images must have the same size');
18+
}
19+
20+
let differentPixels = 0;
21+
const numColorParams = 4; // RGBA
22+
23+
for (let pixelIndex = 0; pixelIndex < imgA.data.length; pixelIndex += numColorParams) {
24+
// Get pixel's color for each image.
25+
const [aR, aG, aB] = imgA.data.subarray(pixelIndex, pixelIndex + numColorParams);
26+
const [bR, bG, bB] = imgB.data.subarray(pixelIndex, pixelIndex + numColorParams);
27+
28+
// Get average pixel's color for each image (make them greyscale).
29+
const aAvgColor = Math.floor((aR + aG + aB) / 3);
30+
const bAvgColor = Math.floor((bR + bG + bB) / 3);
31+
32+
// Compare pixel colors.
33+
if (Math.abs(aAvgColor - bAvgColor) > threshold) {
34+
differentPixels += 1;
35+
}
36+
}
37+
38+
return differentPixels;
39+
}
40+
741
describe('resizeImageWidth', () => {
842
it('should perform content-aware image width reduction', () => {
943
// @see: https://jestjs.io/docs/asynchronous
@@ -21,6 +55,7 @@ describe('resizeImageWidth', () => {
2155
const canvasAfter = createCanvas(imgAfter.width, imgAfter.height);
2256
const ctxAfter = canvasAfter.getContext('2d');
2357
ctxAfter.drawImage(imgAfter, 0, 0, imgAfter.width, imgAfter.height);
58+
const imgDataAfter = ctxAfter.getImageData(0, 0, imgAfter.width, imgAfter.height);
2459

2560
const toWidth = Math.floor(imgBefore.width / 2);
2661

@@ -44,8 +79,13 @@ describe('resizeImageWidth', () => {
4479
expect(imgDataTest.width).toBe(imgAfter.width);
4580
expect(imgDataTest.height).toBe(imgAfter.height);
4681

47-
// @TODO: Check that images are identical.
48-
// expect(canvasTest.toDataURL()).toEqual(canvasAfter.toDataURL());
82+
const colorThreshold = 50;
83+
const differentPixels = pixelsDiff(imgDataTest, imgDataAfter, colorThreshold);
84+
85+
// Allow 10% of pixels to be different
86+
const pixelsThreshold = Math.floor((imgAfter.width * imgAfter.height) / 10);
87+
88+
expect(differentPixels).toBeLessThanOrEqual(pixelsThreshold);
4989
});
5090
});
5191
});

0 commit comments

Comments
 (0)