@@ -4,6 +4,40 @@ import resizeImageWidth from '../resizeImageWidth';
4
4
const testImageBeforePath = './src/algorithms/image-processing/seam-carving/__tests__/test-image-before.jpg' ;
5
5
const testImageAfterPath = './src/algorithms/image-processing/seam-carving/__tests__/test-image-after.jpg' ;
6
6
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
+
7
41
describe ( 'resizeImageWidth' , ( ) => {
8
42
it ( 'should perform content-aware image width reduction' , ( ) => {
9
43
// @see : https://jestjs.io/docs/asynchronous
@@ -21,6 +55,7 @@ describe('resizeImageWidth', () => {
21
55
const canvasAfter = createCanvas ( imgAfter . width , imgAfter . height ) ;
22
56
const ctxAfter = canvasAfter . getContext ( '2d' ) ;
23
57
ctxAfter . drawImage ( imgAfter , 0 , 0 , imgAfter . width , imgAfter . height ) ;
58
+ const imgDataAfter = ctxAfter . getImageData ( 0 , 0 , imgAfter . width , imgAfter . height ) ;
24
59
25
60
const toWidth = Math . floor ( imgBefore . width / 2 ) ;
26
61
@@ -44,8 +79,13 @@ describe('resizeImageWidth', () => {
44
79
expect ( imgDataTest . width ) . toBe ( imgAfter . width ) ;
45
80
expect ( imgDataTest . height ) . toBe ( imgAfter . height ) ;
46
81
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 ) ;
49
89
} ) ;
50
90
} ) ;
51
91
} ) ;
0 commit comments