Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Gamut mapping app] Scale LH improvements #438

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion apps/gamut-mapping/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ <h2>Gamut mapped</h2>
</dd>
<dd>
<css-color swatch="large" :color="mapped[method].color"></css-color>
<dl class="deltas" v-if="!color.inGamut('p3')">
<dl class="deltas">
<div v-for="(delta, c) of mapped[method].deltas" :class="'delta-' + c.toLowerCase()">
<dt>Δ{{ c }}</dt>
<dd :class="{
Expand Down
33 changes: 33 additions & 0 deletions apps/gamut-mapping/methods.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Color from "../../dist/color.js";
import { WHITES } from "../../src/adapt.js";

const methods = {
"clip": {
Expand All @@ -22,6 +23,38 @@ const methods = {
return methods.scale.compute(mappedColor);
}
},
"scale-lh2": {
label: "Scale LH 2",
description: "Identical to Scale LH 2, and handles L=0/1, and noop if already in gamut.",
jamesnw marked this conversation as resolved.
Show resolved Hide resolved
compute: (color) => {
if (color.inGamut("p3")) {
return color.to("p3");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not simply return color? There is no reason to convert it to anything, and any conversion is potentially a lossy operation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did this to match what was happening in the scale method, which returns the color converted to p3. This way, the method returns in a consistent space regardless of whether it starts in gamut or not. Otherwise, the serialized display with switch back and forth between p3 and oklch depending on whether it was in gamut.

(Perhaps the results from all methods should be serialized in a single format- currently some are oklch, and some are p3, making them harder to compare, but that's somewhat orthogonal to the question of whether the Scale LH method should return in a consistent space).

}
let [lightness] = color.to("oklch").coords;
if (lightness >= 1) {
return new Color({ space: "xyz-d65", coords: WHITES["D65"] }).to("p3");
}
else if (lightness <= 0) {
return new Color({ space: "xyz-d65", coords: [0, 0, 0] }).to("p3");
}
let mappedColor = methods.scale.compute(color);
let lch = color.to("oklch").coords;
mappedColor.set({
"oklch.l": lch[0],
"oklch.h": lch[2]
});
// Do not early return if in-gamut already at this point.
// The second scale step gets the color closer to the original.
mappedColor = methods.scale.compute(mappedColor);
if (mappedColor.inGamut("p3")) {
return mappedColor;
}
// Are we mathematically guaranteed to be in gamut at this point?
// If not, would a clip suffice?
return mappedColor;

}
},
"scale": {
label: "Scale",
description: "Using a midpoint of 0.5, scale the color to fit within the linear P3 gamut.",
Expand Down