Skip to content

Commit

Permalink
color: Add color
Browse files Browse the repository at this point in the history
  • Loading branch information
vaxerski committed Dec 3, 2024
1 parent 4d927a5 commit 7ba2870
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 0 deletions.
38 changes: 38 additions & 0 deletions include/hyprgraphics/color/Color.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#pragma once

namespace Hyprgraphics {
class CColor {
public:
// SRGB (NOT linear!!) 0.0 - 1.0
struct SSRGB {
double r = 0, g = 0, b = 0;
};

// HSL 0.0 - 1.0
struct SHSL {
double h = 0, s = 0, l = 0;
};

// OkLab 0.0 - 1.0
struct SOkLab {
double l = 0, a = 0, b = 0;
};

CColor(); // black
CColor(const SSRGB& rgb);
CColor(const SHSL& hsl);
CColor(const SOkLab& lab);

SSRGB asRgb() const;
SHSL asHSL() const;
SOkLab asOkLab() const;

bool operator==(const CColor& other) const {
return other.r == r && other.g == g && other.b == b;
}

private:
// SRGB space for internal color storage
double r = 0, g = 0, b = 0;
};
};
115 changes: 115 additions & 0 deletions src/color/Color.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#include <hyprgraphics/color/Color.hpp>
#include <cmath>

using namespace Hyprgraphics;

static double gammaToLinear(const double in) {
return in >= 0.04045 ? std::pow((in + 0.055) / 1.055, 2.4) : in / 12.92;
}

static double linearToGamma(const double in) {
return in >= 0.0031308 ? 1.055 * std::pow(in, 0.41666666666) - 0.055 : 12.92 * in;
}

static double hueToRgb(double p, double q, double t) {
if (t < 0)
t += 1;
if (t > 1)
t -= 1;
if (t < 1.0 / 6.0)
return p + (q - p) * 6.0 * t;
if (t < 1.0 / 2.0)
return q;
if (t < 2.0 / 3.0)
return p + (q - p) * (2.0 / 3.0 - t) * 6.0;
return p;
}

Hyprgraphics::CColor::CColor() {
;
}

Hyprgraphics::CColor::CColor(const SSRGB& rgb) {
r = rgb.r;
g = rgb.g;
b = rgb.b;
}

Hyprgraphics::CColor::CColor(const SHSL& hsl) {
if (hsl.s <= 0) {
r = hsl.l;
g = hsl.l;
b = hsl.l;
} else {
const double q = hsl.l < 0.5 ? hsl.l * (1.0 + hsl.s) : hsl.l + hsl.s - hsl.l * hsl.s;
const double p = 2.0 * hsl.l - q;
r = hueToRgb(p, q, hsl.h + 1.0 / 3.0);
g = hueToRgb(p, q, hsl.h);
b = hueToRgb(p, q, hsl.h - 1.0 / 3.0);
}
}

Hyprgraphics::CColor::CColor(const SOkLab& lab) {
const double l = std::pow(lab.l + lab.a * 0.3963377774 + lab.b * 0.2158037573, 3);
const double m = std::pow(lab.l + lab.a * (-0.1055613458) + lab.b * (-0.0638541728), 3);
const double s = std::pow(lab.l + lab.a * (-0.0894841775) + lab.b * (-1.2914855480), 3);

r = linearToGamma(l * 4.0767416621 + m * -3.3077115913 + s * 0.2309699292);
g = linearToGamma(l * (-1.2684380046) + m * 2.6097574011 + s * (-0.3413193965));
b = linearToGamma(l * (-0.0041960863) + m * (-0.7034186147) + s * 1.7076147010);
}

Hyprgraphics::CColor::SSRGB Hyprgraphics::CColor::asRgb() const {
return Hyprgraphics::CColor::SSRGB{
.r = r,
.g = g,
.b = b,
};
}

Hyprgraphics::CColor::SHSL Hyprgraphics::CColor::asHSL() const {
const double vmax = std::max(std::max(r, g), b), vmin = std::min(std::min(r, g), b);
double h = 0, s = 0, l = (vmax + vmin) / 2.0;

if (vmax == vmin) {
return Hyprgraphics::CColor::SHSL{
.h = 0,
.s = 0,
.l = l,
};
}

const double d = vmax - vmin;
s = l > 0.5 ? d / (2.0 - vmax - vmin) : d / (vmax + vmin);

if (vmax == r)
h = (g - b) / d + (g < b ? 6.0 : 0.0);
if (vmax == g)
h = (b - r) / d + 2;
if (vmax == b)
h = (r - g) / d + 4;

h /= 6.0;

return Hyprgraphics::CColor::SHSL{
.h = h,
.s = s,
.l = l,
};
}

Hyprgraphics::CColor::SOkLab Hyprgraphics::CColor::asOkLab() const {
const double linR = gammaToLinear(r);
const double linG = gammaToLinear(g);
const double linB = gammaToLinear(b);

const double l = std::cbrtf(0.4122214708 * linR + 0.5363325363 * linG + 0.0514459929 * linB);
const double m = std::cbrtf(0.2119034982 * linR + 0.6806995451 * linG + 0.1073969566 * linB);
const double s = std::cbrtf(0.0883024619 * linR + 0.2817188376 * linG + 0.6299787005 * linB);

return Hyprgraphics::CColor::SOkLab{
.l = l * 0.2104542553 + m * 0.7936177850 + s * (-0.0040720468),
.a = l * 1.9779984951 + m * (-2.4285922050) + s * 0.4505937099,
.b = l * 0.0259040371 + m * 0.7827717662 + s * (-0.8086757660),
};
}

0 comments on commit 7ba2870

Please sign in to comment.