Skip to content

Commit

Permalink
Merge pull request #40 from happo/no-array-destructuring
Browse files Browse the repository at this point in the history
Remove array destructuring in colorDelta, add colorDeltaChannels, deprecate colorDelta
  • Loading branch information
lencioni authored Sep 15, 2024
2 parents 98eb1d4 + 77cf1e1 commit 2086a4b
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 33 deletions.
73 changes: 53 additions & 20 deletions src/__tests__/colorDelta-test.js
Original file line number Diff line number Diff line change
@@ -1,43 +1,76 @@
const colorDelta = require('../colorDelta');
const colorDelta = require("../colorDelta");
const { colorDeltaChannels } = require("../colorDelta");

it('is large when comparing black and white', () => {
expect(colorDelta([0, 0, 0, 255], [255, 255, 255, 255])).toBeGreaterThan(
0.92,
describe("colorDelta", () => {
it("produces the same results as colorDeltaChannels", () => {
const pixels = [
[0, 0, 0, 255],
[255, 255, 255, 255],
[0, 0, 0, 0],
[1, 1, 1, 1],
[1, 46, 250, 0],
[1, 42, 250, 4],
];

for (let i = 0; i < pixels.length; i++) {
for (let j = 0; j < pixels.length; j++) {
expect(colorDelta(pixels[i], pixels[j])).toEqual(
colorDeltaChannels(
pixels[i][0],
pixels[i][1],
pixels[i][2],
pixels[i][3],
pixels[j][0],
pixels[j][1],
pixels[j][2],
pixels[j][3]
)
);
}
}
});
});

it("is large when comparing black and white", () => {
expect(colorDeltaChannels(0, 0, 0, 255, 255, 255, 255, 255)).toBeGreaterThan(
0.92
);
});

it('is small when comparing black and very dark grey', () => {
expect(colorDelta([0, 0, 0, 255], [10, 10, 10, 255])).toBeLessThan(0.02);
it("is small when comparing black and very dark grey", () => {
expect(colorDeltaChannels(0, 0, 0, 255, 10, 10, 10, 255)).toBeLessThan(0.02);
});

it('is medium when comparing black and medium grey', () => {
const delta = colorDelta([0, 0, 0, 255], [127, 127, 127, 255]);
it("is medium when comparing black and medium grey", () => {
const delta = colorDeltaChannels(0, 0, 0, 255, 127, 127, 127, 255);
expect(delta).toBeGreaterThan(0.21);
expect(delta).toBeLessThan(0.24);
});

it('is medium when comparing red and blue', () => {
const delta = colorDelta([255, 0, 0, 255], [0, 0, 255, 255]);
it("is medium when comparing red and blue", () => {
const delta = colorDeltaChannels(255, 0, 0, 255, 0, 0, 255, 255);
expect(delta).toBeGreaterThan(0.5);
expect(delta).toBeLessThan(0.51);
});

it('is one when comparing filler pixel and white', () => {
expect(colorDelta([1, 1, 1, 1], [255, 255, 255, 255])).toEqual(1);
it("is one when comparing filler pixel and white", () => {
expect(colorDeltaChannels(1, 1, 1, 1, 255, 255, 255, 255)).toEqual(1);
});

it('is large when comparing transparent and black', () => {
expect(colorDelta([0, 0, 0, 0], [0, 0, 0, 255])).toBeGreaterThan(0.92);
it("is large when comparing transparent and black", () => {
expect(colorDeltaChannels(0, 0, 0, 0, 0, 0, 0, 255)).toBeGreaterThan(0.92);
});

it('is large when comparing white and filler pixel', () => {
expect(colorDelta([255, 255, 255, 255], [1, 1, 1, 1])).toBeGreaterThan(0.92);
it("is large when comparing white and filler pixel", () => {
expect(colorDeltaChannels(255, 255, 255, 255, 1, 1, 1, 1)).toBeGreaterThan(
0.92
);
});

it('is one when comparing filler pixel and some other color', () => {
expect(colorDelta([1, 1, 1, 1], [33, 33, 33, 10])).toEqual(1);
it("is one when comparing filler pixel and some other color", () => {
expect(colorDeltaChannels(1, 1, 1, 1, 33, 33, 33, 10)).toEqual(1);
});

it('is small when comparing transparent and similar color', () => {
expect(colorDelta([1, 46, 250, 0], [1, 42, 250, 4])).toBeLessThan(0.05);
it("is small when comparing transparent and similar color", () => {
expect(colorDeltaChannels(1, 46, 250, 0, 1, 42, 250, 4)).toBeLessThan(0.05);
});
54 changes: 41 additions & 13 deletions src/colorDelta.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,27 @@ function blend(color, alpha) {
return 255 + (color - 255) * alpha;
}

function isFillerPixel([r, g, b, a]) {
function isFillerPixel(r, g, b, a) {
return r === 1 && g === 1 && b === 1 && a === 1;
}

// 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
//
// Modified from https://github.com/mapbox/pixelmatch
module.exports = function colorDelta(previousPixel, currentPixel) {
let [r1, g1, b1, a1] = previousPixel;
let [r2, g2, b2, a2] = currentPixel;

/**
* Calculate color difference between two pixels
*
* The difference is calculated according to the paper "Measuring perceived
* color difference using YIQ NTSC transmission color space in mobile
* applications" by Y. Kotsarenko and F. Ramos.
*
* Modified from https://github.com/mapbox/pixelmatch
*/
function colorDeltaChannels(r1, g1, b1, a1, r2, g2, b2, a2) {
if (r1 === r2 && g1 === g2 && b1 === b2 && a1 === a2) {
return 0;
}

if (
(isFillerPixel(currentPixel) && a1 > 0) ||
(isFillerPixel(previousPixel) && a2 > 0)
(isFillerPixel(r1, g1, b1, a1) && a1 > 0) ||
(isFillerPixel(r2, g2, b2, a2) && a2 > 0)
) {
return 1;
}
Expand All @@ -60,4 +61,31 @@ module.exports = function colorDelta(previousPixel, currentPixel) {
const q = rgb2q(r1, g1, b1) - rgb2q(r2, g2, b2);

return (0.5053 * y * y + 0.299 * i * i + 0.1957 * q * q) / MAX_YIQ_DIFFERENCE;
};
}

/**
* Calculate color difference between two pixels
*
* The difference is calculated according to the paper "Measuring perceived
* color difference using YIQ NTSC transmission color space in mobile
* applications" by Y. Kotsarenko and F. Ramos.
*
* Modified from https://github.com/mapbox/pixelmatch
*
* @deprecated use `colorDeltaChannels` instead
*/
function colorDelta(previousPixel, currentPixel) {
return colorDeltaChannels(
previousPixel[0],
previousPixel[1],
previousPixel[2],
previousPixel[3],
currentPixel[0],
currentPixel[1],
currentPixel[2],
currentPixel[3]
);
}

module.exports = colorDelta;
module.exports.colorDeltaChannels = colorDeltaChannels;

0 comments on commit 2086a4b

Please sign in to comment.