Skip to content

Commit

Permalink
feat(color): update ChannelSpec and hue-based modes
Browse files Browse the repository at this point in the history
- add `hue` flag for channel spec
- update `.clamp()` impl to wrap hue in [0..1] interval
- add/update LCH conversion paths
  • Loading branch information
postspectacular committed Jan 3, 2022
1 parent 804565e commit 01d93dc
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 5 deletions.
7 changes: 7 additions & 0 deletions packages/color/src/api.ts
Expand Up @@ -64,9 +64,16 @@ export interface IColor {
export interface ChannelSpec {
/**
* Acceptable value range for this channel. Used by {@link TypedColor.clamp}.
*
* @defaultValue [0,1]
*/
range?: Range;
/**
* If true, this channel is used to store normalized hue values.
*
* @defaultValue false
*/
hue?: boolean;
}

export interface ColorSpec<M extends ColorMode, K extends string> {
Expand Down
7 changes: 6 additions & 1 deletion packages/color/src/defcolor.ts
Expand Up @@ -5,6 +5,7 @@ import { isNumber } from "@thi.ng/checks/is-number";
import { isString } from "@thi.ng/checks/is-string";
import { illegalArgs } from "@thi.ng/errors/illegal-arguments";
import { EPS } from "@thi.ng/math/api";
import { fract } from "@thi.ng/math/prec";
import type { IRandom } from "@thi.ng/random";
import { vector } from "@thi.ng/strings/vector";
import { mapStridedBuffer } from "@thi.ng/vectors/buffer";
Expand Down Expand Up @@ -58,6 +59,8 @@ export const defColor = <M extends ColorMode, K extends string>(
const maxR = set4([], max);
minR[numChannels - 1] = 1;

const hueChanID = order.findIndex((id) => !!channels[id]!.hue);

const $Color = class implements TypedColor<$DefColor<any, any>> {
buf: NumericArray;
[id: number]: number;
Expand Down Expand Up @@ -114,7 +117,9 @@ export const defColor = <M extends ColorMode, K extends string>(
}

clamp() {
return <this>clamp4(null, this, min, max);
hueChanID >= 0 && (this[hueChanID] = fract(this[hueChanID]));
clamp4(null, this, min, max);
return this;
}

eqDelta(o: $DefColor<any, any>, eps = EPS): boolean {
Expand Down
6 changes: 5 additions & 1 deletion packages/color/src/hcy/hcy.ts
Expand Up @@ -2,7 +2,10 @@ import type { NumericArray } from "@thi.ng/api";
import type { IRandom } from "@thi.ng/random";
import type { Color, ColorFactory, ReadonlyColor, TypedColor } from "../api.js";
import { defColor } from "../defcolor.js";
import { lchLab } from "../lab/lab-lch.js";
import { labRgb } from "../lab/lab-rgb.js";
import { rgbHcy } from "../rgb/rgb-hcy.js";
import { rgbSrgb } from "../rgb/rgb-srgb.js";
import { hcyRgb } from "./hcy-rgb.js";

export declare class HCY implements TypedColor<HCY> {
Expand Down Expand Up @@ -31,7 +34,8 @@ export declare class HCY implements TypedColor<HCY> {

export const hcy = <ColorFactory<HCY>>defColor({
mode: "hcy",
channels: { h: { hue: true } },
order: <const>["h", "c", "y", "alpha"],
from: { rgb: rgbHcy, srgb: rgbHcy },
from: { rgb: rgbHcy, srgb: rgbHcy, lch: [lchLab, labRgb, rgbSrgb, rgbHcy] },
toRgb: hcyRgb,
});
6 changes: 5 additions & 1 deletion packages/color/src/hsi/hsi.ts
Expand Up @@ -2,7 +2,10 @@ import type { NumericArray } from "@thi.ng/api";
import type { IRandom } from "@thi.ng/random";
import type { Color, ColorFactory, ReadonlyColor, TypedColor } from "../api.js";
import { defColor } from "../defcolor.js";
import { lchLab } from "../lab/lab-lch.js";
import { labRgb } from "../lab/lab-rgb.js";
import { rgbHsi } from "../rgb/rgb-hsi.js";
import { rgbSrgb } from "../rgb/rgb-srgb.js";
import { hsiRgb } from "./hsi-rgb.js";

export declare class HSI implements TypedColor<HSI> {
Expand Down Expand Up @@ -31,7 +34,8 @@ export declare class HSI implements TypedColor<HSI> {

export const hsi = <ColorFactory<HSI>>defColor({
mode: "hsi",
channels: { h: { hue: true } },
order: <const>["h", "s", "i", "alpha"],
from: { rgb: rgbHsi, srgb: rgbHsi },
from: { rgb: rgbHsi, srgb: rgbHsi, lch: [lchLab, labRgb, rgbSrgb, rgbHsi] },
toRgb: hsiRgb,
});
11 changes: 10 additions & 1 deletion packages/color/src/hsl/hsl.ts
Expand Up @@ -3,7 +3,10 @@ import type { IRandom } from "@thi.ng/random";
import type { Color, ColorFactory, ReadonlyColor, TypedColor } from "../api.js";
import { defColor } from "../defcolor.js";
import { hsvHsl } from "../hsv/hsv-hsl.js";
import { lchLab } from "../lab/lab-lch.js";
import { labRgb } from "../lab/lab-rgb.js";
import { rgbHsl } from "../rgb/rgb-hsl.js";
import { rgbSrgb } from "../rgb/rgb-srgb.js";
import { hslRgb } from "./hsl-rgb.js";

export declare class HSL implements TypedColor<HSL> {
Expand Down Expand Up @@ -32,7 +35,13 @@ export declare class HSL implements TypedColor<HSL> {

export const hsl = <ColorFactory<HSL>>defColor({
mode: "hsl",
channels: { h: { hue: true } },
order: <const>["h", "s", "l", "alpha"],
from: { rgb: rgbHsl, srgb: rgbHsl, hsv: hsvHsl },
from: {
rgb: rgbHsl,
srgb: rgbHsl,
hsv: hsvHsl,
lch: [lchLab, labRgb, rgbSrgb, rgbHsl],
},
toRgb: hslRgb,
});
11 changes: 10 additions & 1 deletion packages/color/src/hsv/hsv.ts
Expand Up @@ -3,7 +3,10 @@ import type { IRandom } from "@thi.ng/random";
import type { Color, ColorFactory, ReadonlyColor, TypedColor } from "../api.js";
import { defColor } from "../defcolor.js";
import { hslHsv } from "../hsl/hsl-hsv.js";
import { lchLab } from "../lab/lab-lch.js";
import { labRgb } from "../lab/lab-rgb.js";
import { rgbHsv } from "../rgb/rgb-hsv.js";
import { rgbSrgb } from "../rgb/rgb-srgb.js";
import { hsvRgb } from "./hsv-rgb.js";

export declare class HSV implements TypedColor<HSV> {
Expand Down Expand Up @@ -32,7 +35,13 @@ export declare class HSV implements TypedColor<HSV> {

export const hsv = <ColorFactory<HSV>>defColor({
mode: "hsv",
channels: { h: { hue: true } },
order: <const>["h", "s", "v", "alpha"],
from: { rgb: rgbHsv, srgb: rgbHsv, hsl: hslHsv },
from: {
rgb: rgbHsv,
srgb: rgbHsv,
hsl: hslHsv,
lch: [lchLab, labRgb, rgbSrgb, rgbHsv],
},
toRgb: hsvRgb,
});
1 change: 1 addition & 0 deletions packages/color/src/lch/lch.ts
Expand Up @@ -41,6 +41,7 @@ export const lch = <ColorFactory<LCH>>defColor({
mode: "lch",
channels: {
c: { range: [0, 1.312] },
h: { hue: true },
},
order: <const>["l", "c", "h", "alpha"],
from: {
Expand Down

0 comments on commit 01d93dc

Please sign in to comment.