From 6dc63b3ecb331707ca2faf2be432ea927a439628 Mon Sep 17 00:00:00 2001 From: B2F Date: Sat, 18 Apr 2015 12:22:11 +0200 Subject: [PATCH] Fixes #34 (Diff swallows black color in added areas): adds options.ligthness, options.rgb and options.stack to customize the diff image. --- imagediff.js | 57 ++++++++++++++++++++++++++++++++++++++++++------- js/imagediff.js | 57 ++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 98 insertions(+), 16 deletions(-) diff --git a/imagediff.js b/imagediff.js index 279ade0..4655fb0 100644 --- a/imagediff.js +++ b/imagediff.js @@ -194,10 +194,12 @@ i, j, k, v; for (i = 0; i < length; i += 4) { - cData[i] = Math.abs(aData[i] - bData[i]); - cData[i+1] = Math.abs(aData[i+1] - bData[i+1]); - cData[i+2] = Math.abs(aData[i+2] - bData[i+2]); - cData[i+3] = Math.abs(255 - Math.abs(aData[i+3] - bData[i+3])); + var pixelA = Array.prototype.slice.call(aData, i, i+3); + var pixelB = Array.prototype.slice.call(bData, i, i+3); + var diffPixel = diffPixels(pixelA, pixelB, options); + for (var rgbIndex = 0; rgbIndex < 4; rgbIndex++) { + cData[i+rgbIndex] = diffPixel[rgbIndex]; + } } return c; @@ -231,7 +233,6 @@ cData[i+0] = aData[j+0]; // r cData[i+1] = aData[j+1]; // g cData[i+2] = aData[j+2]; // b - // cData[i+3] = aData[j+3]; // a } } @@ -241,9 +242,12 @@ for (column = b.width; column--;) { i = 4 * ((row + rowOffset) * width + (column + columnOffset)); j = 4 * (row * b.width + column); - cData[i+0] = Math.abs(cData[i+0] - bData[j+0]); // r - cData[i+1] = Math.abs(cData[i+1] - bData[j+1]); // g - cData[i+2] = Math.abs(cData[i+2] - bData[j+2]); // b + var pixelA = Array.prototype.slice.call(cData, i, i+3); + var pixelB = Array.prototype.slice.call(bData, j, j+3); + var diffPixel = diffPixels(pixelA, pixelB, options); + for (var rgbIndex = 0; rgbIndex < 4; rgbIndex++) { + cData[i+rgbIndex] = diffPixel[rgbIndex]; + } } } @@ -261,6 +265,43 @@ return c; } + /** + * Differentiates two rgb pixels by subtracting color values. + * The light value for each color marks the difference gap. + * + * @see https://github.com/HumbleSoftware/js-imagediff/issues/34 + * @param {Object} options + * options.lightness: light added to color value, increasing differences visibility + * options.rgb : array used to specify rgb balance instead of lightness + * options.stack: stack differences on top of the original image, preserving common pixels + * + * @returns {Number} a color value between 0 and 255. + */ + function diffPixels(pixelA, pixelB, options) { + var lightness = options.lightness || 25; + // A custom RGB balance can be applied to color variations. + var diffColor = options.rgb || [lightness,lightness,lightness]; + // Set stack to true if you want to display common pixels instead of a black background: + var stack = options.stack || false; + // diffPixel = [r,g,b,a] + var diffPixel = [0,0,0,255]; + for (var rgbIndex = 0; rgbIndex < 3 ; rgbIndex++) { + diffPixel[rgbIndex] = Math.abs(pixelA[rgbIndex] - pixelB[rgbIndex]); + // Optionally colorize area of difference, adds visibility with lightness. + if (diffPixel[rgbIndex] > 0) { + // Lightens color differences for increased visibilty. + diffPixel[rgbIndex] += diffColor[rgbIndex]; + // Math.min is a failsafe mean for higher diffColor than 255. + diffPixel[rgbIndex] = Math.min(diffPixel[rgbIndex], 255); + } + else if (stack) { + // If options.stack and no pixel differences are found, + // print original pixel instead of a black (0) pixel. + diffPixel[rgbIndex] = pixelA[rgbIndex]; + } + } + return diffPixel; + } // Validation function checkType () { diff --git a/js/imagediff.js b/js/imagediff.js index 275d6f8..f91bb88 100644 --- a/js/imagediff.js +++ b/js/imagediff.js @@ -187,10 +187,12 @@ i, j, k, v; for (i = 0; i < length; i += 4) { - cData[i] = Math.abs(aData[i] - bData[i]); - cData[i+1] = Math.abs(aData[i+1] - bData[i+1]); - cData[i+2] = Math.abs(aData[i+2] - bData[i+2]); - cData[i+3] = Math.abs(255 - Math.abs(aData[i+3] - bData[i+3])); + var pixelA = Array.prototype.slice.call(aData, i, i+3); + var pixelB = Array.prototype.slice.call(bData, i, i+3); + var diffPixel = diffPixels(pixelA, pixelB, options); + for (var rgbIndex = 0; rgbIndex < 4; rgbIndex++) { + cData[i+rgbIndex] = diffPixel[rgbIndex]; + } } return c; @@ -224,7 +226,6 @@ cData[i+0] = aData[j+0]; // r cData[i+1] = aData[j+1]; // g cData[i+2] = aData[j+2]; // b - // cData[i+3] = aData[j+3]; // a } } @@ -234,9 +235,12 @@ for (column = b.width; column--;) { i = 4 * ((row + rowOffset) * width + (column + columnOffset)); j = 4 * (row * b.width + column); - cData[i+0] = Math.abs(cData[i+0] - bData[j+0]); // r - cData[i+1] = Math.abs(cData[i+1] - bData[j+1]); // g - cData[i+2] = Math.abs(cData[i+2] - bData[j+2]); // b + var pixelA = Array.prototype.slice.call(cData, i, i+3); + var pixelB = Array.prototype.slice.call(bData, j, j+3); + var diffPixel = diffPixels(pixelA, pixelB, options); + for (var rgbIndex = 0; rgbIndex < 4; rgbIndex++) { + cData[i+rgbIndex] = diffPixel[rgbIndex]; + } } } @@ -254,6 +258,43 @@ return c; } + /** + * Differentiates two rgb pixels by subtracting color values. + * The light value for each color marks the difference gap. + * + * @see https://github.com/HumbleSoftware/js-imagediff/issues/34 + * @param {Object} options + * options.lightness: light added to color value, increasing differences visibility + * options.rgb : array used to specify rgb balance instead of lightness + * options.stack: stack differences on top of the original image, preserving common pixels + * + * @returns {Number} a color value between 0 and 255. + */ + function diffPixels(pixelA, pixelB, options) { + var lightness = options.lightness || 25; + // A custom RGB balance can be applied to color variations. + var diffColor = options.rgb || [lightness,lightness,lightness]; + // Set stack to true if you want to display common pixels instead of a black background: + var stack = options.stack || false; + // diffPixel = [r,g,b,a] + var diffPixel = [0,0,0,255]; + for (var rgbIndex = 0; rgbIndex < 3 ; rgbIndex++) { + diffPixel[rgbIndex] = Math.abs(pixelA[rgbIndex] - pixelB[rgbIndex]); + // Optionally colorize area of difference, adds visibility with lightness. + if (diffPixel[rgbIndex] > 0) { + // Lightens color differences for increased visibilty. + diffPixel[rgbIndex] += diffColor[rgbIndex]; + // Math.min is a failsafe mean for higher diffColor than 255. + diffPixel[rgbIndex] = Math.min(diffPixel[rgbIndex], 255); + } + else if (stack) { + // If options.stack and no pixel differences are found, + // print original pixel instead of a black (0) pixel. + diffPixel[rgbIndex] = pixelA[rgbIndex]; + } + } + return diffPixel; + } // Validation function checkType () {