Skip to content

Commit 01d93dc

Browse files
feat(color): update ChannelSpec and hue-based modes
- add `hue` flag for channel spec - update `.clamp()` impl to wrap hue in [0..1] interval - add/update LCH conversion paths
1 parent 804565e commit 01d93dc

File tree

7 files changed

+44
-5
lines changed

7 files changed

+44
-5
lines changed

packages/color/src/api.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,16 @@ export interface IColor {
6464
export interface ChannelSpec {
6565
/**
6666
* Acceptable value range for this channel. Used by {@link TypedColor.clamp}.
67+
*
6768
* @defaultValue [0,1]
6869
*/
6970
range?: Range;
71+
/**
72+
* If true, this channel is used to store normalized hue values.
73+
*
74+
* @defaultValue false
75+
*/
76+
hue?: boolean;
7077
}
7178

7279
export interface ColorSpec<M extends ColorMode, K extends string> {

packages/color/src/defcolor.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { isNumber } from "@thi.ng/checks/is-number";
55
import { isString } from "@thi.ng/checks/is-string";
66
import { illegalArgs } from "@thi.ng/errors/illegal-arguments";
77
import { EPS } from "@thi.ng/math/api";
8+
import { fract } from "@thi.ng/math/prec";
89
import type { IRandom } from "@thi.ng/random";
910
import { vector } from "@thi.ng/strings/vector";
1011
import { mapStridedBuffer } from "@thi.ng/vectors/buffer";
@@ -58,6 +59,8 @@ export const defColor = <M extends ColorMode, K extends string>(
5859
const maxR = set4([], max);
5960
minR[numChannels - 1] = 1;
6061

62+
const hueChanID = order.findIndex((id) => !!channels[id]!.hue);
63+
6164
const $Color = class implements TypedColor<$DefColor<any, any>> {
6265
buf: NumericArray;
6366
[id: number]: number;
@@ -114,7 +117,9 @@ export const defColor = <M extends ColorMode, K extends string>(
114117
}
115118

116119
clamp() {
117-
return <this>clamp4(null, this, min, max);
120+
hueChanID >= 0 && (this[hueChanID] = fract(this[hueChanID]));
121+
clamp4(null, this, min, max);
122+
return this;
118123
}
119124

120125
eqDelta(o: $DefColor<any, any>, eps = EPS): boolean {

packages/color/src/hcy/hcy.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ import type { NumericArray } from "@thi.ng/api";
22
import type { IRandom } from "@thi.ng/random";
33
import type { Color, ColorFactory, ReadonlyColor, TypedColor } from "../api.js";
44
import { defColor } from "../defcolor.js";
5+
import { lchLab } from "../lab/lab-lch.js";
6+
import { labRgb } from "../lab/lab-rgb.js";
57
import { rgbHcy } from "../rgb/rgb-hcy.js";
8+
import { rgbSrgb } from "../rgb/rgb-srgb.js";
69
import { hcyRgb } from "./hcy-rgb.js";
710

811
export declare class HCY implements TypedColor<HCY> {
@@ -31,7 +34,8 @@ export declare class HCY implements TypedColor<HCY> {
3134

3235
export const hcy = <ColorFactory<HCY>>defColor({
3336
mode: "hcy",
37+
channels: { h: { hue: true } },
3438
order: <const>["h", "c", "y", "alpha"],
35-
from: { rgb: rgbHcy, srgb: rgbHcy },
39+
from: { rgb: rgbHcy, srgb: rgbHcy, lch: [lchLab, labRgb, rgbSrgb, rgbHcy] },
3640
toRgb: hcyRgb,
3741
});

packages/color/src/hsi/hsi.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ import type { NumericArray } from "@thi.ng/api";
22
import type { IRandom } from "@thi.ng/random";
33
import type { Color, ColorFactory, ReadonlyColor, TypedColor } from "../api.js";
44
import { defColor } from "../defcolor.js";
5+
import { lchLab } from "../lab/lab-lch.js";
6+
import { labRgb } from "../lab/lab-rgb.js";
57
import { rgbHsi } from "../rgb/rgb-hsi.js";
8+
import { rgbSrgb } from "../rgb/rgb-srgb.js";
69
import { hsiRgb } from "./hsi-rgb.js";
710

811
export declare class HSI implements TypedColor<HSI> {
@@ -31,7 +34,8 @@ export declare class HSI implements TypedColor<HSI> {
3134

3235
export const hsi = <ColorFactory<HSI>>defColor({
3336
mode: "hsi",
37+
channels: { h: { hue: true } },
3438
order: <const>["h", "s", "i", "alpha"],
35-
from: { rgb: rgbHsi, srgb: rgbHsi },
39+
from: { rgb: rgbHsi, srgb: rgbHsi, lch: [lchLab, labRgb, rgbSrgb, rgbHsi] },
3640
toRgb: hsiRgb,
3741
});

packages/color/src/hsl/hsl.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ import type { IRandom } from "@thi.ng/random";
33
import type { Color, ColorFactory, ReadonlyColor, TypedColor } from "../api.js";
44
import { defColor } from "../defcolor.js";
55
import { hsvHsl } from "../hsv/hsv-hsl.js";
6+
import { lchLab } from "../lab/lab-lch.js";
7+
import { labRgb } from "../lab/lab-rgb.js";
68
import { rgbHsl } from "../rgb/rgb-hsl.js";
9+
import { rgbSrgb } from "../rgb/rgb-srgb.js";
710
import { hslRgb } from "./hsl-rgb.js";
811

912
export declare class HSL implements TypedColor<HSL> {
@@ -32,7 +35,13 @@ export declare class HSL implements TypedColor<HSL> {
3235

3336
export const hsl = <ColorFactory<HSL>>defColor({
3437
mode: "hsl",
38+
channels: { h: { hue: true } },
3539
order: <const>["h", "s", "l", "alpha"],
36-
from: { rgb: rgbHsl, srgb: rgbHsl, hsv: hsvHsl },
40+
from: {
41+
rgb: rgbHsl,
42+
srgb: rgbHsl,
43+
hsv: hsvHsl,
44+
lch: [lchLab, labRgb, rgbSrgb, rgbHsl],
45+
},
3746
toRgb: hslRgb,
3847
});

packages/color/src/hsv/hsv.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ import type { IRandom } from "@thi.ng/random";
33
import type { Color, ColorFactory, ReadonlyColor, TypedColor } from "../api.js";
44
import { defColor } from "../defcolor.js";
55
import { hslHsv } from "../hsl/hsl-hsv.js";
6+
import { lchLab } from "../lab/lab-lch.js";
7+
import { labRgb } from "../lab/lab-rgb.js";
68
import { rgbHsv } from "../rgb/rgb-hsv.js";
9+
import { rgbSrgb } from "../rgb/rgb-srgb.js";
710
import { hsvRgb } from "./hsv-rgb.js";
811

912
export declare class HSV implements TypedColor<HSV> {
@@ -32,7 +35,13 @@ export declare class HSV implements TypedColor<HSV> {
3235

3336
export const hsv = <ColorFactory<HSV>>defColor({
3437
mode: "hsv",
38+
channels: { h: { hue: true } },
3539
order: <const>["h", "s", "v", "alpha"],
36-
from: { rgb: rgbHsv, srgb: rgbHsv, hsl: hslHsv },
40+
from: {
41+
rgb: rgbHsv,
42+
srgb: rgbHsv,
43+
hsl: hslHsv,
44+
lch: [lchLab, labRgb, rgbSrgb, rgbHsv],
45+
},
3746
toRgb: hsvRgb,
3847
});

packages/color/src/lch/lch.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export const lch = <ColorFactory<LCH>>defColor({
4141
mode: "lch",
4242
channels: {
4343
c: { range: [0, 1.312] },
44+
h: { hue: true },
4445
},
4546
order: <const>["l", "c", "h", "alpha"],
4647
from: {

0 commit comments

Comments
 (0)