pixelmatch
Advanced tools
Comparing version 3.0.0 to 4.0.0
65
index.js
@@ -11,4 +11,5 @@ 'use strict'; | ||
// maximum acceptable square YUV distance between two colors | ||
var maxDelta = 255 * 255 * 3 * threshold * threshold, | ||
// maximum acceptable square distance between two colors; | ||
// 35215 is the maximum possible value for the YIQ difference metric | ||
var maxDelta = 35215 * threshold * threshold, | ||
diff = 0; | ||
@@ -31,13 +32,13 @@ | ||
// one of the pixels is anti-aliasing; draw as yellow and do not count as difference | ||
drawPixel(output, pos, 255, 255, 0); | ||
if (output) drawPixel(output, pos, 255, 255, 0); | ||
} else { | ||
// found substantial difference not caused by anti-aliasing; draw it as red | ||
drawPixel(output, pos, 255, 0, 0); | ||
if (output) drawPixel(output, pos, 255, 0, 0); | ||
diff++; | ||
} | ||
} else { | ||
} else if (output) { | ||
// pixels are similar; draw background as grayscale image blended with white | ||
var val = 255 - 0.1 * (255 - grayPixel(img1, pos)) * img1[pos + 3] / 255; | ||
var val = blend(grayPixel(img1, pos), 0.1); | ||
drawPixel(output, pos, val, val, val); | ||
@@ -112,28 +113,34 @@ } | ||
// calculate either the squared YUV distance between colors, | ||
// or just the brightness differene (Y component) if yOnly is true | ||
// calculate color difference according to the paper "Measuring perceived color difference | ||
// using YIQ NTSC transmission color space in mobile applications" by Y. Kotsarenko and F. Ramos | ||
function colorDelta(img1, img2, i, j, yOnly) { | ||
var a1 = img1[i + 3] / 255, | ||
a2 = img2[j + 3] / 255, | ||
function colorDelta(img1, img2, k, m, yOnly) { | ||
var a1 = img1[k + 3] / 255, | ||
a2 = img2[m + 3] / 255, | ||
r1 = img1[i + 0] * a1, | ||
g1 = img1[i + 1] * a1, | ||
b1 = img1[i + 2] * a1, | ||
r1 = blend(img1[k + 0], a1), | ||
g1 = blend(img1[k + 1], a1), | ||
b1 = blend(img1[k + 2], a1), | ||
r2 = img2[j + 0] * a2, | ||
g2 = img2[j + 1] * a2, | ||
b2 = img2[j + 2] * a2, | ||
r2 = blend(img2[m + 0], a2), | ||
g2 = blend(img2[m + 1], a2), | ||
b2 = blend(img2[m + 2], a2), | ||
y1 = 0.299 * r1 + 0.587 * g1 + 0.114 * b1, | ||
y2 = 0.299 * r2 + 0.587 * g2 + 0.114 * b2, | ||
y = rgb2y(r1, g1, b1) - rgb2y(r2, g2, b2); | ||
yd = y1 - y2; | ||
if (yOnly) return y; // brightness difference only | ||
if (yOnly) return yd; | ||
var i = rgb2i(r1, g1, b1) - rgb2i(r2, g2, b2), | ||
q = rgb2q(r1, g1, b1) - rgb2q(r2, g2, b2); | ||
var ud = 0.492 * (b1 - y1) - 0.492 * (b2 - y2), | ||
vd = 0.877 * (r1 - y1) - 0.877 * (r2 - y2); | ||
return 0.5053 * y * y + 0.299 * i * i + 0.1957 * q * q; | ||
} | ||
return (yd * yd) + (ud * ud) + (vd * vd); | ||
function rgb2y(r, g, b) { return r * 0.29889531 + g * 0.58662247 + b * 0.11448223; } | ||
function rgb2i(r, g, b) { return r * 0.59597799 - g * 0.27417610 - b * 0.32180189; } | ||
function rgb2q(r, g, b) { return r * 0.21147017 - g * 0.52261711 + b * 0.31114694; } | ||
// blend semi-transparent color with white | ||
function blend(c, a) { | ||
return 255 + (c - 255) * a; | ||
} | ||
@@ -148,6 +155,8 @@ | ||
function grayPixel(img, pos) { | ||
return 0.30 * img[pos + 0] + | ||
0.59 * img[pos + 1] + | ||
0.11 * img[pos + 2]; | ||
function grayPixel(img, i) { | ||
var a = img[i + 3] / 255, | ||
r = blend(img[i + 0], a), | ||
g = blend(img[i + 1], a), | ||
b = blend(img[i + 2], a); | ||
return rgb2y(r, g, b); | ||
} |
{ | ||
"name": "pixelmatch", | ||
"version": "3.0.0", | ||
"version": "4.0.0", | ||
"description": "The smallest and fastest pixel-level image comparison library.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -5,2 +5,3 @@ ## pixelmatch | ||
[![Coverage Status](https://coveralls.io/repos/mapbox/pixelmatch/badge.svg?branch=master&service=github)](https://coveralls.io/github/mapbox/pixelmatch?branch=master) | ||
[![](https://img.shields.io/badge/simply-awesome-brightgreen.svg)](https://github.com/mourner/projects) | ||
@@ -10,4 +11,4 @@ The smallest, simplest and fastest JavaScript pixel-level image comparison library, | ||
Features accurate [anti-aliased pixels detection](http://www.ee.ktu.lt/journal/2009/7/25_ISSN_1392-1215_Anti-aliased%20Pxel%20and%20Intensity%20Slope%20Detector.pdf) | ||
and [perceptual color metrics](https://en.wikipedia.org/wiki/YUV). | ||
Features accurate **anti-aliased pixels detection** | ||
and **perceptual color difference metrics**. | ||
@@ -24,2 +25,7 @@ Inspired by [Resemble.js](https://github.com/Huddle/Resemble.js) | ||
Implements ideas from the following papers: | ||
- [Measuring perceived color difference using YIQ NTSC transmission color space in mobile applications](http://www.progmat.uaem.mx:8080/artVol2Num2/Articulo3Vol2Num2.pdf) (2010, Yuriy Kotsarenko, Fernando Ramos) | ||
- [Anti-aliased pixel and intensity slope detector](http://www.ee.ktu.lt/journal/2009/7/25_ISSN_1392-1215_Anti-aliased%20Pxel%20and%20Intensity%20Slope%20Detector.pdf) (2009, Vytautas Vyšniauskas) | ||
### Example output | ||
@@ -38,3 +44,3 @@ | ||
- `img1`, `img2` — Image data of the images to compare (`Buffer` or `Uint8Array`). | ||
- `output` — Image data to write the diff to. | ||
- `output` — Image data to write the diff to, or `null` if don't need a diff image. | ||
- `width`, `height` — Width and height of the images. Note that _all three images_ need to have the same dimensions. | ||
@@ -66,9 +72,10 @@ | ||
var img1 = fs.createReadStream('img1.png').pipe(new PNG()).on('parsed', doneReading); | ||
var img2 = fs.createReadStream('img2.png').pipe(new PNG()).on('parsed', doneReading); | ||
var img1 = fs.createReadStream('img1.png').pipe(new PNG()).on('parsed', doneReading), | ||
img2 = fs.createReadStream('img2.png').pipe(new PNG()).on('parsed', doneReading), | ||
filesRead = 0; | ||
function doneReading() { | ||
if (!img1.data || !img2.data) return; | ||
if (++filesRead < 2) return; | ||
var diff = new PNG({width: img1.width, height: img1.height}); | ||
var diff = new PNG({width: img1.width, height: img1.height}); | ||
pixelmatch(img1.data, img2.data, diff.data, img1.width, img1.height, {threshold: 0.1}); | ||
@@ -75,0 +82,0 @@ |
@@ -9,6 +9,6 @@ 'use strict'; | ||
diffTest('1a', '1b', '1diff', 0.03, false, 144); | ||
diffTest('2a', '2b', '2diff', 0.03, false, 12785); | ||
diffTest('3a', '3b', '3diff', 0.03, false, 212); | ||
diffTest('4a', '4b', '4diff', 0.03, false, 36383); | ||
diffTest('1a', '1b', '1diff', 0.05, false, 143); | ||
diffTest('2a', '2b', '2diff', 0.05, false, 12439); | ||
diffTest('3a', '3b', '3diff', 0.05, false, 212); | ||
diffTest('4a', '4b', '4diff', 0.05, false, 36089); | ||
@@ -30,4 +30,10 @@ function diffTest(imgPath1, imgPath2, diffPath, threshold, includeAA, expectedMismatch) { | ||
var mismatch2 = match(img1.data, img2.data, null, diff.width, diff.height, { | ||
threshold: threshold, | ||
includeAA: includeAA | ||
}); | ||
t.same(diff.data, expectedDiff.data, 'diff image'); | ||
t.same(mismatch, expectedMismatch, 'number of mismatched pixels'); | ||
t.same(mismatch, mismatch2, 'number of mismatched pixels'); | ||
@@ -34,0 +40,0 @@ t.end(); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
959160
23
190
110