mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-10 13:00:29 +03:00
LibGfx: Add Oklab support to Gfx::Color
Interpolation of color on the web is done via the oklab colorspace
This commit is contained in:
parent
71a784741f
commit
70ded2ef42
Notes:
sideshowbarker
2024-07-17 16:23:55 +09:00
Author: https://github.com/mattco98 Commit: https://github.com/SerenityOS/serenity/commit/70ded2ef42 Pull-request: https://github.com/SerenityOS/serenity/pull/23332
@ -32,6 +32,12 @@ struct YUV {
|
||||
float v { 0 };
|
||||
};
|
||||
|
||||
struct Oklab {
|
||||
float L { 0 };
|
||||
float a { 0 };
|
||||
float b { 0 };
|
||||
};
|
||||
|
||||
class Color {
|
||||
public:
|
||||
enum NamedColor {
|
||||
@ -159,6 +165,58 @@ public:
|
||||
return Color(r_u8, g_u8, b_u8, a_u8);
|
||||
}
|
||||
|
||||
// https://bottosson.github.io/posts/oklab/
|
||||
static constexpr Color from_oklab(float L, float a, float b, float alpha = 1.0f)
|
||||
{
|
||||
auto linear_to_srgb = [](float c) {
|
||||
return c >= 0.0031308f ? 1.055f * pow(c, 0.4166666f) - 0.055f : 12.92f * c;
|
||||
};
|
||||
|
||||
float l = L + 0.3963377774f * a + 0.2158037573f * b;
|
||||
float m = L - 0.1055613458f * a - 0.0638541728f * b;
|
||||
float s = L - 0.0894841775f * a - 1.2914855480f * b;
|
||||
|
||||
l = l * l * l;
|
||||
m = m * m * m;
|
||||
s = s * s * s;
|
||||
|
||||
float red = 4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s;
|
||||
float green = -1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s;
|
||||
float blue = -0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s;
|
||||
|
||||
red = linear_to_srgb(red) * 255.f;
|
||||
green = linear_to_srgb(green) * 255.f;
|
||||
blue = linear_to_srgb(blue) * 255.f;
|
||||
|
||||
return Color(
|
||||
clamp(lroundf(red), 0, 255),
|
||||
clamp(lroundf(green), 0, 255),
|
||||
clamp(lroundf(blue), 0, 255),
|
||||
clamp(lroundf(alpha * 255.f), 0, 255));
|
||||
}
|
||||
|
||||
// https://bottosson.github.io/posts/oklab/
|
||||
constexpr Oklab to_oklab()
|
||||
{
|
||||
auto srgb_to_linear = [](float c) {
|
||||
return c >= 0.04045f ? pow((c + 0.055f) / 1.055f, 2.4f) : c / 12.92f;
|
||||
};
|
||||
|
||||
float r = srgb_to_linear(red() / 255.f);
|
||||
float g = srgb_to_linear(green() / 255.f);
|
||||
float b = srgb_to_linear(blue() / 255.f);
|
||||
|
||||
float l = cbrtf(0.4122214708f * r + 0.5363325363f * g + 0.0514459929f * b);
|
||||
float m = cbrtf(0.2119034982f * r + 0.6806995451f * g + 0.1073969566f * b);
|
||||
float s = cbrtf(0.0883024619f * r + 0.2817188376f * g + 0.6299787005f * b);
|
||||
|
||||
return {
|
||||
0.2104542553f * l + 0.7936177850f * m - 0.0040720468f * s,
|
||||
1.9779984951f * l - 2.4285922050f * m + 0.4505937099f * s,
|
||||
0.0259040371f * l + 0.7827717662f * m - 0.8086757660f * s,
|
||||
};
|
||||
}
|
||||
|
||||
constexpr u8 red() const { return (m_value >> 16) & 0xff; }
|
||||
constexpr u8 green() const { return (m_value >> 8) & 0xff; }
|
||||
constexpr u8 blue() const { return m_value & 0xff; }
|
||||
|
@ -771,13 +771,13 @@ static ErrorOr<NonnullRefPtr<StyleValue>> interpolate_property(StyleValue const&
|
||||
case StyleValue::Type::Color: {
|
||||
auto from_color = from.as_color().color();
|
||||
auto to_color = to.as_color().color();
|
||||
auto from_hsv = from_color.to_hsv();
|
||||
auto to_hsv = to_color.to_hsv();
|
||||
auto from_oklab = from_color.to_oklab();
|
||||
auto to_oklab = to_color.to_oklab();
|
||||
|
||||
auto color = Color::from_hsv(
|
||||
interpolate_raw(from_hsv.hue, to_hsv.hue),
|
||||
interpolate_raw(from_hsv.saturation, to_hsv.saturation),
|
||||
interpolate_raw(from_hsv.value, to_hsv.value));
|
||||
auto color = Color::from_oklab(
|
||||
interpolate_raw(from_oklab.L, to_oklab.L),
|
||||
interpolate_raw(from_oklab.a, to_oklab.a),
|
||||
interpolate_raw(from_oklab.b, to_oklab.b));
|
||||
color.set_alpha(interpolate_raw(from_color.alpha(), to_color.alpha()));
|
||||
|
||||
return ColorStyleValue::create(color);
|
||||
|
Loading…
Reference in New Issue
Block a user