|
|
|
@ -4,28 +4,31 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
(function(root, factory) { |
|
|
|
|
'use strict'; |
|
|
|
|
if (typeof define === 'function' && define.amd) { |
|
|
|
|
"use strict"; |
|
|
|
|
if (typeof define === "function" && define.amd) { |
|
|
|
|
define([], factory); |
|
|
|
|
} else if (typeof module === 'object' && module.exports) { |
|
|
|
|
} else if (typeof module === "object" && module.exports) { |
|
|
|
|
module.exports = factory(); |
|
|
|
|
} else { |
|
|
|
|
root.resemble = factory(); |
|
|
|
|
} |
|
|
|
|
}(this, function () { |
|
|
|
|
'use strict'; |
|
|
|
|
})(this, function() { |
|
|
|
|
"use strict"; |
|
|
|
|
|
|
|
|
|
var Img; |
|
|
|
|
var Canvas; |
|
|
|
|
|
|
|
|
|
if (typeof Image !== 'undefined') { |
|
|
|
|
if (typeof Image !== "undefined") { |
|
|
|
|
Img = Image; |
|
|
|
|
} else { |
|
|
|
|
Canvas = require('canvas-prebuilt'); |
|
|
|
|
Canvas = require("canvas-prebuilt"); // eslint-disable-line global-require
|
|
|
|
|
Img = Canvas.Image; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var document = typeof window !== "undefined" ? window.document : { |
|
|
|
|
var document = |
|
|
|
|
typeof window !== "undefined" |
|
|
|
|
? window.document |
|
|
|
|
: { |
|
|
|
|
createElement: function() { |
|
|
|
|
// This will work as long as only createElement is used on window.document
|
|
|
|
|
return new Canvas(); |
|
|
|
@ -36,17 +39,19 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
var globalOutputSettings = oldGlobalSettings; |
|
|
|
|
|
|
|
|
|
function setGlobalOutputSettings(settings) { |
|
|
|
|
var msg = 'warning resemble.outputSettings mutates global state, and ' + |
|
|
|
|
'will be removed in 3.0.0'; |
|
|
|
|
var msg = |
|
|
|
|
"warning resemble.outputSettings mutates global state, and " + |
|
|
|
|
"will be removed in 3.0.0"; |
|
|
|
|
console.warn(msg); |
|
|
|
|
globalOutputSettings = settings; |
|
|
|
|
return this |
|
|
|
|
return this; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var resemble = function(fileData) { |
|
|
|
|
var pixelTransparency = 1; |
|
|
|
|
|
|
|
|
|
var errorPixelColor = { // Color for Error Pixels. Between 0 and 255.
|
|
|
|
|
var errorPixelColor = { |
|
|
|
|
// Color for Error Pixels. Between 0 and 255.
|
|
|
|
|
red: 255, |
|
|
|
|
green: 0, |
|
|
|
|
blue: 255, |
|
|
|
@ -56,24 +61,37 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
var targetPix = { r: 0, g: 0, b: 0, a: 0 }; // isAntialiased
|
|
|
|
|
|
|
|
|
|
function colorsDistance(c1, c2) { |
|
|
|
|
return (Math.abs(c1.r - c2.r) + Math.abs(c1.g - c2.g) + Math.abs(c1.b - c2.b))/3; |
|
|
|
|
return ( |
|
|
|
|
(Math.abs(c1.r - c2.r) + |
|
|
|
|
Math.abs(c1.g - c2.g) + |
|
|
|
|
Math.abs(c1.b - c2.b)) / |
|
|
|
|
3 |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function withinBoundingBox(x, y, width, height, box) { |
|
|
|
|
return x > (box.left || 0) && |
|
|
|
|
return ( |
|
|
|
|
x > (box.left || 0) && |
|
|
|
|
x < (box.right || width) && |
|
|
|
|
y > (box.top || 0) && |
|
|
|
|
y < (box.bottom || height); |
|
|
|
|
y < (box.bottom || height) |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function withinComparedArea(x, y, width, height) { |
|
|
|
|
var isIncluded = true; |
|
|
|
|
|
|
|
|
|
if (boundingBox !== undefined && !withinBoundingBox(x, y, width, height, boundingBox)) { |
|
|
|
|
if ( |
|
|
|
|
boundingBox !== undefined && |
|
|
|
|
!withinBoundingBox(x, y, width, height, boundingBox) |
|
|
|
|
) { |
|
|
|
|
isIncluded = false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (ignoredBox !== undefined && withinBoundingBox(x, y, width, height, ignoredBox)) { |
|
|
|
|
if ( |
|
|
|
|
ignoredBox !== undefined && |
|
|
|
|
withinBoundingBox(x, y, width, height, ignoredBox) |
|
|
|
|
) { |
|
|
|
|
isIncluded = false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -88,9 +106,17 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
px[offset + 3] = errorPixelColor.alpha; |
|
|
|
|
}, |
|
|
|
|
movement: function(px, offset, d1, d2) { |
|
|
|
|
px[offset] = ((d2.r * (errorPixelColor.red / 255)) + errorPixelColor.red) / 2; |
|
|
|
|
px[offset + 1] = ((d2.g * (errorPixelColor.green / 255)) + errorPixelColor.green) / 2; |
|
|
|
|
px[offset + 2] = ((d2.b * (errorPixelColor.blue / 255)) + errorPixelColor.blue) / 2; |
|
|
|
|
px[offset] = |
|
|
|
|
(d2.r * (errorPixelColor.red / 255) + errorPixelColor.red) / |
|
|
|
|
2; |
|
|
|
|
px[offset + 1] = |
|
|
|
|
(d2.g * (errorPixelColor.green / 255) + |
|
|
|
|
errorPixelColor.green) / |
|
|
|
|
2; |
|
|
|
|
px[offset + 2] = |
|
|
|
|
(d2.b * (errorPixelColor.blue / 255) + |
|
|
|
|
errorPixelColor.blue) / |
|
|
|
|
2; |
|
|
|
|
px[offset + 3] = d2.a; |
|
|
|
|
}, |
|
|
|
|
flatDifferenceIntensity: function(px, offset, d1, d2) { |
|
|
|
@ -102,9 +128,15 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
movementDifferenceIntensity: function(px, offset, d1, d2) { |
|
|
|
|
var ratio = colorsDistance(d1, d2) / 255 * 0.8; |
|
|
|
|
|
|
|
|
|
px[offset] = ((1 - ratio) * (d2.r * (errorPixelColor.red / 255)) + ratio * errorPixelColor.red); |
|
|
|
|
px[offset + 1] = ((1 - ratio) * (d2.g * (errorPixelColor.green / 255)) + ratio * errorPixelColor.green); |
|
|
|
|
px[offset + 2] = ((1 - ratio) * (d2.b * (errorPixelColor.blue / 255)) + ratio * errorPixelColor.blue); |
|
|
|
|
px[offset] = |
|
|
|
|
(1 - ratio) * (d2.r * (errorPixelColor.red / 255)) + |
|
|
|
|
ratio * errorPixelColor.red; |
|
|
|
|
px[offset + 1] = |
|
|
|
|
(1 - ratio) * (d2.g * (errorPixelColor.green / 255)) + |
|
|
|
|
ratio * errorPixelColor.green; |
|
|
|
|
px[offset + 2] = |
|
|
|
|
(1 - ratio) * (d2.b * (errorPixelColor.blue / 255)) + |
|
|
|
|
ratio * errorPixelColor.blue; |
|
|
|
|
px[offset + 3] = d2.a; |
|
|
|
|
}, |
|
|
|
|
diffOnly: function(px, offset, d1, d2) { |
|
|
|
@ -125,7 +157,8 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
var images = []; |
|
|
|
|
var updateCallbackArray = []; |
|
|
|
|
|
|
|
|
|
var tolerance = { // between 0 and 255
|
|
|
|
|
var tolerance = { |
|
|
|
|
// between 0 and 255
|
|
|
|
|
red: 16, |
|
|
|
|
green: 16, |
|
|
|
|
blue: 16, |
|
|
|
@ -142,14 +175,15 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
var len = updateCallbackArray.length; |
|
|
|
|
var i; |
|
|
|
|
for (i = 0; i < len; i++) { |
|
|
|
|
if (typeof updateCallbackArray[i] === 'function'){ |
|
|
|
|
if (typeof updateCallbackArray[i] === "function") { |
|
|
|
|
updateCallbackArray[i](data); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function loop(w, h, callback) { |
|
|
|
|
var x,y; |
|
|
|
|
var x; |
|
|
|
|
var y; |
|
|
|
|
|
|
|
|
|
for (x = 0; x < w; x++) { |
|
|
|
|
for (y = 0; y < h; y++) { |
|
|
|
@ -159,7 +193,6 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function parseImage(sourceImageData, width, height) { |
|
|
|
|
|
|
|
|
|
var pixelCount = 0; |
|
|
|
|
var redTotal = 0; |
|
|
|
|
var greenTotal = 0; |
|
|
|
@ -177,11 +210,11 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
var alpha = sourceImageData[offset + 3]; |
|
|
|
|
var brightness = getBrightness(red, green, blue); |
|
|
|
|
|
|
|
|
|
if (red == green && red == blue && alpha) { |
|
|
|
|
if (red == 0) { |
|
|
|
|
blackTotal++ |
|
|
|
|
} else if (red == 255) { |
|
|
|
|
whiteTotal++ |
|
|
|
|
if (red === green && red === blue && alpha) { |
|
|
|
|
if (red === 0) { |
|
|
|
|
blackTotal++; |
|
|
|
|
} else if (red === 255) { |
|
|
|
|
whiteTotal++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -205,7 +238,7 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
triggerDataUpdate(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function loadImageData( fileData, callback ){ |
|
|
|
|
function loadImageData(fileDataForImage, callback) { |
|
|
|
|
var fileReader; |
|
|
|
|
var hiddenImage = new Img(); |
|
|
|
|
|
|
|
|
@ -214,7 +247,7 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (useCrossOrigin) { |
|
|
|
|
hiddenImage.setAttribute('crossorigin', 'anonymous'); |
|
|
|
|
hiddenImage.setAttribute("crossorigin", "anonymous"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
hiddenImage.onerror = function(err) { |
|
|
|
@ -228,14 +261,14 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
hiddenImage.onload = null; // fixes pollution between calls
|
|
|
|
|
hiddenImage.onerror = null; |
|
|
|
|
|
|
|
|
|
var hiddenCanvas = document.createElement('canvas'); |
|
|
|
|
var hiddenCanvas = document.createElement("canvas"); |
|
|
|
|
var imageData; |
|
|
|
|
|
|
|
|
|
// don't assign to hiddenImage, see https://github.com/Huddle/Resemble.js/pull/87/commits/300d43352a2845aad289b254bfbdc7cd6a37e2d7
|
|
|
|
|
var width = hiddenImage.width; |
|
|
|
|
var height = hiddenImage.height; |
|
|
|
|
|
|
|
|
|
if( scaleToSameSize && images.length == 1 ){ |
|
|
|
|
if (scaleToSameSize && images.length === 1) { |
|
|
|
|
width = images[0].width; |
|
|
|
|
height = images[0].height; |
|
|
|
|
} |
|
|
|
@ -243,46 +276,57 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
hiddenCanvas.width = width; |
|
|
|
|
hiddenCanvas.height = height; |
|
|
|
|
|
|
|
|
|
hiddenCanvas.getContext('2d').drawImage(hiddenImage, 0, 0, width, height); |
|
|
|
|
imageData = hiddenCanvas.getContext('2d').getImageData(0, 0, width, height); |
|
|
|
|
hiddenCanvas |
|
|
|
|
.getContext("2d") |
|
|
|
|
.drawImage(hiddenImage, 0, 0, width, height); |
|
|
|
|
imageData = hiddenCanvas |
|
|
|
|
.getContext("2d") |
|
|
|
|
.getImageData(0, 0, width, height); |
|
|
|
|
|
|
|
|
|
images.push(imageData); |
|
|
|
|
|
|
|
|
|
callback(imageData, width, height); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
if (typeof fileData === 'string') { |
|
|
|
|
hiddenImage.src = fileData; |
|
|
|
|
if (typeof fileDataForImage === "string") { |
|
|
|
|
hiddenImage.src = fileDataForImage; |
|
|
|
|
if (hiddenImage.complete && hiddenImage.naturalWidth > 0) { |
|
|
|
|
hiddenImage.onload(); |
|
|
|
|
} |
|
|
|
|
} else if (typeof fileData.data !== 'undefined' |
|
|
|
|
&& typeof fileData.width === 'number' |
|
|
|
|
&& typeof fileData.height === 'number') { |
|
|
|
|
|
|
|
|
|
images.push(fileData); |
|
|
|
|
|
|
|
|
|
callback(fileData, fileData.width, fileData.height); |
|
|
|
|
} else if (typeof Buffer !== 'undefined' && fileData instanceof Buffer){ |
|
|
|
|
} else if ( |
|
|
|
|
typeof fileDataForImage.data !== "undefined" && |
|
|
|
|
typeof fileDataForImage.width === "number" && |
|
|
|
|
typeof fileDataForImage.height === "number" |
|
|
|
|
) { |
|
|
|
|
images.push(fileDataForImage); |
|
|
|
|
|
|
|
|
|
callback( |
|
|
|
|
fileDataForImage, |
|
|
|
|
fileDataForImage.width, |
|
|
|
|
fileDataForImage.height |
|
|
|
|
); |
|
|
|
|
} else if ( |
|
|
|
|
typeof Buffer !== "undefined" && |
|
|
|
|
fileDataForImage instanceof Buffer |
|
|
|
|
) { |
|
|
|
|
// If we have Buffer, assume we're on Node+Canvas and its supported
|
|
|
|
|
hiddenImage.src = fileData; |
|
|
|
|
hiddenImage.src = fileDataForImage; |
|
|
|
|
} else { |
|
|
|
|
fileReader = new FileReader(); |
|
|
|
|
fileReader.onload = function(event) { |
|
|
|
|
hiddenImage.src = event.target.result; |
|
|
|
|
}; |
|
|
|
|
fileReader.readAsDataURL(fileData); |
|
|
|
|
fileReader.readAsDataURL(fileDataForImage); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function isColorSimilar(a, b, color) { |
|
|
|
|
|
|
|
|
|
var absDiff = Math.abs(a - b); |
|
|
|
|
|
|
|
|
|
if(typeof a === 'undefined'){ |
|
|
|
|
if (typeof a === "undefined") { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
if(typeof b === 'undefined'){ |
|
|
|
|
if (typeof b === "undefined") { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -290,14 +334,17 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
return true; |
|
|
|
|
} else if (absDiff < tolerance[color]) { |
|
|
|
|
return true; |
|
|
|
|
} else { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function isPixelBrightnessSimilar(d1, d2) { |
|
|
|
|
var alpha = isColorSimilar(d1.a, d2.a, 'alpha'); |
|
|
|
|
var brightness = isColorSimilar(d1.brightness, d2.brightness, 'minBrightness'); |
|
|
|
|
var alpha = isColorSimilar(d1.a, d2.a, "alpha"); |
|
|
|
|
var brightness = isColorSimilar( |
|
|
|
|
d1.brightness, |
|
|
|
|
d2.brightness, |
|
|
|
|
"minBrightness" |
|
|
|
|
); |
|
|
|
|
return brightness && alpha; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -313,43 +360,60 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function isRGBSimilar(d1, d2) { |
|
|
|
|
var red = isColorSimilar(d1.r,d2.r,'red'); |
|
|
|
|
var green = isColorSimilar(d1.g,d2.g,'green'); |
|
|
|
|
var blue = isColorSimilar(d1.b,d2.b,'blue'); |
|
|
|
|
var alpha = isColorSimilar(d1.a, d2.a, 'alpha'); |
|
|
|
|
var red = isColorSimilar(d1.r, d2.r, "red"); |
|
|
|
|
var green = isColorSimilar(d1.g, d2.g, "green"); |
|
|
|
|
var blue = isColorSimilar(d1.b, d2.b, "blue"); |
|
|
|
|
var alpha = isColorSimilar(d1.a, d2.a, "alpha"); |
|
|
|
|
|
|
|
|
|
return red && green && blue && alpha; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function isContrasting(d1, d2) { |
|
|
|
|
return Math.abs(d1.brightness - d2.brightness) > tolerance.maxBrightness; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function getHue(r,g,b){ |
|
|
|
|
|
|
|
|
|
r = r / 255; |
|
|
|
|
g = g / 255; |
|
|
|
|
b = b / 255; |
|
|
|
|
var max = Math.max(r, g, b), min = Math.min(r, g, b); |
|
|
|
|
return ( |
|
|
|
|
Math.abs(d1.brightness - d2.brightness) > |
|
|
|
|
tolerance.maxBrightness |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function getHue(red, green, blue) { |
|
|
|
|
var r = red / 255; |
|
|
|
|
var g = green / 255; |
|
|
|
|
var b = blue / 255; |
|
|
|
|
var max = Math.max(r, g, b); |
|
|
|
|
var min = Math.min(r, g, b); |
|
|
|
|
var h; |
|
|
|
|
var d; |
|
|
|
|
|
|
|
|
|
if (max == min){ |
|
|
|
|
if (max === min) { |
|
|
|
|
h = 0; // achromatic
|
|
|
|
|
} else { |
|
|
|
|
d = max - min; |
|
|
|
|
switch (max) { |
|
|
|
|
case r: h = (g - b) / d + (g < b ? 6 : 0); break; |
|
|
|
|
case g: h = (b - r) / d + 2; break; |
|
|
|
|
case b: h = (r - g) / d + 4; break; |
|
|
|
|
} |
|
|
|
|
case r: |
|
|
|
|
h = (g - b) / d + (g < b ? 6 : 0); |
|
|
|
|
break; |
|
|
|
|
case g: |
|
|
|
|
h = (b - r) / d + 2; |
|
|
|
|
break; |
|
|
|
|
case b: |
|
|
|
|
h = (r - g) / d + 4; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
h /= 6; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return h; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function isAntialiased(sourcePix, data, cacheSet, verticalPos, horizontalPos, width){ |
|
|
|
|
function isAntialiased( |
|
|
|
|
sourcePix, |
|
|
|
|
pix, |
|
|
|
|
cacheSet, |
|
|
|
|
verticalPos, |
|
|
|
|
horizontalPos, |
|
|
|
|
width |
|
|
|
|
) { |
|
|
|
|
var offset; |
|
|
|
|
var distance = 1; |
|
|
|
|
var i; |
|
|
|
@ -362,14 +426,14 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
|
|
|
|
|
for (i = distance * -1; i <= distance; i++) { |
|
|
|
|
for (j = distance * -1; j <= distance; j++) { |
|
|
|
|
|
|
|
|
|
if (i === 0 && j === 0) { |
|
|
|
|
// ignore source pixel
|
|
|
|
|
} else { |
|
|
|
|
offset = |
|
|
|
|
((verticalPos + j) * width + (horizontalPos + i)) * |
|
|
|
|
4; |
|
|
|
|
|
|
|
|
|
offset = ((verticalPos+j)*width + (horizontalPos+i)) * 4; |
|
|
|
|
|
|
|
|
|
if(!getPixelInfo(targetPix , data, offset, cacheSet)){ |
|
|
|
|
if (!getPixelInfo(targetPix, pix, offset, cacheSet)) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -388,7 +452,10 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
hasSiblingWithDifferentHue++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if( hasSiblingWithDifferentHue > 1 || hasHighContrastSibling > 1){ |
|
|
|
|
if ( |
|
|
|
|
hasSiblingWithDifferentHue > 1 || |
|
|
|
|
hasHighContrastSibling > 1 |
|
|
|
|
) { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -402,34 +469,34 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function copyPixel(px, offset, data){ |
|
|
|
|
if (errorType === 'diffOnly') { |
|
|
|
|
function copyPixel(px, offset, pix) { |
|
|
|
|
if (errorType === "diffOnly") { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
px[offset] = data.r; //r
|
|
|
|
|
px[offset + 1] = data.g; //g
|
|
|
|
|
px[offset + 2] = data.b; //b
|
|
|
|
|
px[offset + 3] = data.a * pixelTransparency; //a
|
|
|
|
|
px[offset] = pix.r; // r
|
|
|
|
|
px[offset + 1] = pix.g; // g
|
|
|
|
|
px[offset + 2] = pix.b; // b
|
|
|
|
|
px[offset + 3] = pix.a * pixelTransparency; // a
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function copyGrayScalePixel(px, offset, data){ |
|
|
|
|
if (errorType === 'diffOnly') { |
|
|
|
|
function copyGrayScalePixel(px, offset, pix) { |
|
|
|
|
if (errorType === "diffOnly") { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
px[offset] = data.brightness; //r
|
|
|
|
|
px[offset + 1] = data.brightness; //g
|
|
|
|
|
px[offset + 2] = data.brightness; //b
|
|
|
|
|
px[offset + 3] = data.a * pixelTransparency; //a
|
|
|
|
|
px[offset] = pix.brightness; // r
|
|
|
|
|
px[offset + 1] = pix.brightness; // g
|
|
|
|
|
px[offset + 2] = pix.brightness; // b
|
|
|
|
|
px[offset + 3] = pix.a * pixelTransparency; // a
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function getPixelInfo(dst, data, offset) { |
|
|
|
|
if (data.length > offset) { |
|
|
|
|
dst.r = data[offset]; |
|
|
|
|
dst.g = data[offset + 1]; |
|
|
|
|
dst.b = data[offset + 2]; |
|
|
|
|
dst.a = data[offset + 3]; |
|
|
|
|
function getPixelInfo(dst, pix, offset) { |
|
|
|
|
if (pix.length > offset) { |
|
|
|
|
dst.r = pix[offset]; |
|
|
|
|
dst.g = pix[offset + 1]; |
|
|
|
|
dst.b = pix[offset + 2]; |
|
|
|
|
dst.a = pix[offset + 3]; |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
@ -437,17 +504,16 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function addBrightnessInfo(data){ |
|
|
|
|
data.brightness = getBrightness(data.r,data.g,data.b); // 'corrected' lightness
|
|
|
|
|
function addBrightnessInfo(pix) { |
|
|
|
|
pix.brightness = getBrightness(pix.r, pix.g, pix.b); // 'corrected' lightness
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function addHueInfo(data){ |
|
|
|
|
data.h = getHue(data.r,data.g,data.b); |
|
|
|
|
function addHueInfo(pix) { |
|
|
|
|
pix.h = getHue(pix.r, pix.g, pix.b); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function analyseImages(img1, img2, width, height) { |
|
|
|
|
|
|
|
|
|
var hiddenCanvas = document.createElement('canvas'); |
|
|
|
|
var hiddenCanvas = document.createElement("canvas"); |
|
|
|
|
|
|
|
|
|
var data1 = img1.data; |
|
|
|
|
var data2 = img2.data; |
|
|
|
@ -455,9 +521,9 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
hiddenCanvas.width = width; |
|
|
|
|
hiddenCanvas.height = height; |
|
|
|
|
|
|
|
|
|
var context = hiddenCanvas.getContext('2d'); |
|
|
|
|
var context = hiddenCanvas.getContext("2d"); |
|
|
|
|
var imgd = context.createImageData(width, height); |
|
|
|
|
var targetPix = imgd.data; |
|
|
|
|
var pix = imgd.data; |
|
|
|
|
|
|
|
|
|
var mismatchCount = 0; |
|
|
|
|
var diffBounds = { |
|
|
|
@ -477,7 +543,11 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
|
|
|
|
|
var skip; |
|
|
|
|
|
|
|
|
|
if(!!largeImageThreshold && ignoreAntialiasing && (width > largeImageThreshold || height > largeImageThreshold)){ |
|
|
|
|
if ( |
|
|
|
|
!!largeImageThreshold && |
|
|
|
|
ignoreAntialiasing && |
|
|
|
|
(width > largeImageThreshold || height > largeImageThreshold) |
|
|
|
|
) { |
|
|
|
|
skip = 6; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -485,29 +555,42 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
var pixel2 = { r: 0, g: 0, b: 0, a: 0 }; |
|
|
|
|
|
|
|
|
|
loop(width, height, function(horizontalPos, verticalPos) { |
|
|
|
|
|
|
|
|
|
if(skip){ // only skip if the image isn't small
|
|
|
|
|
if(verticalPos % skip === 0 || horizontalPos % skip === 0){ |
|
|
|
|
if (skip) { |
|
|
|
|
// only skip if the image isn't small
|
|
|
|
|
if ( |
|
|
|
|
verticalPos % skip === 0 || |
|
|
|
|
horizontalPos % skip === 0 |
|
|
|
|
) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var offset = (verticalPos * width + horizontalPos) * 4; |
|
|
|
|
var isWithinComparedArea = withinComparedArea(horizontalPos, verticalPos, width, height); |
|
|
|
|
|
|
|
|
|
if (!getPixelInfo(pixel1, data1, offset, 1) || !getPixelInfo(pixel2, data2, offset, 2)) { |
|
|
|
|
var isWithinComparedArea = withinComparedArea( |
|
|
|
|
horizontalPos, |
|
|
|
|
verticalPos, |
|
|
|
|
width, |
|
|
|
|
height |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
if ( |
|
|
|
|
!getPixelInfo(pixel1, data1, offset, 1) || |
|
|
|
|
!getPixelInfo(pixel2, data2, offset, 2) |
|
|
|
|
) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (ignoreColors) { |
|
|
|
|
|
|
|
|
|
addBrightnessInfo(pixel1); |
|
|
|
|
addBrightnessInfo(pixel2); |
|
|
|
|
|
|
|
|
|
if( isPixelBrightnessSimilar(pixel1, pixel2) || !isWithinComparedArea ){ |
|
|
|
|
copyGrayScalePixel(targetPix, offset, pixel2); |
|
|
|
|
if ( |
|
|
|
|
isPixelBrightnessSimilar(pixel1, pixel2) || |
|
|
|
|
!isWithinComparedArea |
|
|
|
|
) { |
|
|
|
|
copyGrayScalePixel(pix, offset, pixel2); |
|
|
|
|
} else { |
|
|
|
|
errorPixel(targetPix, offset, pixel1, pixel2); |
|
|
|
|
errorPixel(pix, offset, pixel1, pixel2); |
|
|
|
|
mismatchCount++; |
|
|
|
|
updateBounds(horizontalPos, verticalPos); |
|
|
|
|
} |
|
|
|
@ -515,31 +598,46 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (isRGBSimilar(pixel1, pixel2) || !isWithinComparedArea) { |
|
|
|
|
copyPixel(targetPix, offset, pixel1); |
|
|
|
|
|
|
|
|
|
} else if( ignoreAntialiasing && ( |
|
|
|
|
addBrightnessInfo(pixel1), // jit pixel info augmentation looks a little weird, sorry.
|
|
|
|
|
copyPixel(pix, offset, pixel1); |
|
|
|
|
} else if ( |
|
|
|
|
ignoreAntialiasing && |
|
|
|
|
(addBrightnessInfo(pixel1), // jit pixel info augmentation looks a little weird, sorry.
|
|
|
|
|
addBrightnessInfo(pixel2), |
|
|
|
|
isAntialiased(pixel1, data1, 1, verticalPos, horizontalPos, width) || |
|
|
|
|
isAntialiased(pixel2, data2, 2, verticalPos, horizontalPos, width) |
|
|
|
|
)){ |
|
|
|
|
|
|
|
|
|
if( isPixelBrightnessSimilar(pixel1, pixel2) || !isWithinComparedArea ){ |
|
|
|
|
copyGrayScalePixel(targetPix, offset, pixel2); |
|
|
|
|
isAntialiased( |
|
|
|
|
pixel1, |
|
|
|
|
data1, |
|
|
|
|
1, |
|
|
|
|
verticalPos, |
|
|
|
|
horizontalPos, |
|
|
|
|
width |
|
|
|
|
) || |
|
|
|
|
isAntialiased( |
|
|
|
|
pixel2, |
|
|
|
|
data2, |
|
|
|
|
2, |
|
|
|
|
verticalPos, |
|
|
|
|
horizontalPos, |
|
|
|
|
width |
|
|
|
|
)) |
|
|
|
|
) { |
|
|
|
|
if ( |
|
|
|
|
isPixelBrightnessSimilar(pixel1, pixel2) || |
|
|
|
|
!isWithinComparedArea |
|
|
|
|
) { |
|
|
|
|
copyGrayScalePixel(pix, offset, pixel2); |
|
|
|
|
} else { |
|
|
|
|
errorPixel(targetPix, offset, pixel1, pixel2); |
|
|
|
|
errorPixel(pix, offset, pixel1, pixel2); |
|
|
|
|
mismatchCount++; |
|
|
|
|
updateBounds(horizontalPos, verticalPos); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
errorPixel(targetPix, offset, pixel1, pixel2); |
|
|
|
|
errorPixel(pix, offset, pixel1, pixel2); |
|
|
|
|
mismatchCount++; |
|
|
|
|
updateBounds(horizontalPos, verticalPos); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
data.rawMisMatchPercentage = (mismatchCount / (height*width) * 100); |
|
|
|
|
data.rawMisMatchPercentage = mismatchCount / (height * width) * 100; |
|
|
|
|
data.misMatchPercentage = data.rawMisMatchPercentage.toFixed(2); |
|
|
|
|
data.diffBounds = diffBounds; |
|
|
|
|
data.analysisTime = Date.now() - time; |
|
|
|
@ -568,14 +666,14 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
context.putImageData(imgd, 0, 0); |
|
|
|
|
} |
|
|
|
|
return hiddenCanvas.toBuffer(); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function addLabel(text, context, hiddenCanvas) { |
|
|
|
|
var textPadding = 2; |
|
|
|
|
|
|
|
|
|
context.font = '12px sans-serif'; |
|
|
|
|
context.font = "12px sans-serif"; |
|
|
|
|
|
|
|
|
|
var textWidth = context.measureText(text).width + textPadding * 2; |
|
|
|
|
var barHeight = 22; |
|
|
|
@ -593,7 +691,7 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
|
|
|
|
|
context.fillStyle = "#fff"; |
|
|
|
|
context.textBaseline = "top"; |
|
|
|
|
context.font = '12px sans-serif'; |
|
|
|
|
context.font = "12px sans-serif"; |
|
|
|
|
context.fillText(text, textPadding, 1); |
|
|
|
|
|
|
|
|
|
return barHeight; |
|
|
|
@ -604,10 +702,10 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
var context; |
|
|
|
|
|
|
|
|
|
if (img.height < h || img.width < w) { |
|
|
|
|
c = document.createElement('canvas'); |
|
|
|
|
c = document.createElement("canvas"); |
|
|
|
|
c.width = w; |
|
|
|
|
c.height = h; |
|
|
|
|
context = c.getContext('2d'); |
|
|
|
|
context = c.getContext("2d"); |
|
|
|
|
context.putImageData(img, 0, 0); |
|
|
|
|
return context.getImageData(0, 0, w, h); |
|
|
|
|
} |
|
|
|
@ -617,11 +715,15 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
|
|
|
|
|
function outputSettings(options) { |
|
|
|
|
var key; |
|
|
|
|
var undefined; |
|
|
|
|
|
|
|
|
|
if (options.errorColor) { |
|
|
|
|
for (key in options.errorColor) { |
|
|
|
|
errorPixelColor[key] = options.errorColor[key] === undefined ? errorPixelColor[key] : options.errorColor[key]; |
|
|
|
|
if (options.hasOwnProperty(key)) { |
|
|
|
|
errorPixelColor[key] = |
|
|
|
|
options.errorColor[key] === void 0 |
|
|
|
|
? errorPixelColor[key] |
|
|
|
|
: options.errorColor[key]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -630,11 +732,16 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
errorType = options.errorType; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(options.errorPixel && typeof options.errorPixel === "function") { |
|
|
|
|
if ( |
|
|
|
|
options.errorPixel && |
|
|
|
|
typeof options.errorPixel === "function" |
|
|
|
|
) { |
|
|
|
|
errorPixel = options.errorPixel; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pixelTransparency = isNaN(Number(options.transparency)) ? pixelTransparency : options.transparency; |
|
|
|
|
pixelTransparency = isNaN(Number(options.transparency)) |
|
|
|
|
? pixelTransparency |
|
|
|
|
: options.transparency; |
|
|
|
|
|
|
|
|
|
if (options.largeImageThreshold !== undefined) { |
|
|
|
|
largeImageThreshold = options.largeImageThreshold; |
|
|
|
@ -651,7 +758,6 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
if (options.ignoredBox !== undefined) { |
|
|
|
|
ignoredBox = options.ignoredBox; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function compare(one, two) { |
|
|
|
@ -665,22 +771,41 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
if (images.length === 2) { |
|
|
|
|
if (images[0].error || images[1].error) { |
|
|
|
|
data = {}; |
|
|
|
|
data.error = images[0].error ? images[0].error : images[1].error; |
|
|
|
|
data.error = images[0].error |
|
|
|
|
? images[0].error |
|
|
|
|
: images[1].error; |
|
|
|
|
triggerDataUpdate(); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
width = images[0].width > images[1].width ? images[0].width : images[1].width; |
|
|
|
|
height = images[0].height > images[1].height ? images[0].height : images[1].height; |
|
|
|
|
|
|
|
|
|
if( (images[0].width === images[1].width) && (images[0].height === images[1].height) ){ |
|
|
|
|
width = |
|
|
|
|
images[0].width > images[1].width |
|
|
|
|
? images[0].width |
|
|
|
|
: images[1].width; |
|
|
|
|
height = |
|
|
|
|
images[0].height > images[1].height |
|
|
|
|
? images[0].height |
|
|
|
|
: images[1].height; |
|
|
|
|
|
|
|
|
|
if ( |
|
|
|
|
images[0].width === images[1].width && |
|
|
|
|
images[0].height === images[1].height |
|
|
|
|
) { |
|
|
|
|
data.isSameDimensions = true; |
|
|
|
|
} else { |
|
|
|
|
data.isSameDimensions = false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
data.dimensionDifference = { width: images[0].width - images[1].width, height: images[0].height - images[1].height }; |
|
|
|
|
data.dimensionDifference = { |
|
|
|
|
width: images[0].width - images[1].width, |
|
|
|
|
height: images[0].height - images[1].height |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
analyseImages( normalise(images[0],width, height), normalise(images[1],width, height), width, height); |
|
|
|
|
analyseImages( |
|
|
|
|
normalise(images[0], width, height), |
|
|
|
|
normalise(images[1], width, height), |
|
|
|
|
width, |
|
|
|
|
height |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
triggerDataUpdate(); |
|
|
|
|
} |
|
|
|
@ -692,9 +817,8 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function getCompareApi(param) { |
|
|
|
|
|
|
|
|
|
var secondFileData, |
|
|
|
|
hasMethod = typeof param === 'function'; |
|
|
|
|
var secondFileData; |
|
|
|
|
var hasMethod = typeof param === "function"; |
|
|
|
|
|
|
|
|
|
if (!hasMethod) { |
|
|
|
|
// assume it's file data
|
|
|
|
@ -705,17 +829,20 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
scaleToSameSize: function() { |
|
|
|
|
scaleToSameSize = true; |
|
|
|
|
|
|
|
|
|
if(hasMethod) { param(); } |
|
|
|
|
if (hasMethod) { |
|
|
|
|
param(); |
|
|
|
|
} |
|
|
|
|
return self; |
|
|
|
|
}, |
|
|
|
|
useOriginalSize: function() { |
|
|
|
|
scaleToSameSize = false; |
|
|
|
|
|
|
|
|
|
if(hasMethod) { param(); } |
|
|
|
|
if (hasMethod) { |
|
|
|
|
param(); |
|
|
|
|
} |
|
|
|
|
return self; |
|
|
|
|
}, |
|
|
|
|
ignoreNothing: function() { |
|
|
|
|
|
|
|
|
|
tolerance.red = 0; |
|
|
|
|
tolerance.green = 0; |
|
|
|
|
tolerance.blue = 0; |
|
|
|
@ -726,11 +853,12 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
ignoreAntialiasing = false; |
|
|
|
|
ignoreColors = false; |
|
|
|
|
|
|
|
|
|
if(hasMethod) { param(); } |
|
|
|
|
if (hasMethod) { |
|
|
|
|
param(); |
|
|
|
|
} |
|
|
|
|
return self; |
|
|
|
|
}, |
|
|
|
|
ignoreLess: function() { |
|
|
|
|
|
|
|
|
|
tolerance.red = 16; |
|
|
|
|
tolerance.green = 16; |
|
|
|
|
tolerance.blue = 16; |
|
|
|
@ -741,11 +869,12 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
ignoreAntialiasing = false; |
|
|
|
|
ignoreColors = false; |
|
|
|
|
|
|
|
|
|
if(hasMethod) { param(); } |
|
|
|
|
if (hasMethod) { |
|
|
|
|
param(); |
|
|
|
|
} |
|
|
|
|
return self; |
|
|
|
|
}, |
|
|
|
|
ignoreAntialiasing: function() { |
|
|
|
|
|
|
|
|
|
tolerance.red = 32; |
|
|
|
|
tolerance.green = 32; |
|
|
|
|
tolerance.blue = 32; |
|
|
|
@ -756,11 +885,12 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
ignoreAntialiasing = true; |
|
|
|
|
ignoreColors = false; |
|
|
|
|
|
|
|
|
|
if(hasMethod) { param(); } |
|
|
|
|
if (hasMethod) { |
|
|
|
|
param(); |
|
|
|
|
} |
|
|
|
|
return self; |
|
|
|
|
}, |
|
|
|
|
ignoreColors: function() { |
|
|
|
|
|
|
|
|
|
tolerance.alpha = 16; |
|
|
|
|
tolerance.minBrightness = 16; |
|
|
|
|
tolerance.maxBrightness = 240; |
|
|
|
@ -768,11 +898,12 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
ignoreAntialiasing = false; |
|
|
|
|
ignoreColors = true; |
|
|
|
|
|
|
|
|
|
if(hasMethod) { param(); } |
|
|
|
|
if (hasMethod) { |
|
|
|
|
param(); |
|
|
|
|
} |
|
|
|
|
return self; |
|
|
|
|
}, |
|
|
|
|
ignoreAlpha: function() { |
|
|
|
|
|
|
|
|
|
tolerance.red = 16; |
|
|
|
|
tolerance.green = 16; |
|
|
|
|
tolerance.blue = 16; |
|
|
|
@ -783,11 +914,15 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
ignoreAntialiasing = false; |
|
|
|
|
ignoreColors = false; |
|
|
|
|
|
|
|
|
|
if(hasMethod) { param(); } |
|
|
|
|
if (hasMethod) { |
|
|
|
|
param(); |
|
|
|
|
} |
|
|
|
|
return self; |
|
|
|
|
}, |
|
|
|
|
repaint: function() { |
|
|
|
|
if(hasMethod) { param(); } |
|
|
|
|
if (hasMethod) { |
|
|
|
|
param(); |
|
|
|
|
} |
|
|
|
|
return self; |
|
|
|
|
}, |
|
|
|
|
outputSettings: function(options) { |
|
|
|
@ -795,7 +930,6 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
return self; |
|
|
|
|
}, |
|
|
|
|
onComplete: function(callback) { |
|
|
|
|
|
|
|
|
|
updateCallbackArray.push(callback); |
|
|
|
|
|
|
|
|
|
var wrapper = function() { |
|
|
|
@ -831,34 +965,40 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
|
|
|
|
|
function applyIgnore(api, ignore) { |
|
|
|
|
switch (ignore) { |
|
|
|
|
case 'nothing': |
|
|
|
|
case "nothing": |
|
|
|
|
api.ignoreNothing(); |
|
|
|
|
break; |
|
|
|
|
case 'less': |
|
|
|
|
case "less": |
|
|
|
|
api.ignoreLess(); |
|
|
|
|
break; |
|
|
|
|
case 'antialiasing': |
|
|
|
|
case "antialiasing": |
|
|
|
|
api.ignoreAntialiasing(); |
|
|
|
|
break; |
|
|
|
|
case 'colors': |
|
|
|
|
case "colors": |
|
|
|
|
api.ignoreColors(); |
|
|
|
|
break; |
|
|
|
|
case 'alpha': |
|
|
|
|
case "alpha": |
|
|
|
|
api.ignoreAlpha(); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
throw new Error('Invalid ignore: ' + ignore); |
|
|
|
|
break; |
|
|
|
|
throw new Error("Invalid ignore: " + ignore); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
resemble.compare = function (image1, image2, options, callback) { |
|
|
|
|
if (typeof options === 'function') { |
|
|
|
|
resemble.compare = function(image1, image2, options, cb) { |
|
|
|
|
let callback; |
|
|
|
|
let opt; |
|
|
|
|
|
|
|
|
|
if (typeof options === "function") { |
|
|
|
|
callback = options; |
|
|
|
|
options = undefined; |
|
|
|
|
opt = {}; |
|
|
|
|
} else { |
|
|
|
|
callback = cb; |
|
|
|
|
opt = options || {}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var res = resemble(image1), opt = options || {}, compare; |
|
|
|
|
var res = resemble(image1); |
|
|
|
|
var compare; |
|
|
|
|
|
|
|
|
|
if (opt.output) { |
|
|
|
|
res.outputSettings(opt.output); |
|
|
|
@ -870,7 +1010,7 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
compare.scaleToSameSize(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (typeof opt.ignore === 'string') { |
|
|
|
|
if (typeof opt.ignore === "string") { |
|
|
|
|
applyIgnore(compare, opt.ignore); |
|
|
|
|
} else if (opt.ignore && opt.ignore.forEach) { |
|
|
|
|
opt.ignore.forEach(function(v) { |
|
|
|
@ -889,4 +1029,4 @@ URL: https://github.com/Huddle/Resemble.js
|
|
|
|
|
|
|
|
|
|
resemble.outputSettings = setGlobalOutputSettings; |
|
|
|
|
return resemble; |
|
|
|
|
})); |
|
|
|
|
}); |
|
|
|
|