5#include <cgv/defines/assert.h>
6#include <cgv/type/func/promote.h>
7#include <cgv/type/func/promote_const.h>
8#include <cgv/type/traits/max.h>
9#include <cgv/type/info/type_name.h>
11#include "color_model.h"
25 static float value() {
return 1.0f; }
30 static double value() {
return 1.0; }
32template <ColorModel cm>
34 static const unsigned int nr_components = 3;
38 static const unsigned int nr_components = 1;
40template <AlphaModel am>
42 static const unsigned int nr_components = 1;
46 static const unsigned int nr_components = 0;
50template <
typename T, ColorModel cm, AlphaModel am = NO_ALPHA>
65 template <
typename T2, ColorModel cm2, AlphaModel am2>
67 convert_color(c2, *
this);
70 T&
at(
unsigned int i) {
return components[i]; }
72 const T&
at(
unsigned int i)
const {
return components[i]; }
82template <
typename T, ColorModel cm = RGB, AlphaModel = NO_ALPHA>
86template <
typename T, AlphaModel am>
90 template <ColorModel cm>
99 template <ColorModel cm>
103template <
typename T, AlphaModel am>
107 template <ColorModel cm>
114 const T& ref_dummy_alpha() {
static T dummy_alpha =
color_one<T>::value();
return dummy_alpha; }
116 template <ColorModel cm>
127template <
typename T1,
typename T2>
128inline void convert_color_component(
const T1& from, T2& to) {
133inline void convert_color_component(
const unsigned int& from,
unsigned short& to) {
138inline void convert_color_component(
const unsigned int& from,
unsigned char& to) {
143inline void convert_color_component(
const unsigned short& from,
unsigned char& to) {
148inline void convert_color_component(
const unsigned short& from,
unsigned int& to) {
149 to = (
unsigned int) from << 16;
153inline void convert_color_component(
const unsigned char& from,
unsigned int& to) {
154 to = (
unsigned int)from << 24;
158inline void convert_color_component(
const unsigned char& from,
unsigned short& to) {
159 to = (
unsigned short)from << 8;
166template <
typename T1, AlphaModel am1,
typename T2, AlphaModel am2>
167inline void convert_alpha_model(const_alpha_reference<T1,am1> from, alpha_reference<T2,am2> to)
169 color<typename type::func::promote<T1,T2>::type,LUM,OPACITY> tmp;
170 alpha_reference<typename type::func::promote<T1, T2>::type, OPACITY> ref(tmp);
171 convert_alpha_model(from,tmp);
172 convert_alpha_model(tmp,to);
175template <
typename T1,
typename T2>
176void convert_alpha_model(const_alpha_reference<T1, NO_ALPHA> from, alpha_reference<T2, OPACITY> to)
178 to.alpha_ref = color_one<T2>::value();
181template <
typename T1,
typename T2>
182void convert_alpha_model(const_alpha_reference<T1, NO_ALPHA> from, alpha_reference<T2, TRANSPARENCY> to)
184 to.alpha_ref = T2(0);
187template <
typename T1,
typename T2>
188void convert_alpha_model(const_alpha_reference<T1, NO_ALPHA> from, alpha_reference<T2, EXTINCTION> to)
190 to.alpha_ref = color_one<T2>::value();
193template <
typename T1,
typename T2>
194void convert_alpha_model(const_alpha_reference<T1, OPACITY> from, alpha_reference<T2, TRANSPARENCY> to)
196 convert_color_component(from.alpha_ref, to.alpha_ref);
197 to.alpha_ref = color_one<T2>::value() - to.alpha_ref;
200template <
typename T1,
typename T2>
201void convert_alpha_model(const_alpha_reference<T1, TRANSPARENCY> from, alpha_reference<T2, OPACITY> to)
203 convert_color_component(from.alpha_ref, to.alpha_ref);
204 to.alpha_ref = color_one<T2>::value() - to.alpha_ref;
207template <
typename T1,
typename T2>
208void convert_alpha_model(const_alpha_reference<T1, OPACITY> from, alpha_reference<T2, EXTINCTION> to)
211 convert_color_component(from.alpha_ref, tmp);
213 convert_color_component(tmp, to.alpha_ref);
216template <
typename T1,
typename T2>
217void convert_alpha_model(const_alpha_reference<T1, EXTINCTION> from, alpha_reference<T2, OPACITY> to)
220 convert_color_component(from.alpha_ref, tmp);
222 convert_color_component(tmp, to.alpha_ref);
225template <
typename T1, AlphaModel am1,
typename T2>
226void convert_alpha_model(const_alpha_reference<T1, am1> from, alpha_reference<T2, NO_ALPHA> to)
230template <
typename T1,
typename T2>
231void convert_alpha_model(const_alpha_reference<T1, NO_ALPHA> from, alpha_reference<T2, NO_ALPHA> to)
235template <
typename T1, AlphaModel am,
typename T2>
236void convert_alpha_model(const_alpha_reference<T1, am> from, alpha_reference<T2, am> to)
238 convert_color_component(from.alpha_ref, to.alpha_ref);
247template <
typename T1, ColorModel cm1,
typename T2, ColorModel cm2>
248inline void convert_color_model(
const color_base<T1, cm1>& from, color_base<T2, cm2>& to)
250 color_base<typename type::func::promote<T1, T2>::type, XYZ> tmp;
251 convert_color_model(from, tmp);
252 convert_color_model(tmp, to);
255template <
typename T1, ColorModel cm,
typename T2>
256void convert_color_model(
const color_base<T1, cm>& from, color_base<T2, cm>& to)
258 for (
unsigned int i = 0; i < color_base<T1, cm>::nr_components; ++i)
259 convert_color_component(from.at(i), to.at(i));
262template <
typename T1, ColorModel cm1,
typename T2>
263void convert_color_model(
const color_base<T1, cm1>& from, color_base<T2, XYZ>& to)
265 std::cerr <<
"conversion not implemented" << std::endl;
268template <
typename T1, ColorModel cm2,
typename T2>
269void convert_color_model(
const color_base<T1, XYZ>& from, color_base<T2, cm2>& to)
271 std::cerr <<
"conversion not implemented" << std::endl;
274template <
typename T1,
typename T2>
275void convert_color_model(
const color_base<T1, LUM>& c1, color_base<T2, XYZ>& c2) {
278 convert_color_component(c1.at(0), c2.at(1));
281template <
typename T1,
typename T2>
282void convert_color_model(
const color_base<T1, XYZ>& c1, color_base<T2, LUM>& c2) {
283 convert_color_component(c1.at(1), c2.at(0));
286template <
typename T1,
typename T2>
287void convert_color_model(
const color_base<T1, RGB>& _c1, color_base<T2, XYZ>& c2) {
288 color_base<double, RGB> c1;
289 convert_color_model(_c1,c1);
290 convert_color_component(0.412453 * c1.at(0) + 0.357580 * c1.at(1) + 0.180423 * c1.at(2), c2.at(0));
291 convert_color_component(0.212671 * c1.at(0) + 0.715160 * c1.at(1) + 0.072169 * c1.at(2), c2.at(1));
292 convert_color_component(0.019334 * c1.at(0) + 0.119193 * c1.at(1) + 0.950227 * c1.at(2), c2.at(2));
295template <
typename T1,
typename T2>
296void convert_color_model(
const color_base<T1, XYZ>& _c1, color_base<T2, RGB>& c2) {
297 color_base<double, XYZ> c1(_c1);
298 convert_color_model(_c1, c1);
299 convert_color_component(3.2404813432 * c1.at(0) - 1.5371515163 * c1.at(1) - 0.4985363262 * c1.at(2), c2.at(0));
300 convert_color_component(-0.9692549500 * c1.at(0) + 1.8759900015 * c1.at(1) + 0.0415559266 * c1.at(2), c2.at(1));
301 convert_color_component(0.0556466391 * c1.at(0) - 0.2040413384 * c1.at(1) + 1.0573110696 * c1.at(2), c2.at(2));
304template <
typename T1,
typename T2>
305void convert_color_model(
const color_base<T1, RGB>&
rgb, color_base<T2, HLS>& hls) {
307 convert_color_component(std::max(
rgb.at(0), std::max(
rgb.at(1),
rgb.at(2))), mx);
308 convert_color_component(std::min(
rgb.at(0), std::min(
rgb.at(1),
rgb.at(2))), mn);
309 double LL = (mx + mn) / 2;
311 hls.at(0) = hls.at(2) = 0;
312 convert_color_component(LL, hls.at(1));
317 double SS = (LL <= 0.5) ? DM / SM : DM / (2 - SM);
318 color_base<double, RGB> c;
319 convert_color_model(
rgb, c);
321 if (c.at(0) == mx) HH = (c.at(1) - c.at(2)) / DM;
322 else if (c.at(1) == mx) HH = 2 + (c.at(2) - c.at(0)) / DM;
323 else HH = 4 + (c.at(0) - c.at(1)) / DM;
326 convert_color_component(HH, hls.at(0));
327 convert_color_component(LL, hls.at(1));
328 convert_color_component(SS, hls.at(2));
332template <
typename T1,
typename T2>
333void convert_color_model(
const color_base<T1, HLS>& hls, color_base<T2, RGB>&
rgb) {
335 convert_color_component(hls.at(0), HH); HH *= 6;
336 convert_color_component(hls.at(1), LL);
337 convert_color_component(hls.at(2), SS);
340 while (I >= 6) I -= 6;
341 double mx = (LL <= 0.5) ? LL * (1 + SS) : LL + SS - LL * SS;
342 double mn = 2 * LL - mx;
346 convert_color_component(LL, tmp);
352 convert_color_component(mx,
rgb.at(0));
353 convert_color_component(mn + F * DM,
rgb.at(1));
354 convert_color_component(mn,
rgb.at(2));
357 convert_color_component(mn + (1 - F) * DM,
rgb.at(0));
358 convert_color_component(mx,
rgb.at(1));
359 convert_color_component(mn,
rgb.at(2));
362 convert_color_component(mn,
rgb.at(0));
363 convert_color_component(mx,
rgb.at(1));
364 convert_color_component(mn + F * DM,
rgb.at(2));
367 convert_color_component(mn,
rgb.at(0));
368 convert_color_component(mn + (1 - F) * DM,
rgb.at(1));
369 convert_color_component(mx,
rgb.at(2));
372 convert_color_component(mn + F * DM,
rgb.at(0));
373 convert_color_component(mn,
rgb.at(1));
374 convert_color_component(mx,
rgb.at(2));
377 convert_color_component(mx,
rgb.at(0));
378 convert_color_component(mn,
rgb.at(1));
379 convert_color_component(mn + (1 - F) * DM,
rgb.at(2));
385template <
typename T1,
typename T2>
386void convert_color_model(
const color_base<T1, HLS>& c1, color_base<T2, XYZ>& c2) {
387 color_base<typename type::func::promote<T1, T2>::type, RGB> tmp;
388 convert_color_model(c1, tmp);
389 convert_color_model(tmp, c2);
392template <
typename T1,
typename T2>
393void convert_color_model(
const color_base<T1, XYZ>& c1, color_base<T2, HLS>& c2) {
394 color_base<typename type::func::promote<T1, T2>::type, RGB> tmp;
395 convert_color_model(c1, tmp);
396 convert_color_model(tmp, c2);
400template <
typename T1, ColorModel cm1, AlphaModel am1,
typename T2, ColorModel cm2, AlphaModel am2>
401inline void convert_color(
const color_base<T1,cm1,am1>& from, color_base<T2,cm2,am2>& to)
403 convert_color_model(
reinterpret_cast<const color_base<T1,cm1>&
>(from),
reinterpret_cast<color_base<T2,cm2>&
>(to));
404 convert_alpha_model(const_alpha_reference<T1,am1>(from),alpha_reference<T2,am2>(to));
410template <
typename T, ColorModel cm, AlphaModel am>
421template <
typename T, AlphaModel am>
425 T&
R() {
return this->at(0); }
427 const T&
R()
const {
return this->at(0); }
429 T&
G() {
return this->at(1); }
431 const T&
G()
const {
return this->at(1); }
433 T&
B() {
return this->at(2); }
435 const T&
B()
const {
return this->at(2); }
441template <
typename T, ColorModel cm, AlphaModel am>
452template <
typename T, AlphaModel am>
456 T&
H() {
return this->at(0); }
458 const T&
H()
const {
return this->at(0); }
460 T&
L() {
return this->at(1); }
462 const T&
L()
const {
return this->at(1); }
464 T&
S() {
return this->at(2); }
466 const T&
S()
const {
return this->at(2); }
472template <
typename T, ColorModel cm, AlphaModel am>
483template <
typename T, AlphaModel am>
487 T&
X() {
return this->at(0); }
489 const T&
X()
const {
return this->at(0); }
491 T&
Y() {
return this->at(1); }
493 const T&
Y()
const {
return this->at(1); }
495 T&
Z() {
return this->at(2); }
497 const T&
Z()
const {
return this->at(2); }
503template <
typename T, ColorModel cm, AlphaModel am>
511 return opa_ref.alpha_ref;
515template <
typename T, ColorModel cm>
521 const T&
opacity()
const {
return this->alpha(); }
527template <
typename T, ColorModel cm, AlphaModel am>
535 return tra_ref.alpha_ref;
539template <
typename T, ColorModel cm>
551template <
typename T, ColorModel cm, AlphaModel am>
559 return ext_ref.alpha_ref;
563template <
typename T, ColorModel cm>
573template <
typename T, ColorModel cm, AlphaModel am>
595 this->components[0] = c0;
597 this->components[1] = c1;
600 color(
const T& c0,
const T& c1,
const T& c2) {
601 this->components[0] = c0;
603 this->components[1] = c1;
605 this->components[2] = c2;
608 color(
const T& c0,
const T& c1,
const T& c2,
const T& c3) {
609 this->components[0] = c0;
611 this->components[1] = c1;
613 this->components[2] = c2;
615 this->components[3] = c3;
619 this->
at(nr_components - 1) = a;
624 template <
typename T2, ColorModel cm2, AlphaModel am2>
626 convert_color(c2, *
this);
629 template <
typename T2, ColorModel cm2, AlphaModel am2>
631 convert_color(c2, *
this);
636 std::fill(this->components, this->components+
nr_components, c);
643 template <
typename T2, ColorModel cm2, AlphaModel am2>
647 this->
at(i) *= tmp[i];
651 template <
typename T2, ColorModel cm2, AlphaModel am2>
664 template <
typename T2>
668 res[i] = this->
at(i)*c;
672 template <
typename T2, ColorModel cm2, AlphaModel am2>
676 this->
at(i) += tmp[i];
680 template <
typename T2, ColorModel cm2, AlphaModel am2>
699 template <
typename T2, ColorModel cm2, AlphaModel am2>
703 this->
at(i) -= tmp[i];
707 template <
typename T2, ColorModel cm2, AlphaModel am2>
728 for (
unsigned i = 0; i < nr; ++i)
729 if (this->
at(i) < mn)
731 else if (this->
at(i) > mx)
741#define CGV_MEDIA_COLOR_DECLARED
750template <
typename T, ColorModel cm, AlphaModel am>
751bool operator == (
const color<T,cm,am>& c1,
const color<T,cm,am>& c2) {
752 for (
unsigned int i=0; i<color<T,cm,am>::nr_components; ++i)
758template <
typename T1, ColorModel cm1, AlphaModel am1,
typename T2, ColorModel cm2, AlphaModel am2>
759color<typename type::func::promote<T1,T2>::type,cm1,am1> operator * (
const color<T1,cm1,am1>& c1,
const color<T2,cm2,am2>& c2) {
760 color<typename type::func::promote<T1,T2>::type,cm1,am1> res(c1);
765template <
typename T1,
typename T2, ColorModel cm2, AlphaModel am2>
766color<typename type::func::promote<T1,T2>::type,cm2,am2> operator * (
const T1& c1,
const color<T2,cm2,am2>& c2) {
767 color<typename type::func::promote<T1,T2>::type,cm2,am2> res(c2);
772template <
typename T1, ColorModel cm1, AlphaModel am1,
typename T2, ColorModel cm2, AlphaModel am2>
773color<typename type::func::promote<T1,T2>::type,cm1,am1> operator + (
const color<T1,cm1,am1>& c1,
const color<T2,cm2,am2>& c2) {
774 color<typename type::func::promote<T1,T2>::type,cm1,am1> res(c1);
779template <
typename T1, ColorModel cm1, AlphaModel am1>
780std::ostream& operator << (std::ostream& os,
const color<T1,cm1,am1>& c) {
782 for (
unsigned int i=1; i<color<T1,cm1,am1>::nr_components; ++i)
787template <
typename T1, ColorModel cm1, AlphaModel am1>
788std::istream& operator >> (std::istream& is, color<T1,cm1,am1>& c) {
790 for (
unsigned int i=1; i<color<T1,cm1,am1>::nr_components; ++i)
795template <ColorModel cm, AlphaModel am>
796std::ostream& operator << (std::ostream& os,
const color<unsigned char,cm,am>& c) {
798 for (
unsigned int i=1; i<color<unsigned char,cm,am>::nr_components; ++i)
799 os <<
" " << (
int)c[i];
803template <ColorModel cm, AlphaModel am>
804std::istream& operator >> (std::istream& is, color<unsigned char,cm,am>& c) {
807 c[0] = (
unsigned char)tmp;
808 for (
unsigned int i=1; i<color<unsigned char,cm,am>::nr_components; ++i) {
810 c[i] = (
unsigned char)tmp;
822template <
typename T, ColorModel cm, AlphaModel am>
823const color<T,cm,am> lerp(
const color<T,cm,am>& c1,
const color<T,cm,am>& c2, T t) {
824 return ((T)1 - t) * c1 + t * c2;
828template<
typename T1,
typename T2, AlphaModel am>
829const color<T1, RGB, am> pow(
const color<T1, RGB, am>& c, T2 e) {
830 color<T1, RGB, am> x = c;
831 for(
unsigned int i = 0; i < color<T1, RGB, am>::nr_color_components; ++i) {
833 convert_color_component(x[i], v);
834 convert_color_component(std::pow(v, e), x[i]);
840template<
typename T, AlphaModel am>
841const color<T, RGB, am> inv(
const color<T, RGB, am>& c) {
843 for(
unsigned int i = 0; i < color<T, RGB, am>::nr_components; ++i) {
844 x[i] = color_one<T>::value() - c[i];
850template<
typename T, AlphaModel am>
851std::string
to_hex(
const color<T, RGB, am>& c) {
852 std::string res =
"0x";
854 std::string buf =
"00";
858 convert_color_component(c[i], v);
860 res[2 * i + 2] = buf[0];
861 res[2 * i + 3] = buf[1];
867template<
typename T, AlphaModel am>
868bool from_hex(
const std::string& s, color<T, RGB, am>& c) {
871 if(s.length() > 1 && s[0] ==
'0' && s[1] ==
'x')
879 uint8_t v = parsed[i + off];
880 convert_color_component(v, c[i]);
std::string to_hex(uint8_t v, bool use_upper_case)
convert to hex
uint8_t from_hex(char c)
convert from hex character
std::vector< uint8_t > parse_hex_bytes(const std::string &byte_str)
parse bytes hex coded bytes
cgv::media::color< cgv::type::uint8_type, cgv::media::RGB, cgv::media::OPACITY > rgba8
declare rgba color type with 8 bit components
cgv::media::color< float, cgv::media::RGB, cgv::media::OPACITY > rgba
declare rgba color type with 32 bit components
cgv::media::color< float, cgv::media::RGB > rgb
declare rgb color type with 32 bit components
cgv::media::color< cgv::type::uint8_type, cgv::media::RGB > rgb8
declare rgb color type with 8 bit components
Helper functions to process strings.
the max traits defines for each type in the static const member value, what the maximum value is.