-
Notifications
You must be signed in to change notification settings - Fork 82
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* `deltas()` function, closes #437 * Handle hue angles - `hue` option to customize how hues are handled - `shorter` by default * Proper `none` handling * Add tests for hues + none * Fix none handling * Lint
- Loading branch information
Showing
4 changed files
with
132 additions
and
0 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import getColor from "./getColor.js"; | ||
import ColorSpace from "./space.js"; | ||
import to from "./to.js"; | ||
import { adjust } from "./angles.js"; | ||
import { isNone } from "./util.js"; | ||
|
||
/** | ||
* Get color differences per-component, on any color space | ||
* @param {Color} c1 | ||
* @param {Color} c2 | ||
* @param {object} options | ||
* @param {string | ColorSpace} [options.space=c1.space] - The color space to use for the delta calculation. Defaults to the color space of the first color. | ||
* @param {string} [options.hue="shorter"] - How to handle hue differences. Same as hue interpolation option. | ||
* @returns {number[]} - An array of differences per component. | ||
* If one of the components is none, the difference will be 0. | ||
* If both components are none, the difference will be none. | ||
*/ | ||
export default function deltas (c1, c2, {space, hue = "shorter"} = {}) { | ||
c1 = getColor(c1); | ||
space ||= c1.space; | ||
space = ColorSpace.get(space); | ||
let spaceCoords = Object.values(space.coords); | ||
|
||
[c1, c2] = [c1, c2].map(c => to(c, space)); | ||
let [coords1, coords2] = [c1, c2].map(c => c.coords); | ||
|
||
let coords = coords1.map((coord1, i) => { | ||
let coordMeta = spaceCoords[i]; | ||
let coord2 = coords2[i]; | ||
|
||
if (coordMeta.type === "angle") { | ||
[coord1, coord2] = adjust(hue, [coord1, coord2]); | ||
} | ||
|
||
return subtractCoords(coord1, coord2); | ||
}); | ||
|
||
let alpha = subtractCoords(c1.alpha, c2.alpha); | ||
|
||
return { space: c1.space, spaceId: c1.space.id, coords, alpha }; | ||
} | ||
|
||
function subtractCoords (c1, c2) { | ||
if (isNone(c1) || isNone(c2)) { | ||
return c1 === c2 ? null : 0; | ||
} | ||
|
||
return c1 - c2; | ||
} |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import "../src/spaces/index.js"; | ||
import deltas from "../src/deltas.js"; | ||
import * as check from "../node_modules/htest.dev/src/check.js"; | ||
|
||
export default { | ||
name: "deltas() tests", | ||
description: "These tests test the various Delta E algorithms.", | ||
run (c1, c2, o) { | ||
return deltas(c1, c2, o); | ||
}, | ||
check: check.deep(check.shallowEquals({ epsilon: .0001, subset: true })), | ||
tests: [ | ||
{ | ||
name: "Same color space", | ||
tests: [ | ||
{ | ||
name: "Same color", | ||
args: ["red", "red"], | ||
expect: { spaceId: "srgb", coords: [0, 0, 0], alpha: 0 }, | ||
}, | ||
{ | ||
args: ["white", "black"], | ||
expect: { spaceId: "srgb", coords: [1, 1, 1], alpha: 0 }, | ||
}, | ||
{ | ||
name: "Hues should never have a difference > 180 by default", | ||
args: [ | ||
{spaceId: "oklch", coords: [.5, .2, -180]}, | ||
{spaceId: "oklch", coords: [.5, .2, 720]}, | ||
], | ||
expect: { spaceId: "oklch", coords: [0, 0, 180], alpha: 0 }, | ||
}, | ||
{ | ||
name: "If both coords are none, the delta should be none.", | ||
args: [ | ||
{spaceId: "oklch", coords: [null, null, null], alpha: null}, | ||
{spaceId: "oklch", coords: [null, null, null], alpha: null}, | ||
], | ||
expect: { spaceId: "oklch", coords: [null, null, null], alpha: null }, | ||
}, | ||
{ | ||
name: "If one coord is none, the delta should be 0.", | ||
args: [ | ||
{spaceId: "oklch", coords: [.5, .2, -180], alpha: null}, | ||
{spaceId: "oklch", coords: [null, null, null], alpha: .5}, | ||
], | ||
expect: { spaceId: "oklch", coords: [0, 0, 0], alpha: 0 }, | ||
}, | ||
], | ||
}, | ||
{ | ||
name: "Different color space", | ||
tests: [ | ||
{ | ||
name: "Same color", | ||
args: ["red", "hsl(0 100% 50%)"], | ||
expect: { spaceId: "srgb", coords: [0, 0, 0], alpha: 0 }, | ||
}, | ||
{ | ||
args: ["white", "hsl(0 100% 0%)"], | ||
expect: { spaceId: "srgb", coords: [1, 1, 1], alpha: 0 }, | ||
}, | ||
], | ||
}, | ||
{ | ||
name: "Forced color space", | ||
tests: [ | ||
{ | ||
name: "Same color", | ||
args: ["red", "hsl(0 100% 50%)", { space: "oklch" }], | ||
expect: { spaceId: "oklch", coords: [0, 0, 0], alpha: 0 }, | ||
}, | ||
{ | ||
args: [{space: "srgb", coords: [1, 0, 0]}, {space: "srgb", coords: [.5, 0, 0]}, { space: "oklch" }], | ||
expect: { spaceId: "oklch", coords: [0.2523245655926571, 0.10354211689049864, 0], alpha: 0 }, | ||
}, | ||
], | ||
}, | ||
], | ||
}; |