4 #include <cgv/defines/assert.h>
5 #include <cgv/type/func/promote.h>
6 #include <cgv/type/traits/max.h>
7 #include <cgv/type/info/type_name.h>
8 #include "color_model.hh"
17 static T value() {
return type::traits::max<T>::value; }
20 struct color_one<float>
22 static float value() {
return 1.0f; }
25 struct color_one<double>
27 static double value() {
return 1.0; }
30 template <ColorModel cm>
31 struct color_model_traits {
32 static const unsigned int nr_components = 3;
36 struct color_model_traits<LUM> {
37 static const unsigned int nr_components = 1;
40 template <AlphaModel am>
41 struct alpha_model_traits {
42 static const unsigned int nr_components = 1;
46 struct alpha_model_traits<NO_ALPHA> {
47 static const unsigned int nr_components = 0;
50 template <
typename T, ColorModel cm = RGB, AlphaModel = NO_ALPHA>
54 template <
typename T, AlphaModel = NO_ALPHA>
61 template <
typename T1,
typename T2>
62 inline void convert_color_component(
const T1& from, T2& to) {
63 to = (T2)((
typename type::func::promote<T1,T2>::type)(from)*color_one<T2>::value()/color_one<T1>::value());
68 inline void convert_color_component(
const unsigned int& from,
unsigned short& to) {
73 inline void convert_color_component(
const unsigned int& from,
unsigned char& to) {
78 inline void convert_color_component(
const unsigned short& from,
unsigned char& to) {
83 inline void convert_color_component(
const unsigned short& from,
unsigned int& to) {
84 to = (
unsigned int) from << 16;
88 inline void convert_color_component(
const unsigned char& from,
unsigned int& to) {
89 to = (
unsigned int)from << 24;
93 inline void convert_color_component(
const unsigned char& from,
unsigned short& to) {
94 to = (
unsigned short)from << 8;
98 template <
typename T1, AlphaModel am1,
typename T2, AlphaModel am2>
99 inline void convert_alpha_model(
const dummy_alpha<T1,am1>& from, dummy_alpha<T2,am2>& to)
101 dummy_alpha<typename type::func::promote<T1,T2>::type,OPACITY> tmp;
102 convert_alpha_model(from,tmp);
103 convert_alpha_model(tmp,to);
106 template <AlphaModel am1, AlphaModel am2,
typename T>
107 inline T convert_alpha(
const T& from)
109 dummy_alpha<T,am1> to;
110 convert_alpha_model((
const dummy_alpha<T,am2>&) from, to);
114 template <
typename T1, ColorModel cm1,
typename T2, ColorModel cm2>
115 inline void convert_color_model(
const color<T1,cm1>& from, color<T2,cm2>& to)
117 color<typename type::func::promote<T1,T2>::type,XYZ> tmp;
118 convert_color(from,tmp);
119 convert_color(tmp,to);
123 template <
typename T1, ColorModel cm1, AlphaModel am1,
typename T2, ColorModel cm2, AlphaModel am2>
124 inline void convert_color(
const color<T1,cm1,am1>& from, color<T2,cm2,am2>& to)
126 convert_color_model(*((
const color<T1,cm1>*)&from),(color<T2,cm2>&)to);
127 convert_alpha_model(*((
const dummy_alpha<T1,am1>*)&from.alpha()),(dummy_alpha<T2,am2>&)(to.alpha()));
134 template <
typename T, ColorModel cm, AlphaModel am>
146 template <
typename T, AlphaModel am>
167 template <
typename T, ColorModel cm, AlphaModel am>
179 template <
typename T, AlphaModel am>
200 template <
typename T, ColorModel cm, AlphaModel am>
212 template <
typename T, AlphaModel am>
234 template <
typename T, ColorModel cm, AlphaModel am>
246 template <
typename T, ColorModel cm>
259 template <
typename T, ColorModel cm, AlphaModel am>
271 template <
typename T, ColorModel cm>
284 template <
typename T, ColorModel cm, AlphaModel am>
296 template <
typename T, ColorModel cm>
307 template <
typename T, ColorModel cm, AlphaModel am>
308 class color :
public extinction_alpha_interface<color<T,cm,am> >
334 color(
const T& c0,
const T& c1,
const T& c2) {
342 color(
const T& c0,
const T& c1,
const T& c2,
const T& c3) {
352 template <
typename T2, ColorModel cm2, AlphaModel am2>
354 convert_color(c2, *
this);
357 template <
typename T2, ColorModel cm2, AlphaModel am2>
359 convert_color(c2, *
this);
371 template <
typename T2, ColorModel cm2, AlphaModel am2>
375 components[i] *= tmp[i];
379 template <
typename T2, ColorModel cm2, AlphaModel am2>
392 template <
typename T2>
396 res[i] = components[i]*c;
400 template <
typename T2, ColorModel cm2, AlphaModel am2>
404 components[i] += tmp[i];
408 template <
typename T2, ColorModel cm2, AlphaModel am2>
427 void clamp(
const T& mn = 0,
const T& mx = color_one<T>::value(),
bool skip_alpha =
false) {
431 for (
int i=nr-1; i>=0; --i)
432 if (components[i] < mn)
434 else if (components[i] > mx)
440 const T&
operator [] (
unsigned int i)
const {
return components[i]; }
457 template <
typename T, ColorModel cm, AlphaModel am>
458 bool operator == (
const color<T,cm,am>& c1,
const color<T,cm,am>& c2) {
459 for (
unsigned int i=0; i<color<T,cm,am>::nr_components; ++i)
466 template <
typename T1, ColorModel cm1, AlphaModel am1,
typename T2, ColorModel cm2, AlphaModel am2>
467 color<typename type::func::promote<T1,T2>::type,cm1,am1> operator * (
const color<T1,cm1,am1>& c1,
const color<T2,cm2,am2>& c2) {
468 color<typename type::func::promote<T1,T2>::type,cm1,am1> res(c1);
474 template <
typename T1,
typename T2, ColorModel cm2, AlphaModel am2>
475 color<typename type::func::promote<T1,T2>::type,cm2,am2> operator * (
const T1& c1,
const color<T2,cm2,am2>& c2) {
476 color<typename type::func::promote<T1,T2>::type,cm2,am2> res(c2);
482 template <
typename T1, ColorModel cm1, AlphaModel am1,
typename T2, ColorModel cm2, AlphaModel am2>
483 color<typename type::func::promote<T1,T2>::type,cm1,am1> operator + (
const color<T1,cm1,am1>& c1,
const color<T2,cm2,am2>& c2) {
484 color<typename type::func::promote<T1,T2>::type,cm1,am1> res(c1);
490 template <
typename T1, ColorModel cm1, AlphaModel am1>
491 std::ostream& operator << (std::ostream& os,
const color<T1,cm1,am1>& c) {
493 for (
unsigned int i=1; i<color<T1,cm1,am1>::nr_components; ++i)
498 template <
typename T1, ColorModel cm1, AlphaModel am1>
499 std::istream& operator >> (std::istream& is, color<T1,cm1,am1>& c) {
501 for (
unsigned int i=1; i<color<T1,cm1,am1>::nr_components; ++i)
507 template <ColorModel cm, AlphaModel am>
508 std::ostream& operator << (std::ostream& os,
const color<unsigned char,cm,am>& c) {
510 for (
unsigned int i=1; i<color<unsigned char,cm,am>::nr_components; ++i)
511 os <<
" " << (
int)c[i];
515 template <ColorModel cm, AlphaModel am>
516 std::istream& operator >> (std::istream& is, color<unsigned char,cm,am>& c) {
519 c[0] = (
unsigned char)tmp;
520 for (
unsigned int i=1; i<color<unsigned char,cm,am>::nr_components; ++i) {
522 c[i] = (
unsigned char)tmp;
536 template <
typename T1,
typename T2>
537 void convert_alpha_model(
const dummy_alpha<T1,NO_ALPHA>& from, dummy_alpha<T2,OPACITY>& to)
539 to.alpha = color_one<T2>::value();
542 template <
typename T1,
typename T2>
543 void convert_alpha_model(
const dummy_alpha<T1,NO_ALPHA>& from, dummy_alpha<T2,TRANSPARENCY>& to)
548 template <
typename T1,
typename T2>
549 void convert_alpha_model(
const dummy_alpha<T1,NO_ALPHA>& from, dummy_alpha<T2,EXTINCTION>& to)
551 to.alpha = color_one<T2>::value();
554 template <
typename T1,
typename T2>
555 void convert_alpha_model(
const dummy_alpha<T1,OPACITY>& from, dummy_alpha<T2,TRANSPARENCY>& to)
557 convert_color_component(from.alpha,to.alpha);
558 to.alpha = color_one<T2>::value()-to.alpha;
561 template <
typename T1,
typename T2>
562 void convert_alpha_model(
const dummy_alpha<T1,TRANSPARENCY>& from, dummy_alpha<T2,OPACITY>& to)
564 convert_color_component(from.alpha,to.alpha);
565 to.alpha = color_one<T2>::value()-to.alpha;
568 template <
typename T1,
typename T2>
569 void convert_alpha_model(
const dummy_alpha<T1,OPACITY>& from, dummy_alpha<T2,EXTINCTION>& to)
572 convert_color_component(from.alpha,tmp);
574 convert_color_component(tmp, to.alpha);
577 template <
typename T1,
typename T2>
578 void convert_alpha_model(
const dummy_alpha<T1,EXTINCTION>& from, dummy_alpha<T2,OPACITY>& to)
581 convert_color_component(from.alpha,tmp);
583 convert_color_component(tmp, to.alpha);
587 template <
typename T1, AlphaModel am1,
typename T2>
588 void convert_alpha_model(
const dummy_alpha<T1,am1>& from, dummy_alpha<T2,NO_ALPHA>& to)
592 template <
typename T1,
typename T2>
593 void convert_alpha_model(
const dummy_alpha<T1,NO_ALPHA>& from, dummy_alpha<T2,NO_ALPHA>& to)
597 template <
typename T1, AlphaModel am,
typename T2>
598 void convert_alpha_model(
const dummy_alpha<T1,am>& from, dummy_alpha<T2,am>& to)
600 convert_color_component(from.alpha, to.alpha);
611 template <
typename T1, ColorModel cm,
typename T2>
612 void convert_color_model(
const color<T1,cm>& from, color<T2,cm>& to)
614 for (
unsigned int i=0; i<color<T1,cm>::nr_components; ++i)
615 convert_color_component(from[i], to[i]);
619 template <
typename T1,
typename T2>
620 void convert_color_model(
const color<T1,XYZ>& from, color<T2,XYZ>& to)
622 for (
unsigned int i=0; i<color<T1,XYZ>::nr_components; ++i)
623 convert_color_component(from[i], to[i]);
627 template <
typename T1, ColorModel cm1,
typename T2>
628 void convert_color_model(
const color<T1,cm1>& from, color<T2,XYZ>& to)
630 std::cerr <<
"conversion not implemented" << std::endl;
633 template <
typename T1, ColorModel cm2,
typename T2>
634 void convert_color_model(
const color<T1,XYZ>& from, color<T2,cm2>& to)
636 std::cerr <<
"conversion not implemented" << std::endl;
640 template <
typename T1,
typename T2>
641 void convert_color_model(
const color<T1,LUM>& c1, color<T2,XYZ>& c2) {
644 convert_color_component(c1[0],c2[1]);
647 template <
typename T1,
typename T2>
648 void convert_color_model(
const color<T1,XYZ>& c1, color<T2,LUM>& c2) {
649 convert_color_component(c1[1],c2[0]);
652 template <
typename T1,
typename T2>
653 void convert_color_model(
const color<T1,RGB>& _c1, color<T2,XYZ>& c2) {
654 color<double,RGB> c1(_c1);
655 convert_color_component(0.412453*c1[0]+0.357580*c1[1]+0.180423*c1[2], c2[0]);
656 convert_color_component(0.212671*c1[0]+0.715160*c1[1]+0.072169*c1[2], c2[1]);
657 convert_color_component(0.019334*c1[0]+0.119193*c1[1]+0.950227*c1[2], c2[2]);
660 template <
typename T1,
typename T2>
661 void convert_color_model(
const color<T1,XYZ>& _c1, color<T2,RGB>& c2) {
662 color<double,XYZ> c1(_c1);
663 convert_color_component(3.2404813432*c1[0]-1.5371515163*c1[1]-0.4985363262*c1[2], c2[0]);
664 convert_color_component(-0.9692549500*c1[0]+1.8759900015*c1[1]+0.0415559266*c1[2], c2[1]);
665 convert_color_component(0.0556466391*c1[0]-0.2040413384*c1[1]+1.0573110696*c1[2], c2[2]);
669 template <
typename T1,
typename T2>
670 void convert_color_model(
const color<T1,RGB>& rgb, color<T2,HLS>& hls) {
672 convert_color_component(std::max(rgb[0], std::max(rgb[1],rgb[2])), mx);
673 convert_color_component(std::min(rgb[0], std::min(rgb[1],rgb[2])), mn);
674 double LL = (mx+mn)/2;
677 convert_color_component(LL,hls[1]);
682 double SS = (LL <= 0.5) ? DM/SM : DM/(2-SM);
683 color<double,RGB> c(rgb);
685 if (c[0] == mx) HH = (c[1]-c[2])/DM;
686 else if (c[1] == mx) HH = 2+(c[2]-c[0])/DM;
687 else HH = 4+(c[0]-c[1])/DM;
690 convert_color_component(HH,hls[0]);
691 convert_color_component(LL,hls[1]);
692 convert_color_component(SS,hls[2]);
696 template <
typename T1,
typename T2>
697 void convert_color_model(
const color<T1,HLS>& hls, color<T2,RGB>& rgb) {
699 convert_color_component(hls[0],HH); HH *= 6;
700 convert_color_component(hls[1],LL);
701 convert_color_component(hls[2],SS);
704 while (I >= 6) I -= 6;
705 double mx = (LL <= 0.5) ? LL*(1+SS) : LL+SS-LL*SS;
706 double mn = 2*LL - mx;
710 convert_color_component(LL,tmp);
716 convert_color_component(mx, rgb[0]);
717 convert_color_component(mn+F*DM,rgb[1]);
718 convert_color_component(mn, rgb[2]);
721 convert_color_component(mn+(1-F)*DM, rgb[0]);
722 convert_color_component(mx, rgb[1]);
723 convert_color_component(mn, rgb[2]);
726 convert_color_component(mn, rgb[0]);
727 convert_color_component(mx, rgb[1]);
728 convert_color_component(mn+F*DM, rgb[2]);
731 convert_color_component(mn, rgb[0]);
732 convert_color_component(mn+(1-F)*DM, rgb[1]);
733 convert_color_component(mx, rgb[2]);
736 convert_color_component(mn+F*DM, rgb[0]);
737 convert_color_component(mn, rgb[1]);
738 convert_color_component(mx, rgb[2]);
741 convert_color_component(mx, rgb[0]);
742 convert_color_component(mn, rgb[1]);
743 convert_color_component(mn+(1-F)*DM, rgb[2]);
750 template <
typename T1,
typename T2>
751 void convert_color_model(
const color<T1,HLS>& c1, color<T2,XYZ>& c2) {
752 color<typename type::func::promote<T1,T2>::type,RGB> tmp;
753 convert_color(c1,tmp);
754 convert_color(tmp,c2);
757 template <
typename T1,
typename T2>
758 void convert_color_model(
const color<T1,XYZ>& c1, color<T2,HLS>& c2) {
759 color<typename type::func::promote<T1,T2>::type,RGB> tmp;
760 convert_color(c1,tmp);
761 convert_color(tmp,c2);