Skip to content

Instantly share code, notes, and snippets.

@ukyo
Created April 24, 2019 03:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ukyo/43b89eece3df1e4f7eb159bdbdf3b824 to your computer and use it in GitHub Desktop.
Save ukyo/43b89eece3df1e4f7eb159bdbdf3b824 to your computer and use it in GitHub Desktop.
wip pixelmatch.ts
export function pixelmatch(img1: u32, img2: u32, width: u32, height: u32): u32 {
let maxDelta = (35215 as f32) * 0.1 * 0.1;
let diff = 0;
for (let y: u32 = 0; y < height; y++) {
for (let x: u32 = 0; x < width; x++) {
let pos = (y * width + x) * 4;
let delta = colorDelta(img1, img2, pos, pos, false);
if (delta > maxDelta) {
diff++;
drawPixel(img1 + img2, pos, 255, 0, 0);
} else {
let val = grayPixel(pos, 0.1) as u32;
drawPixel(img1 + img2, pos, val, val, val);
}
}
}
return diff;
}
@inline
function colorDelta(img1: u32, img2: u32, k: u32, m: u32, yOnly: bool): f32 {
let pos = k + img1;
let r1u8 = load<u8>(pos, 0);
let g1u8 = load<u8>(pos, 1);
let b1u8 = load<u8>(pos, 2);
let a1u8 = load<u8>(pos, 3);
pos = m + img2;
let r2u8 = load<u8>(pos, 0);
let g2u8 = load<u8>(pos, 1);
let b2u8 = load<u8>(pos, 2);
let a2u8 = load<u8>(pos, 3);
if (a1u8 === a2u8 && r1u8 === r2u8 && g1u8 === g2u8 && b1u8 === b2u8) return 0.0;
let r1 = r1u8 as f32;
let g1 = g1u8 as f32;
let b1 = b1u8 as f32;
let a1 = a1u8 as f32;
let r2 = r2u8 as f32;
let g2 = g2u8 as f32;
let b2 = b2u8 as f32;
let a2 = a2u8 as f32;
if (a1 < 255) {
a1 = a1 / 255;
r1 = blend(r1, a1);
g1 = blend(g1, a1);
b1 = blend(b1, a1);
}
if (a2 < 255) {
a2 = a2 / 255;
r2 = blend(r2, a2);
g2 = blend(g2, a2);
b2 = blend(b2, a2);
}
let y = rgb2y(r1, g1, b1) - rgb2y(r2, g2, b2);
if (yOnly) return y; // brightness difference only
let i = rgb2i(r1, g1, b1) - rgb2i(r2, g2, b2);
let q = rgb2q(r1, g1, b1) - rgb2q(r2, g2, b2);
return 0.5053 * y * y + 0.299 * i * i + 0.1957 * q * q;
}
@inline
function blend(c: f32, a: f32): f32 {
return 255.0 + (c - 255.0) * a;
}
@inline
function rgb2y(r: f32, g: f32, b: f32): f32 {
return r * 0.29889531 + g * 0.58662247 + b * 0.11448223;
}
@inline
function rgb2i(r: f32, g: f32, b: f32): f32 {
return r * 0.59597799 - g * 0.2741761 - b * 0.32180189;
}
@inline
function rgb2q(r: f32, g: f32, b: f32): f32 {
return r * 0.21147017 - g * 0.52261711 + b * 0.31114694;
}
@inline
function drawPixel(offset: u32, pos: u32, r: u32, g: u32, b: u32): void {
pos = pos + offset;
store<u8>(pos, r, 0);
store<u8>(pos, g, 1);
store<u8>(pos, b, 2);
store<u8>(pos, 255, 3);
}
@inline
function grayPixel(i: u32, alpha: f32): f32 {
let r = load<u8>(i, 0) as f32;
let g = load<u8>(i, 1) as f32;
let b = load<u8>(i, 2) as f32;
let a = load<u8>(i, 3) as f32;
return blend(rgb2y(r, g, b), (alpha * a) / 255.0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment