11#include <promeki/config.h>
12#if PROMEKI_ENABLE_CORE
23PROMEKI_NAMESPACE_BEGIN
145 PROMEKI_DATATYPE(ColorModel, DataTypeColorModel, 1)
148 Error writeToStream(DataStream &s) const;
150 template <uint32_t V> static Result<ColorModel> readFromStream(DataStream &s);
166 LinearRec601_PAL = 6,
168 LinearRec601_NTSC = 8,
192 YCbCr_Rec2020_PQ = 26,
193 YCbCr_Rec2020_HLG = 27,
243 typedef double (*TransferFunc)(double);
255 typedef Array<CIEPoint, 4> Primaries;
258 using IDList = ::promeki::List<ID>;
272 Type type = TypeInvalid;
276 CompInfo comps[3] = {};
277 TransferFunc oetf =
nullptr;
278 TransferFunc eotf =
nullptr;
280 ID linearCounterpart = Invalid;
281 ID nonlinearCounterpart = Invalid;
282 ID parentModel = Invalid;
285 Matrix3x3 toParentMatrix;
286 Matrix3x3 fromParentMatrix;
287 float toParentOffset[3] = {};
288 float fromParentOffset[3] = {};
289 void (*toXYZFunc)(
const Data *d,
const float *src,
290 float *dst) =
nullptr;
291 void (*fromXYZFunc)(
const Data *d,
const float *src,
292 float *dst) =
nullptr;
303 static ID registerType();
314 static void registerData(Data &&data);
323 static IDList registeredIDs();
330 static ColorModel lookup(
const String &name);
343 static Result<ColorModel> fromString(
const String &name) {
344 ColorModel m = lookup(name);
345 if (!m.isValid())
return makeError<ColorModel>(Error::IdNotFound);
346 return makeResult(m);
368 uint8_t primaries = 0;
369 uint8_t transfer = 0;
395 static H273 toH273(ID
id);
403 inline ColorModel(ID
id = Invalid);
406 ID id()
const {
return _d->id; }
409 bool isValid()
const {
return _d !=
nullptr && _d->type != TypeInvalid; }
412 bool operator==(
const ColorModel &other)
const {
return _d == other._d; }
415 bool operator!=(
const ColorModel &other)
const {
return _d != other._d; }
418 Type type()
const {
return _d->type; }
421 const String &name()
const {
return _d->name; }
424 String toString()
const {
return _d->name; }
427 const String &desc()
const {
return _d->desc; }
434 size_t compCount()
const {
return 3; }
441 const CompInfo &compInfo(
size_t index)
const {
return _d->comps[index < 3 ? index : 0]; }
448 const Primaries &primaries()
const {
return _d->primaries; }
456 const CIEPoint &whitePoint()
const {
return _d->primaries[3]; }
461 bool isLinear()
const {
return _d->linear; }
470 inline ColorModel linearCounterpart()
const;
478 inline ColorModel nonlinearCounterpart()
const;
486 double applyTransfer(
double linear)
const {
return _d->oetf(linear); }
494 double removeTransfer(
double encoded)
const {
return _d->eotf(encoded); }
503 inline ColorModel parentModel()
const;
511 void toXYZ(
const float *src,
float *dst)
const { _d->toXYZFunc(_d, src, dst); }
519 void fromXYZ(
const float *src,
float *dst)
const { _d->fromXYZFunc(_d, src, dst); }
527 float toNative(
size_t comp,
float normalized)
const {
528 if (comp >= 3)
return 0.0f;
529 const CompInfo &ci = _d->comps[comp];
530 return ci.nativeMin + normalized * (ci.nativeMax - ci.nativeMin);
539 float fromNative(
size_t comp,
float native)
const {
540 if (comp >= 3)
return 0.0f;
541 const CompInfo &ci = _d->comps[comp];
542 float range = ci.nativeMax - ci.nativeMin;
543 if (range == 0.0f)
return 0.0f;
544 return (native - ci.nativeMin) / range;
548 const Data *data()
const {
return _d; }
551 const Data *_d =
nullptr;
552 static const Data *lookupData(ID
id);
557inline ColorModel::ColorModel(ID
id) : _d(lookupData(id)) {}
559inline ColorModel ColorModel::linearCounterpart()
const {
560 ID lcid = _d->linearCounterpart;
561 return lcid != Invalid ? ColorModel(lcid) : *this;
564inline ColorModel ColorModel::nonlinearCounterpart()
const {
565 ID nlid = _d->nonlinearCounterpart;
566 return nlid != Invalid ? ColorModel(nlid) : *this;
569inline ColorModel ColorModel::parentModel()
const {
570 return ColorModel(_d->parentModel);