Browse Source

I think antialising is working

pull/6/merge
James Cryer 12 years ago
parent
commit
f0a15916b6
  1. 29
      demoassets/main.js
  2. 7
      index.html
  3. 335
      resemble.js

29
demoassets/main.js

@ -58,6 +58,8 @@ $(function(){
window.open(diffImage.src, '_blank');
});
$('#button').show();
if(data.misMatchPercentage == 0){
$('#thesame').show();
$('#diff-results').hide();
@ -75,16 +77,39 @@ $(function(){
var file1;
var file2;
var resembleControl;
dropZone($('#dropzone1'), function(file){
file1 = file;
if(file2){
resemble(file).compareTo(file2).onComplete(onComplete);
resembleControl = resemble(file).compareTo(file2).onComplete(onComplete);
}
});
dropZone($('#dropzone2'), function(file){
file2 = file;
if(file1){
resemble(file).compareTo(file1).onComplete(onComplete);
resembleControl = resemble(file).compareTo(file1).onComplete(onComplete);
}
});
var buttons = $('#raw, #colors, #antialising');
buttons.click(function(){
var $this = $(this);
buttons.removeClass('active');
$this.addClass('active');
if($this.is('#raw')){
resembleControl.ignoreNothing();
}
else
if($this.is('#colors')){
resembleControl.ignoreColors();
}
else
if($this.is('#antialising')){
resembleControl.ignoreAntialiasing();
}
});

7
index.html

@ -81,6 +81,13 @@
Diff will appear here.
</div>
<br/>
<div class="btn-group" id="buttons">
<button class="btn active" id="raw">Ignore nothing</button>
<button class="btn" id="colors">Ignore colors</button>
<button class="btn" id="antialising">Ignore antialiasing</button>
</div>
<br/>
<br/>
<p id="diff-results" style="display:none;">
<strong>The second image is <span id="mismatch"></span>% different compared to the first.
<span id="differentdimensions" style="display:none;">And they have different dimensions.</span></strong>

335
resemble.js

@ -6,13 +6,17 @@
var images = [];
var updateCallbackArray = [];
var tolerance = [ // between 0 and 255
255, // red
255, // green 16
255, // blue 24
255, // alpha
255 // brightness
];
var tolerance = { // between 0 and 255
red: 16,
green: 16,
blue: 16,
minBrightness: 16,
maxBrightness: 240
};
var ignoreAntialiasing = false;
var ignoreColors = false;
var skip = false;
function triggerDataUpdate(){
var len = updateCallbackArray.length;
@ -46,8 +50,7 @@
var red = sourceImageData[offset];
var green = sourceImageData[offset + 1];
var blue = sourceImageData[offset + 2];
var alpha = sourceImageData[offset + 3];
var brightness = (0.3*red + 0.59*green + 0.11*blue);
var brightness = getBrightness(red,green,blue);
pixleCount++;
@ -93,9 +96,7 @@
fileReader.readAsDataURL(fileData);
}
function isPixelDifferent(d1, d2, off, plus){
var a = d1[off + plus];
var b = d2[off + plus];
function isColorSimilar(a, b, color){
var absDiff = Math.abs(a - b);
@ -108,34 +109,175 @@
if(a === b){
return true;
} else if ( absDiff < tolerance[plus] ) {
} else if ( absDiff < tolerance[color] ) {
return true;
} else {
return false;
}
}
function compareBrightness(data1, data2, offset){
var red1 = data1[offset + 0];
var green1 = data1[offset + 1];
var blue1 = data1[offset + 2];
function isNumber(n) {
return !isNaN(parseFloat(n));
}
function isPixelBrightnessSimilar(d1, d2){
return Math.abs(d1.brightness - d2.brightness) < tolerance.minBrightness;
}
function getBrightness(r,g,b){
return 0.3*r + 0.59*g + 0.11*b;
}
function isRGBSame(d1,d2){
var red = d1.r === d2.r;
var green = d1.g === d2.g;
var blue = d1.b === d2.b;
return red && green && blue;
}
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 red2 = data2[offset + 0];
var green2 = data2[offset + 1];
var blue2 = data2[offset + 2];
return red && green && blue;
}
function isContrasting(d1, d2){
return Math.abs(d1.brightness - d2.brightness) > tolerance.maxBrightness;
}
function getHsl(data, offset){
var r = data[offset] / 255;
var g = data[offset+1] / 255;
var b = data[offset+2] / 255;
var max = Math.max(r, g, b), min = Math.min(r, g, b);
var h;
var s;
var l = (max + min) / 2;
var d;
if (max == min){
h = s = 0; // achromatic
} else{
d = max - min;
s = l > 0.5 ? d / (2 - max - min) : 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;
}
h /= 6;
}
var brightness1;
var brightness2;
return { // values between 0 and 1
hue: h,
saturation: s,
lightness: l
};
}
if(red1 && green1 && blue1 && red2 && green2 && blue2){
function isAntialiased(sourcePix, data, cacheSet, verticalPos, horizontalPos, width){
var offset;
var targetPix;
var distance = 1;
var i;
var j;
var hasHighContrastSibling = 0;
var hasSiblingWithDifferentHue = 0;
var hasEquivilantSibling = 0;
brightness1 = (0.3*red1 + 0.59*green1 + 0.11*blue1);
brightness2 = (0.3*red2 + 0.59*green2 + 0.11*blue2);
for (i = distance*-1; i <= distance; i++){
for (j = distance*-1; j <= distance; j++){
return Math.abs(brightness1 - brightness2) < tolerance[4];
if(i===0 && j===0){
// ignore source pixel
} else {
offset = ((verticalPos+j)*width + (horizontalPos+i)) * 4;
targetPix = getRGBAndHSL(data, offset, cacheSet);
if(targetPix === null){
continue;
}
if( isContrasting(sourcePix, targetPix) ){
hasHighContrastSibling++;
}
if( isRGBSame(sourcePix,targetPix) ){
hasEquivilantSibling++;
}
if( Math.abs(targetPix.h - sourcePix.h) > 0.3 ){
hasSiblingWithDifferentHue++;
}
if( hasSiblingWithDifferentHue > 1 || hasHighContrastSibling > 1 || hasEquivilantSibling === 0){
return true;
}
}
}
}
return false;
}
function errorPixel(px, offset){
px[offset] = 255; //r
px[offset + 1] = 0; //g
px[offset + 2] = 255; //b
px[offset + 3] = 255; //a
}
function copyPixel(px, offset, data){
px[offset] = data.r; //r
px[offset + 1] = data.g; //g
px[offset + 2] = data.b; //b
px[offset + 3] = 255; //a
}
function copyGrayScalePixel(px, offset, data){
px[offset] = data.brightness; //r
px[offset + 1] = data.brightness; //g
px[offset + 2] = data.brightness; //b
px[offset + 3] = 255; //a
}
var cache = [];
function getRGBAndHSL(data, offset, cacheSet){
var hsl;
var r;
var g;
var b;
var d;
if(cache[cacheSet] && cache[cacheSet][offset]){
return cache[cacheSet][offset];
} else {
return false;
if(typeof data[offset] !== 'undefined'){
hsl = getHsl(data, offset);
r = data[offset];
g = data[offset+1];
b = data[offset+2];
d = {
r: r,
g: g,
b: b,
h: hsl.hue,
s: hsl.saturation,
l: hsl.lightness,
brightness: getBrightness(r,g,b) // 'corrected' lightness
};
if(!cache[cacheSet]){
cache[cacheSet] = [];
}
cache[cacheSet][offset] = d;
return d;
} else {
return null;
}
}
}
@ -151,39 +293,67 @@
var context = hiddenCanvas.getContext('2d');
var imgd = context.createImageData(width,height);
var pix = imgd.data;
var targetPix = imgd.data;
var mismatchCount = 0;
var isAntialiasedCount = 0;
var isBrightnessCount = 0;
loop(height, width, function(verticalPos, horizontalPos){
var offset = (verticalPos*width + horizontalPos) * 4;
var red = isPixelDifferent(data1, data2, offset, 0);
var green = isPixelDifferent(data1, data2, offset, 1);
var blue = isPixelDifferent(data1, data2, offset, 2);
var alpha = isPixelDifferent(data1, data2, offset, 3);
var pixel1 = getRGBAndHSL(data1, offset, 1);
var brightness = compareBrightness(data1, data2, offset);
if(skip){
if(verticalPos % skip === 0 || horizontalPos % skip === 0){
copyGrayScalePixel(targetPix, offset, pixel1);
return;
}
}
if(brightness && red && green && blue){
var pixel2 = getRGBAndHSL(data2, offset, 2);
pix[offset] = data1[offset + 0];
pix[offset + 1] = data1[offset + 1];
pix[offset + 2] = data1[offset + 2];
pix[offset + 3] = data1[offset + 3];
if(pixel1 === null || pixel2 === null){
return;
}
} else {
pix[offset] = 255;
pix[offset + 1] = 0;
pix[offset + 2] = 255;
pix[offset + 3] = 255;
if (ignoreColors){
if( isPixelBrightnessSimilar(pixel1, pixel2) ){
copyGrayScalePixel(targetPix, offset, pixel2);
} else {
errorPixel(targetPix, offset);
mismatchCount++;
}
return;
}
if( isRGBSimilar(pixel1, pixel2) ){
copyPixel(targetPix, offset, pixel2);
} else if( ignoreAntialiasing &&
(isAntialiased(pixel1, data1, 1, verticalPos, horizontalPos, width) ||
isAntialiased(pixel2, data2, 2, verticalPos, horizontalPos, width)) ){
isAntialiasedCount++;
if( isPixelBrightnessSimilar(pixel1, pixel2) ){
isBrightnessCount++;
copyGrayScalePixel(targetPix, offset, pixel2);
} else {
errorPixel(targetPix, offset);
mismatchCount++;
}
} else {
errorPixel(targetPix, offset);
mismatchCount++;
}
});
context.putImageData(imgd, 0,0);
cache = [];
data.misMatchPercentage = (mismatchCount / (height*width) * 100).toFixed(2);
data.imageDiffFileData = hiddenCanvas.toDataURL("image/png");
}
@ -209,10 +379,82 @@
}
}
images = [];
loadImageData(one, onceWeHaveBoth);
loadImageData(two, onceWeHaveBoth);
}
function getCompareApi(param){
var hasMethod = typeof param === 'function';
if( !hasMethod ){
// assume it's file data
secondFileData = param;
}
var self = {
ignoreNothing: function(){
tolerance.red = 16;
tolerance.green = 16;
tolerance.blue = 16;
tolerance.minBrightness = 16;
tolerance.maxBrightness = 240;
ignoreAntialiasing = false;
ignoreColors = false;
skip = false;
if(hasMethod) { param(); }
return self;
},
ignoreAntialiasing: function(){
tolerance.red = 24;
tolerance.green = 24;
tolerance.blue = 24;
tolerance.minBrightness = 64;
tolerance.maxBrightness = 96;
ignoreAntialiasing = true;
ignoreColors = false;
skip = 4;
if(hasMethod) { param(); }
return self;
},
ignoreColors: function(){
tolerance.minBrightness = 16;
tolerance.maxBrightness = 240;
ignoreAntialiasing = false;
ignoreColors = true;
skip = false;
if(hasMethod) { param(); }
return self;
},
onComplete: function( callback ){
updateCallbackArray.push(callback);
var wrapper = function(){
compare(fileData, secondFileData);
};
wrapper();
return getCompareApi(wrapper);
}
};
return self;
}
return {
onComplete: function( callback ){
updateCallbackArray.push(callback);
@ -221,12 +463,7 @@
});
},
compareTo: function(secondFileData){
return {
onComplete: function( callback ){
updateCallbackArray.push(callback);
compare(fileData, secondFileData);
}
};
return getCompareApi(secondFileData);
}
};

Loading…
Cancel
Save