CM structs, constants & math

This commit is contained in:
UjinT34 2025-03-31 18:17:57 +03:00
parent 175c6b29b6
commit 181e4c1964
2 changed files with 161 additions and 1 deletions

View file

@ -1,5 +1,6 @@
#pragma once
#include <array>
namespace Hyprgraphics {
class CColor {
public:
@ -18,6 +19,24 @@ 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;
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 +46,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 +54,46 @@ namespace Hyprgraphics {
// SRGB space for internal color storage
double r = 0, g = 0, b = 0;
};
typedef std::array<double, 3> vec3;
typedef std::array<vec3, 3> mat3;
class CMatrix3 {
public:
CMatrix3() = default;
CMatrix3(const mat3& values);
CMatrix3 invert();
CColor::XYZ operator*(const CColor::XYZ& xyz) const;
CMatrix3 operator*(const CMatrix3& other) const;
const mat3& mat();
private:
mat3 m = {
0, 0, 0, //
0, 0, 0, //
0, 0, 0, //
};
};
const CMatrix3 Identity3 = CMatrix3(mat3{
1, 0, 0, //
0, 1, 0, //
0, 0, 1, //
});
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;
CMatrix3 convertMatrix(const SPCPRimaries& dst) const;
};
};

View file

@ -26,6 +26,105 @@ static double hueToRgb(double p, double q, double t) {
return p;
}
Hyprgraphics::CMatrix3::CMatrix3(const mat3& values) : m(values) {}
CMatrix3 Hyprgraphics::CMatrix3::invert() {
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(mat3{
(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 {
mat3 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 mat3& Hyprgraphics::CMatrix3::mat() {
return m;
};
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(mat3{
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 Identity3;
const auto srcXYZ = xy2xyz(src);
const auto dstXYZ = xy2xyz(dst);
const auto factors = (Bradford * dstXYZ) / (Bradford * srcXYZ);
return BradfordInv *
CMatrix3(mat3{
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(mat3{
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 mat3{
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() {
;
}