Skip to content

Commit

Permalink
feat: mix colors in the linear sRGB model
Browse files Browse the repository at this point in the history
This seems to produce results that are closer to perceptual models.
See https://bottosson.github.io/posts/colorwrong/
  • Loading branch information
aradzie committed Nov 30, 2024
1 parent abf185b commit a1212ae
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 8 deletions.
2 changes: 1 addition & 1 deletion packages/keybr-color/lib/mix.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ test("mix", () => {
const b = hexColor(0xff8000);
equal(mixColors(a, b, -100.0).hex(), 0x0080ff);
equal(mixColors(a, b, 0.0).hex(), 0x0080ff);
equal(mixColors(a, b, 0.5).hex(), 0x808080);
equal(mixColors(a, b, 0.5).hex(), 0xbc80bc);
equal(mixColors(a, b, 1.0).hex(), 0xff8000);
equal(mixColors(a, b, 100.0).hex(), 0xff8000);
});
21 changes: 14 additions & 7 deletions packages/keybr-color/lib/mix.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import { clamp } from "@keybr/lang";
import { RgbColor } from "./color-rgb.ts";
import { rgbGammaToLinear, rgbLinearToGamma } from "./convert-xyz.ts";
import { type Rgb } from "./types.ts";

const u: Rgb = { r: 0, g: 0, b: 0, alpha: 1 };
const v: Rgb = { r: 0, g: 0, b: 0, alpha: 1 };

export function mixColors(
a: Readonly<Rgb>,
b: Readonly<Rgb>,
n: number,
r: number,
): RgbColor {
n = clamp(n, 0, 1);
return new RgbColor(
(b.r - a.r) * n + a.r,
(b.g - a.g) * n + a.g,
(b.b - a.b) * n + a.b,
);
r = clamp(r, 0, 1);
rgbGammaToLinear(a, u);
rgbGammaToLinear(b, v);
u.r = (v.r - u.r) * r + u.r;
u.g = (v.g - u.g) * r + u.g;
u.b = (v.b - u.b) * r + u.b;
u.alpha = (v.alpha - u.alpha) * r + u.alpha;
rgbLinearToGamma(u, v);
return new RgbColor(v.r, v.g, v.b, v.alpha);
}

0 comments on commit a1212ae

Please sign in to comment.