mirror of
https://github.com/hyprwm/hyprgraphics.git
synced 2025-05-14 22:30:38 +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
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
namespace Hyprgraphics {
|
namespace Hyprgraphics {
|
||||||
class CColor {
|
class CColor {
|
||||||
public:
|
public:
|
||||||
|
@ -18,6 +19,25 @@ namespace Hyprgraphics {
|
||||||
double l = 0, a = 0, b = 0;
|
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(); // black
|
||||||
CColor(const SSRGB& rgb);
|
CColor(const SSRGB& rgb);
|
||||||
CColor(const SHSL& hsl);
|
CColor(const SHSL& hsl);
|
||||||
|
@ -35,4 +55,40 @@ namespace Hyprgraphics {
|
||||||
// SRGB space for internal color storage
|
// SRGB space for internal color storage
|
||||||
double r = 0, g = 0, b = 0;
|
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;
|
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() {
|
Hyprgraphics::CColor::CColor() {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue