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>
10#include "color_model.h"
24 static float value() {
return 1.0f; }
29 static double value() {
return 1.0; }
31template <ColorModel cm>
33 static const unsigned int nr_components = 3;
37 static const unsigned int nr_components = 1;
39template <AlphaModel am>
41 static const unsigned int nr_components = 1;
45 static const unsigned int nr_components = 0;
49template <
typename T, ColorModel cm, AlphaModel am = NO_ALPHA>
64 template <
typename T2, ColorModel cm2, AlphaModel am2>
66 convert_color(c2, *
this);
69 T&
at(
unsigned int i) {
return components[i]; }
71 const T&
at(
unsigned int i)
const {
return components[i]; }
81template <
typename T, ColorModel cm = RGB, AlphaModel = NO_ALPHA>
85template <
typename T, AlphaModel am>
89 template <ColorModel cm>
98 template <ColorModel cm>
102template <
typename T, AlphaModel am>
106 template <ColorModel cm>
113 const T& ref_dummy_alpha() {
static T dummy_alpha =
color_one<T>::value();
return dummy_alpha; }
115 template <ColorModel cm>
126template <
typename T1,
typename T2>
127inline void convert_color_component(
const T1& from, T2& to) {
132inline void convert_color_component(
const unsigned int& from,
unsigned short& to) {
137inline void convert_color_component(
const unsigned int& from,
unsigned char& to) {
142inline void convert_color_component(
const unsigned short& from,
unsigned char& to) {
147inline void convert_color_component(
const unsigned short& from,
unsigned int& to) {
148 to = (
unsigned int) from << 16;
152inline void convert_color_component(
const unsigned char& from,
unsigned int& to) {
153 to = (
unsigned int)from << 24;
157inline void convert_color_component(
const unsigned char& from,
unsigned short& to) {
158 to = (
unsigned short)from << 8;
165template <
typename T1, AlphaModel am1,
typename T2, AlphaModel am2>
166inline void convert_alpha_model(const_alpha_reference<T1,am1> from, alpha_reference<T2,am2> to)
168 color<typename type::func::promote<T1,T2>::type,LUM,OPACITY> tmp;
169 alpha_reference<typename type::func::promote<T1, T2>::type, OPACITY> ref(tmp);
170 convert_alpha_model(from,tmp);
171 convert_alpha_model(tmp,to);
174template <
typename T1,
typename T2>
175void convert_alpha_model(const_alpha_reference<T1, NO_ALPHA> from, alpha_reference<T2, OPACITY> to)
177 to.alpha_ref = color_one<T2>::value();
180template <
typename T1,
typename T2>
181void convert_alpha_model(const_alpha_reference<T1, NO_ALPHA> from, alpha_reference<T2, TRANSPARENCY> to)
183 to.alpha_ref = T2(0);
186template <
typename T1,
typename T2>
187void convert_alpha_model(const_alpha_reference<T1, NO_ALPHA> from, alpha_reference<T2, EXTINCTION> to)
189 to.alpha_ref = color_one<T2>::value();
192template <
typename T1,
typename T2>
193void convert_alpha_model(const_alpha_reference<T1, OPACITY> from, alpha_reference<T2, TRANSPARENCY> to)
195 convert_color_component(from.alpha_ref, to.alpha_ref);
196 to.alpha_ref = color_one<T2>::value() - to.alpha_ref;
199template <
typename T1,
typename T2>
200void convert_alpha_model(const_alpha_reference<T1, TRANSPARENCY> from, alpha_reference<T2, OPACITY> to)
202 convert_color_component(from.alpha_ref, to.alpha_ref);
203 to.alpha_ref = color_one<T2>::value() - to.alpha_ref;
206template <
typename T1,
typename T2>
207void convert_alpha_model(const_alpha_reference<T1, OPACITY> from, alpha_reference<T2, EXTINCTION> to)
210 convert_color_component(from.alpha_ref, tmp);
212 convert_color_component(tmp, to.alpha_ref);
215template <
typename T1,
typename T2>
216void convert_alpha_model(const_alpha_reference<T1, EXTINCTION> from, alpha_reference<T2, OPACITY> to)
219 convert_color_component(from.alpha_ref, tmp);
221 convert_color_component(tmp, to.alpha_ref);
224template <
typename T1, AlphaModel am1,
typename T2>
225void convert_alpha_model(const_alpha_reference<T1, am1> from, alpha_reference<T2, NO_ALPHA> to)
229template <
typename T1,
typename T2>
230void convert_alpha_model(const_alpha_reference<T1, NO_ALPHA> from, alpha_reference<T2, NO_ALPHA> to)
234template <
typename T1, AlphaModel am,
typename T2>
235void convert_alpha_model(const_alpha_reference<T1, am> from, alpha_reference<T2, am> to)
237 convert_color_component(from.alpha_ref, to.alpha_ref);
246template <
typename T1, ColorModel cm1,
typename T2, ColorModel cm2>
247inline void convert_color_model(
const color_base<T1, cm1>& from, color_base<T2, cm2>& to)
249 color_base<typename type::func::promote<T1, T2>::type, XYZ> tmp;
250 convert_color_model(from, tmp);
251 convert_color_model(tmp, to);
254template <
typename T1, ColorModel cm,
typename T2>
255void convert_color_model(
const color_base<T1, cm>& from, color_base<T2, cm>& to)
257 for (
unsigned int i = 0; i < color_base<T1, cm>::nr_components; ++i)
258 convert_color_component(from.at(i), to.at(i));
261template <
typename T1, ColorModel cm1,
typename T2>
262void convert_color_model(
const color_base<T1, cm1>& from, color_base<T2, XYZ>& to)
264 std::cerr <<
"conversion not implemented" << std::endl;
267template <
typename T1, ColorModel cm2,
typename T2>
268void convert_color_model(
const color_base<T1, XYZ>& from, color_base<T2, cm2>& to)
270 std::cerr <<
"conversion not implemented" << std::endl;
273template <
typename T1,
typename T2>
274void convert_color_model(
const color_base<T1, LUM>& c1, color_base<T2, XYZ>& c2) {
277 convert_color_component(c1.at(0), c2.at(1));
280template <
typename T1,
typename T2>
281void convert_color_model(
const color_base<T1, XYZ>& c1, color_base<T2, LUM>& c2) {
282 convert_color_component(c1.at(1), c2.at(0));
285template <
typename T1,
typename T2>
286void convert_color_model(
const color_base<T1, RGB>& _c1, color_base<T2, XYZ>& c2) {
287 color_base<double, RGB> c1;
288 convert_color_model(_c1,c1);
289 convert_color_component(0.412453 * c1.at(0) + 0.357580 * c1.at(1) + 0.180423 * c1.at(2), c2.at(0));
290 convert_color_component(0.212671 * c1.at(0) + 0.715160 * c1.at(1) + 0.072169 * c1.at(2), c2.at(1));
291 convert_color_component(0.019334 * c1.at(0) + 0.119193 * c1.at(1) + 0.950227 * c1.at(2), c2.at(2));
294template <
typename T1,
typename T2>
295void convert_color_model(
const color_base<T1, XYZ>& _c1, color_base<T2, RGB>& c2) {
296 color_base<double, XYZ> c1(_c1);
297 convert_color_model(_c1, c1);
298 convert_color_component(3.2404813432 * c1.at(0) - 1.5371515163 * c1.at(1) - 0.4985363262 * c1.at(2), c2.at(0));
299 convert_color_component(-0.9692549500 * c1.at(0) + 1.8759900015 * c1.at(1) + 0.0415559266 * c1.at(2), c2.at(1));
300 convert_color_component(0.0556466391 * c1.at(0) - 0.2040413384 * c1.at(1) + 1.0573110696 * c1.at(2), c2.at(2));
303template <
typename T1,
typename T2>
304void convert_color_model(
const color_base<T1, RGB>&
rgb, color_base<T2, HLS>& hls) {
306 convert_color_component(std::max(
rgb.at(0), std::max(
rgb.at(1),
rgb.at(2))), mx);
307 convert_color_component(std::min(
rgb.at(0), std::min(
rgb.at(1),
rgb.at(2))), mn);
308 double LL = (mx + mn) / 2;
310 hls.at(0) = hls.at(2) = 0;
311 convert_color_component(LL, hls.at(1));
316 double SS = (LL <= 0.5) ? DM / SM : DM / (2 - SM);
317 color_base<double, RGB> c;
318 convert_color_model(
rgb, c);
320 if (c.at(0) == mx) HH = (c.at(1) - c.at(2)) / DM;
321 else if (c.at(1) == mx) HH = 2 + (c.at(2) - c.at(0)) / DM;
322 else HH = 4 + (c.at(0) - c.at(1)) / DM;
325 convert_color_component(HH, hls.at(0));
326 convert_color_component(LL, hls.at(1));
327 convert_color_component(SS, hls.at(2));
331template <
typename T1,
typename T2>
332void convert_color_model(
const color_base<T1, HLS>& hls, color_base<T2, RGB>&
rgb) {
334 convert_color_component(hls.at(0), HH); HH *= 6;
335 convert_color_component(hls.at(1), LL);
336 convert_color_component(hls.at(2), SS);
339 while (I >= 6) I -= 6;
340 double mx = (LL <= 0.5) ? LL * (1 + SS) : LL + SS - LL * SS;
341 double mn = 2 * LL - mx;
345 convert_color_component(LL, tmp);
351 convert_color_component(mx,
rgb.at(0));
352 convert_color_component(mn + F * DM,
rgb.at(1));
353 convert_color_component(mn,
rgb.at(2));
356 convert_color_component(mn + (1 - F) * DM,
rgb.at(0));
357 convert_color_component(mx,
rgb.at(1));
358 convert_color_component(mn,
rgb.at(2));
361 convert_color_component(mn,
rgb.at(0));
362 convert_color_component(mx,
rgb.at(1));
363 convert_color_component(mn + F * DM,
rgb.at(2));
366 convert_color_component(mn,
rgb.at(0));
367 convert_color_component(mn + (1 - F) * DM,
rgb.at(1));
368 convert_color_component(mx,
rgb.at(2));
371 convert_color_component(mn + F * DM,
rgb.at(0));
372 convert_color_component(mn,
rgb.at(1));
373 convert_color_component(mx,
rgb.at(2));
376 convert_color_component(mx,
rgb.at(0));
377 convert_color_component(mn,
rgb.at(1));
378 convert_color_component(mn + (1 - F) * DM,
rgb.at(2));
384template <
typename T1,
typename T2>
385void convert_color_model(
const color_base<T1, HLS>& c1, color_base<T2, XYZ>& c2) {
386 color_base<typename type::func::promote<T1, T2>::type, RGB> tmp;
387 convert_color_model(c1, tmp);
388 convert_color_model(tmp, c2);
391template <
typename T1,
typename T2>
392void convert_color_model(
const color_base<T1, XYZ>& c1, color_base<T2, HLS>& c2) {
393 color_base<typename type::func::promote<T1, T2>::type, RGB> tmp;
394 convert_color_model(c1, tmp);
395 convert_color_model(tmp, c2);
399template <
typename T1, ColorModel cm1, AlphaModel am1,
typename T2, ColorModel cm2, AlphaModel am2>
400inline void convert_color(
const color_base<T1,cm1,am1>& from, color_base<T2,cm2,am2>& to)
402 convert_color_model(
reinterpret_cast<const color_base<T1,cm1>&
>(from),
reinterpret_cast<color_base<T2,cm2>&
>(to));
403 convert_alpha_model(const_alpha_reference<T1,am1>(from),alpha_reference<T2,am2>(to));
409template <
typename T, ColorModel cm, AlphaModel am>
420template <
typename T, AlphaModel am>
424 T&
R() {
return this->at(0); }
426 const T&
R()
const {
return this->at(0); }
428 T&
G() {
return this->at(1); }
430 const T&
G()
const {
return this->at(1); }
432 T&
B() {
return this->at(2); }
434 const T&
B()
const {
return this->at(2); }
440template <
typename T, ColorModel cm, AlphaModel am>
451template <
typename T, AlphaModel am>
455 T&
H() {
return this->at(0); }
457 const T&
H()
const {
return this->at(0); }
459 T&
L() {
return this->at(1); }
461 const T&
L()
const {
return this->at(1); }
463 T&
S() {
return this->at(2); }
465 const T&
S()
const {
return this->at(2); }
471template <
typename T, ColorModel cm, AlphaModel am>
482template <
typename T, AlphaModel am>
486 T&
X() {
return this->at(0); }
488 const T&
X()
const {
return this->at(0); }
490 T&
Y() {
return this->at(1); }
492 const T&
Y()
const {
return this->at(1); }
494 T&
Z() {
return this->at(2); }
496 const T&
Z()
const {
return this->at(2); }
502template <
typename T, ColorModel cm, AlphaModel am>
510 return opa_ref.alpha_ref;
514template <
typename T, ColorModel cm>
520 const T&
opacity()
const {
return this->alpha(); }
526template <
typename T, ColorModel cm, AlphaModel am>
534 return tra_ref.alpha_ref;
538template <
typename T, ColorModel cm>
550template <
typename T, ColorModel cm, AlphaModel am>
558 return ext_ref.alpha_ref;
562template <
typename T, ColorModel cm>
572template <
typename T, ColorModel cm, AlphaModel am>
594 this->components[0] = c0;
596 this->components[1] = c1;
599 color(
const T& c0,
const T& c1,
const T& c2) {
600 this->components[0] = c0;
602 this->components[1] = c1;
604 this->components[2] = c2;
607 color(
const T& c0,
const T& c1,
const T& c2,
const T& c3) {
608 this->components[0] = c0;
610 this->components[1] = c1;
612 this->components[2] = c2;
614 this->components[3] = c3;
618 this->
at(nr_components - 1) = a;
623 template <
typename T2, ColorModel cm2, AlphaModel am2>
625 convert_color(c2, *
this);
628 template <
typename T2, ColorModel cm2, AlphaModel am2>
630 convert_color(c2, *
this);
635 std::fill(this->components, this->components+
nr_components, c);
642 template <
typename T2, ColorModel cm2, AlphaModel am2>
646 this->
at(i) *= tmp[i];
650 template <
typename T2, ColorModel cm2, AlphaModel am2>
663 template <
typename T2>
667 res[i] = this->
at(i)*c;
671 template <
typename T2, ColorModel cm2, AlphaModel am2>
675 this->
at(i) += tmp[i];
679 template <
typename T2, ColorModel cm2, AlphaModel am2>
698 template <
typename T2, ColorModel cm2, AlphaModel am2>
702 this->
at(i) -= tmp[i];
706 template <
typename T2, ColorModel cm2, AlphaModel am2>
727 for (
unsigned i = 0; i < nr; ++i)
728 if (this->
at(i) < mn)
730 else if (this->
at(i) > mx)
740#define CGV_MEDIA_COLOR_DECLARED
749template <
typename T, ColorModel cm, AlphaModel am>
750bool operator == (
const color<T,cm,am>& c1,
const color<T,cm,am>& c2) {
751 for (
unsigned int i=0; i<color<T,cm,am>::nr_components; ++i)
757template <
typename T1, ColorModel cm1, AlphaModel am1,
typename T2, ColorModel cm2, AlphaModel am2>
758color<typename type::func::promote<T1,T2>::type,cm1,am1> operator * (
const color<T1,cm1,am1>& c1,
const color<T2,cm2,am2>& c2) {
759 color<typename type::func::promote<T1,T2>::type,cm1,am1> res(c1);
764template <
typename T1,
typename T2, ColorModel cm2, AlphaModel am2>
765color<typename type::func::promote<T1,T2>::type,cm2,am2> operator * (
const T1& c1,
const color<T2,cm2,am2>& c2) {
766 color<typename type::func::promote<T1,T2>::type,cm2,am2> res(c2);
771template <
typename T1, ColorModel cm1, AlphaModel am1,
typename T2, ColorModel cm2, AlphaModel am2>
772color<typename type::func::promote<T1,T2>::type,cm1,am1> operator + (
const color<T1,cm1,am1>& c1,
const color<T2,cm2,am2>& c2) {
773 color<typename type::func::promote<T1,T2>::type,cm1,am1> res(c1);
778template <
typename T1, ColorModel cm1, AlphaModel am1>
779std::ostream& operator << (std::ostream& os,
const color<T1,cm1,am1>& c) {
781 for (
unsigned int i=1; i<color<T1,cm1,am1>::nr_components; ++i)
786template <
typename T1, ColorModel cm1, AlphaModel am1>
787std::istream& operator >> (std::istream& is, color<T1,cm1,am1>& c) {
789 for (
unsigned int i=1; i<color<T1,cm1,am1>::nr_components; ++i)
794template <ColorModel cm, AlphaModel am>
795std::ostream& operator << (std::ostream& os,
const color<unsigned char,cm,am>& c) {
797 for (
unsigned int i=1; i<color<unsigned char,cm,am>::nr_components; ++i)
798 os <<
" " << (
int)c[i];
802template <ColorModel cm, AlphaModel am>
803std::istream& operator >> (std::istream& is, color<unsigned char,cm,am>& c) {
806 c[0] = (
unsigned char)tmp;
807 for (
unsigned int i=1; i<color<unsigned char,cm,am>::nr_components; ++i) {
809 c[i] = (
unsigned char)tmp;
821template <
typename T, ColorModel cm, AlphaModel am>
822const color<T,cm,am> lerp(
const color<T,cm,am>& c1,
const color<T,cm,am>& c2, T t) {
823 return ((T)1 - t) * c1 + t * c2;
828template <
typename T1,
typename T2, AlphaModel am,
829 typename std::enable_if<std::is_integral<T1>::value,
bool>::type =
true,
830 typename std::enable_if<std::is_floating_point<T2>::value,
bool>::type =
true>
831const color<T1,RGB,am> pow(
const color<T1,RGB,am>& c, T2 e) {
832 constexpr T2 m =
static_cast<T2
>(std::numeric_limits<T1>::max());
833 color<T1,RGB,am> x = c;
834 for(
unsigned int i=0; i<color<T1,RGB,am>::nr_color_components; ++i)
835 x[i] =
static_cast<T1
>(std::pow(
static_cast<T2
>(c[i]) / m, e) * m);
839template<typename T, AlphaModel am, typename std::enable_if<std::is_floating_point<T>::value,
bool>::type =
true>
840const color<T,RGB,am> pow(
const color<T,RGB,am>& c, T e) {
841 color<T,RGB,am> x = c;
842 for(
unsigned int i=0; i<color<T,RGB,am>::nr_color_components; ++i)
843 x[i] = std::pow(x[i], e);
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
the max traits defines for each type in the static const member value, what the maximum value is.