11#include <promeki/config.h>
12#if PROMEKI_ENABLE_CORE
21PROMEKI_NAMESPACE_BEGIN
114 PROMEKI_DATATYPE(Color, DataTypeColor, 1)
117 Error writeToStream(DataStream &s) const;
119 template <uint32_t V> static Result<Color> readFromStream(DataStream &s);
144 static const Color Black;
145 static const Color White;
146 static const Color Red;
147 static const Color Green;
148 static const Color Blue;
149 static const Color Yellow;
150 static const Color Cyan;
151 static const Color Magenta;
152 static const Color DarkGray;
153 static const Color LightGray;
154 static const Color Orange;
155 static const Color Transparent;
156 static const Color Ignored;
162 static Color srgb(
float r,
float g,
float b,
float a = 1.0f) {
163 return Color(ColorModel::sRGB, r, g, b, a);
167 static Color linearSrgb(
float r,
float g,
float b,
float a = 1.0f) {
168 return Color(ColorModel::LinearSRGB, r, g, b, a);
172 static Color rec709(
float r,
float g,
float b,
float a = 1.0f) {
173 return Color(ColorModel::Rec709, r, g, b, a);
177 static Color hsv(
float h,
float s,
float v,
float a = 1.0f) {
178 return Color(ColorModel::HSV_sRGB, h, s, v, a);
182 static Color hsl(
float h,
float s,
float l,
float a = 1.0f) {
183 return Color(ColorModel::HSL_sRGB, h, s, l, a);
187 static Color ycbcr709(
float y,
float cb,
float cr,
float a = 1.0f) {
188 return Color(ColorModel::YCbCr_Rec709, y, cb, cr, a);
192 static Color ycbcr601(
float y,
float cb,
float cr,
float a = 1.0f) {
193 return Color(ColorModel::YCbCr_Rec601, y, cb, cr, a);
197 static Color xyz(
float x,
float y,
float z,
float a = 1.0f) {
198 return Color(ColorModel::CIEXYZ, x, y, z, a);
202 static Color lab(
float l,
float a,
float b,
float alpha = 1.0f) {
203 return Color(ColorModel::CIELab, l, a, b, alpha);
211 static Color fromHex(
const String &hex);
229 static Result<Color> fromString(
const String &str);
240 static Color fromNative(
const ColorModel &model,
float n0,
float n1,
float n2,
float n3 = 1.0f);
255 Color(
const ColorModel &model,
float c0,
float c1,
float c2,
float c3 = 1.0f)
256 : _c{c0, c1, c2, c3}, _model(model) {}
266 Color(ColorModel::ID
id,
float c0,
float c1,
float c2,
float c3 = 1.0f)
267 : _c{c0, c1, c2, c3}, _model(id) {}
274 Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255)
275 : _c{r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f}, _model(ColorModel::sRGB) {}
280 bool isValid()
const {
return _model.isValid(); }
283 const ColorModel &model()
const {
return _model; }
288 float comp(
size_t index)
const {
return index < 4 ? _c[index] : 0.0f; }
291 void setComp(
size_t index,
float val) {
292 if (index < 4) _c[index] = val;
296 float alpha()
const {
return _c[3]; }
299 float a()
const {
return _c[3]; }
302 void setAlpha(
float val) { _c[3] = val; }
305 void setA(
float val) { _c[3] = val; }
310 float r()
const {
return _c[0]; }
313 float g()
const {
return _c[1]; }
316 float b()
const {
return _c[2]; }
319 void setR(
float val) { _c[0] = val; }
322 void setG(
float val) { _c[1] = val; }
325 void setB(
float val) { _c[2] = val; }
344 float h()
const {
return _c[0]; }
347 float s()
const {
return _c[1]; }
350 float v()
const {
return _c[2]; }
353 float l()
const {
return _c[0]; }
358 float y()
const {
return _c[0]; }
361 float cb()
const {
return _c[1]; }
364 float cr()
const {
return _c[2]; }
373 Color convert(
const ColorModel &target)
const;
379 Color toLinearRGB()
const;
388 Color toYCbCr709()
const;
410 String toString(StringFormat fmt = ModelFormat, AlphaMode alpha = AlphaAuto)
const;
420 String toHex(
bool includeAlpha =
false)
const;
430 Color lerp(
const Color &other,
double t)
const;
437 Color inverted()
const;
444 double luminance()
const;
451 Color contrastingBW()
const;
458 Color complementary()
const;
465 float toNative(
size_t comp)
const;
473 bool isClose(
const Color &other,
float epsilon = 1e-5f)
const;
476 bool operator==(
const Color &other)
const {
477 return _model == other._model && _c[0] == other._c[0] && _c[1] == other._c[1] &&
478 _c[2] == other._c[2] && _c[3] == other._c[3];
482 bool operator!=(
const Color &other)
const {
return !(*
this == other); }
488 using List = ::promeki::List<Color>;
512 size_t nearestPaletteIndex(
const Color *palette,
size_t n)
const;
515 size_t nearestPaletteIndex(
const List &palette)
const {
516 return nearestPaletteIndex(palette.data(), palette.size());
522 Color nearestPaletteColor(
const List &palette)
const {
523 if (palette.isEmpty())
return Color();
524 return palette[nearestPaletteIndex(palette)];
528 float _c[4] = {0.0f, 0.0f, 0.0f, 0.0f};
532 Color ensureSRGB()
const;
535inline const Color Color::Black{(uint8_t)0, (uint8_t)0, (uint8_t)0};
536inline const Color Color::White{(uint8_t)255, (uint8_t)255, (uint8_t)255};
537inline const Color Color::Red{(uint8_t)255, (uint8_t)0, (uint8_t)0};
538inline const Color Color::Green{(uint8_t)0, (uint8_t)255, (uint8_t)0};
539inline const Color Color::Blue{(uint8_t)0, (uint8_t)0, (uint8_t)255};
540inline const Color Color::Yellow{(uint8_t)255, (uint8_t)255, (uint8_t)0};
541inline const Color Color::Cyan{(uint8_t)0, (uint8_t)255, (uint8_t)255};
542inline const Color Color::Magenta{(uint8_t)255, (uint8_t)0, (uint8_t)255};
543inline const Color Color::DarkGray{(uint8_t)64, (uint8_t)64, (uint8_t)64};
544inline const Color Color::LightGray{(uint8_t)192, (uint8_t)192, (uint8_t)192};
545inline const Color Color::Orange{(uint8_t)255, (uint8_t)165, (uint8_t)0};
546inline const Color Color::Transparent{(uint8_t)0, (uint8_t)0, (uint8_t)0, (uint8_t)0};
547inline const Color Color::Ignored{};
551PROMEKI_FORMAT_VIA_TOSTRING(promeki::Color);