mirror of
https://github.com/hyprwm/hyprgraphics.git
synced 2025-05-12 21:30:43 +01:00
color: CM structs, constants & math (#14)
This commit is contained in:
parent
175c6b29b6
commit
760d67a2a8
2 changed files with 165 additions and 1 deletions
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <array>
|
||||
namespace Hyprgraphics {
|
||||
class CColor {
|
||||
public:
|
||||
|
@ -18,6 +19,25 @@ namespace Hyprgraphics {
|
|||
double l = 0, a = 0, b = 0;
|
||||
};
|
||||
|
||||
// xy 0.0 - 1.0
|
||||
struct xy {
|
||||
double x = 0, y = 0;
|
||||
|
||||
bool operator==(const xy& p2) const {
|
||||
return x == p2.x && y == p2.y;
|
||||
}
|
||||
};
|
||||
|
||||
// XYZ 0.0 - 1.0
|
||||
struct XYZ {
|
||||
double x = 0, y = 0, z = 0;
|
||||
|
||||
// per-component division
|
||||
XYZ operator/(const XYZ& other) const {
|
||||
return {x / other.x, y / other.y, z / other.z};
|
||||
}
|
||||
};
|
||||
|
||||
CColor(); // black
|
||||
CColor(const SSRGB& rgb);
|
||||
CColor(const SHSL& hsl);
|
||||
|
@ -27,7 +47,7 @@ namespace Hyprgraphics {
|
|||
SHSL asHSL() const;
|
||||
SOkLab asOkLab() const;
|
||||
|
||||
bool operator==(const CColor& other) const {
|
||||
bool operator==(const CColor& other) const {
|
||||
return other.r == r && other.g == g && other.b == b;
|
||||
}
|
||||
|
||||
|
@ -35,4 +55,40 @@ namespace Hyprgraphics {
|
|||
// SRGB space for internal color storage
|
||||
double r = 0, g = 0, b = 0;
|
||||
};
|
||||
|
||||
// 3x3 matrix for CM transformations
|
||||
class CMatrix3 {
|
||||
public:
|
||||
CMatrix3() = default;
|
||||
CMatrix3(const std::array<std::array<double, 3>, 3>& values);
|
||||
|
||||
CMatrix3 invert() const;
|
||||
CColor::XYZ operator*(const CColor::XYZ& xyz) const;
|
||||
CMatrix3 operator*(const CMatrix3& other) const;
|
||||
|
||||
const std::array<std::array<double, 3>, 3>& mat();
|
||||
|
||||
static const CMatrix3& identity();
|
||||
|
||||
private:
|
||||
std::array<std::array<double, 3>, 3> m = {
|
||||
0, 0, 0, //
|
||||
0, 0, 0, //
|
||||
0, 0, 0, //
|
||||
};
|
||||
};
|
||||
|
||||
CColor::XYZ xy2xyz(const CColor::xy& xy);
|
||||
CMatrix3 adaptWhite(const CColor::xy& src, const CColor::xy& dst);
|
||||
|
||||
struct SPCPRimaries {
|
||||
CColor::xy red, green, blue, white;
|
||||
|
||||
bool operator==(const SPCPRimaries& p2) const {
|
||||
return red == p2.red && green == p2.green && blue == p2.blue && white == p2.white;
|
||||
}
|
||||
|
||||
CMatrix3 toXYZ() const; // toXYZ() * rgb -> xyz
|
||||
CMatrix3 convertMatrix(const SPCPRimaries& dst) const; // convertMatrix(dst) * rgb with "this" primaries -> rgb with dst primaries
|
||||
};
|
||||
};
|
||||
|
|
|
@ -26,6 +26,114 @@ static double hueToRgb(double p, double q, double t) {
|
|||
return p;
|
||||
}
|
||||
|
||||
Hyprgraphics::CMatrix3::CMatrix3(const std::array<std::array<double, 3>, 3>& values) : m(values) {}
|
||||
|
||||
CMatrix3 Hyprgraphics::CMatrix3::invert() const {
|
||||
double invDet = 1 /
|
||||
(0 //
|
||||
+ m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) //
|
||||
- m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]) //
|
||||
+ m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]) //
|
||||
);
|
||||
|
||||
return CMatrix3(std::array<std::array<double, 3>, 3>{
|
||||
(m[1][1] * m[2][2] - m[2][1] * m[1][2]) * invDet, (m[0][2] * m[2][1] - m[0][1] * m[2][2]) * invDet, (m[0][1] * m[1][2] - m[0][2] * m[1][1]) * invDet, //
|
||||
(m[1][2] * m[2][0] - m[1][0] * m[2][2]) * invDet, (m[0][0] * m[2][2] - m[0][2] * m[2][0]) * invDet, (m[1][0] * m[0][2] - m[0][0] * m[1][2]) * invDet, //
|
||||
(m[1][0] * m[2][1] - m[2][0] * m[1][1]) * invDet, (m[2][0] * m[0][1] - m[0][0] * m[2][1]) * invDet, (m[0][0] * m[1][1] - m[1][0] * m[0][1]) * invDet, //
|
||||
});
|
||||
}
|
||||
|
||||
CColor::XYZ Hyprgraphics::CMatrix3::operator*(const CColor::XYZ& value) const {
|
||||
return CColor::XYZ{
|
||||
m[0][0] * value.x + m[0][1] * value.y + m[0][2] * value.z, //
|
||||
m[1][0] * value.x + m[1][1] * value.y + m[1][2] * value.z, //
|
||||
m[2][0] * value.x + m[2][1] * value.y + m[2][2] * value.z, //
|
||||
};
|
||||
}
|
||||
|
||||
CMatrix3 Hyprgraphics::CMatrix3::operator*(const CMatrix3& other) const {
|
||||
std::array<std::array<double, 3>, 3> res = {0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
for (int k = 0; k < 3; k++) {
|
||||
res[i][j] += m[i][k] * other.m[k][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
return CMatrix3(res);
|
||||
}
|
||||
|
||||
const std::array<std::array<double, 3>, 3>& Hyprgraphics::CMatrix3::mat() {
|
||||
return m;
|
||||
};
|
||||
|
||||
const CMatrix3& CMatrix3::identity() {
|
||||
static const CMatrix3 Identity3 = CMatrix3(std::array<std::array<double, 3>, 3>{
|
||||
1, 0, 0, //
|
||||
0, 1, 0, //
|
||||
0, 0, 1, //
|
||||
});
|
||||
return Identity3;
|
||||
}
|
||||
|
||||
CColor::XYZ Hyprgraphics::xy2xyz(const CColor::xy& xy) {
|
||||
if (xy.y == 0.0)
|
||||
return {0.0, 0.0, 0.0};
|
||||
|
||||
return {xy.x / xy.y, 1.0, (1.0 - xy.x - xy.y) / xy.y};
|
||||
}
|
||||
|
||||
CMatrix3 Bradford = CMatrix3(std::array<std::array<double, 3>, 3>{
|
||||
0.8951, 0.2664, -0.1614, //
|
||||
-0.7502, 1.7135, 0.0367, //
|
||||
0.0389, -0.0685, 1.0296, //
|
||||
});
|
||||
|
||||
CMatrix3 BradfordInv = Bradford.invert();
|
||||
|
||||
CMatrix3 Hyprgraphics::adaptWhite(const CColor::xy& src, const CColor::xy& dst) {
|
||||
if (src == dst)
|
||||
return CMatrix3::identity();
|
||||
|
||||
const auto srcXYZ = xy2xyz(src);
|
||||
const auto dstXYZ = xy2xyz(dst);
|
||||
const auto factors = (Bradford * dstXYZ) / (Bradford * srcXYZ);
|
||||
|
||||
return BradfordInv *
|
||||
CMatrix3(std::array<std::array<double, 3>, 3>{
|
||||
factors.x, 0.0, 0.0, //
|
||||
0.0, factors.y, 0.0, //
|
||||
0.0, 0.0, factors.z, //
|
||||
}) *
|
||||
Bradford;
|
||||
}
|
||||
|
||||
CMatrix3 Hyprgraphics::SPCPRimaries::toXYZ() const {
|
||||
const auto r = xy2xyz(red);
|
||||
const auto g = xy2xyz(green);
|
||||
const auto b = xy2xyz(blue);
|
||||
const auto w = xy2xyz(white);
|
||||
|
||||
const auto invMat = CMatrix3(std::array<std::array<double, 3>, 3>{
|
||||
r.x, g.x, b.x, //
|
||||
r.y, g.y, b.y, //
|
||||
r.z, g.z, b.z, //
|
||||
})
|
||||
.invert();
|
||||
|
||||
const auto s = invMat * w;
|
||||
|
||||
return std::array<std::array<double, 3>, 3>{
|
||||
s.x * r.x, s.y * g.x, s.z * b.x, //
|
||||
s.x * r.y, s.y * g.y, s.z * b.y, //
|
||||
s.x * r.z, s.y * g.z, s.z * b.z, //
|
||||
};
|
||||
}
|
||||
|
||||
CMatrix3 Hyprgraphics::SPCPRimaries::convertMatrix(const SPCPRimaries& dst) const {
|
||||
return dst.toXYZ().invert() * adaptWhite(white, dst.white) * toXYZ();
|
||||
}
|
||||
|
||||
Hyprgraphics::CColor::CColor() {
|
||||
;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue