Created
April 24, 2019 03:38
-
-
Save ukyo/43b89eece3df1e4f7eb159bdbdf3b824 to your computer and use it in GitHub Desktop.
wip pixelmatch.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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