$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
value/rgb.hh
1 // Copyright (C) 2007, 2008, 2009, 2010, 2012, 2013 EPITA Research and
2 // Development Laboratory (LRDE)
3 //
4 // This file is part of Olena.
5 //
6 // Olena is free software: you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free
8 // Software Foundation, version 2 of the License.
9 //
10 // Olena is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // As a special exception, you may use this file as part of a free
19 // software project without restriction. Specifically, if other files
20 // instantiate templates or use macros or inline functions from this
21 // file, or you compile this file and link it with other files to produce
22 // an executable, this file does not by itself cause the resulting
23 // executable to be covered by the GNU General Public License. This
24 // exception does not however invalidate any other reasons why the
25 // executable file might be covered by the GNU General Public License.
26 
27 #ifndef MLN_VALUE_RGB_HH
28 # define MLN_VALUE_RGB_HH
29 
30 
31 # include <mln/value/ops.hh>
32 
33 # include <mln/value/concept/vectorial.hh>
34 # include <mln/value/int_u.hh>
35 # include <mln/algebra/vec.hh>
36 
37 # include <mln/value/internal/make_generic_name.hh>
38 
39 # include <mln/convert/from_to.hh>
40 
41 // FIXME: should we consider that mln_min may be negative? => wrong
42 // color formulae.
43 
44 namespace mln
45 {
46 
47  // Forward declaration.
48  namespace value {
49  template <unsigned n> struct rgb;
50  template <typename H, typename S, typename L> class hsl_;
51 
52  }
53  namespace fun {
54  namespace v2v {
55  template <typename T_hsl> struct f_rgb_to_hsl_;
56  typedef f_rgb_to_hsl_<value::hsl_<float, float, float> > f_rgb_to_hsl_f_t;
58  }
59  }
60 
61 
62  namespace literal
63  {
64  // Forward declarations.
65  struct black_t;
66  struct white_t;
67 
68  struct light_gray_t;
69  struct medium_gray_t;
70  struct dark_gray_t;
71 
72  struct red_t;
73  struct green_t;
74  struct blue_t;
75  struct brown_t;
76  struct lime_t;
77  struct orange_t;
78  struct pink_t;
79  struct purple_t;
80  struct teal_t;
81  struct violet_t;
82  struct cyan_t;
83  struct magenta_t;
84  struct yellow_t;
85  struct olive_t;
86  //
87  }
88 
89 
90  // Forward declaration.
91  namespace value
92  {
93  template <typename H, typename S, typename L> class hsl_;
94  }
95 
96  namespace trait
97  {
98  template < unsigned n >
99  struct set_precise_binary_< op::plus, mln::value::rgb<n>, mln::value::rgb<n> >
100  {
101  typedef mln::value::rgb<n> ret;
102  };
103 
104  template < unsigned n >
105  struct set_precise_binary_< op::minus, mln::value::rgb<n>, mln::value::rgb<n> >
106  {
107  typedef mln::value::rgb<n> ret;
108  };
109 
110  template < unsigned n, typename S >
111  struct set_precise_binary_< op::times, mln::value::rgb<n>, mln::value::scalar_<S> >
112  {
113  typedef mln::value::rgb<n> ret;
114  };
115 
116  template < unsigned n, typename S >
117  struct set_precise_binary_< op::div, mln::value::rgb<n>, mln::value::scalar_<S> >
118  {
119  typedef mln::value::rgb<n> ret;
120  };
121 
122 
123  // FIXME : Is there any way more generic? a way to factor
124  // set_precise_binary_< op::div, mln::value::rgb<n>, mln::value::scalar_<S> >
125  // and
126  // set_precise_binary_< op::div, mln::value::rgb<n>, mln::value::int_u<m> >
127  // as for op::times.
128 
129  template < unsigned n, unsigned m >
130  struct set_precise_binary_< op::times, mln::value::rgb<n>, mln::value::int_u<m> >
131  {
132  typedef mln::value::rgb<n> ret;
133  };
134 
135  template < unsigned n, unsigned m >
136  struct set_precise_binary_< op::div, mln::value::rgb<n>, mln::value::int_u<m> >
137  {
138  typedef mln::value::rgb<n> ret;
139  };
140 
141 
142 // template < unsigned n, typename I >
143 // struct set_binary_< op::times,
144 // mln::value::Vectorial, mln::value::rgb<n>,
145 // mln::value::Integer, I >
146 // {
147 // typedef mln::value::rgb<n> ret;
148 // };
149 
150 // template < unsigned n, typename S >
151 // struct set_binary_< op::times,
152 // mln::value::Scalar, S,
153 // mln::value::Vectorial, mln::value::rgb<n> >
154 // {
155 // typedef mln::value::rgb<n> ret;
156 // };
157 
158  template <unsigned n>
159  struct value_< mln::value::rgb<n> >
160  {
161  enum {
162  dim = 3,
163  nbits = dim * n,
164  card = mln_value_card_from_(nbits)
165  };
166 
167  typedef trait::value::nature::vectorial nature;
168  typedef trait::value::kind::color kind;
169  typedef trait::value::quant::high /*mln_value_quant_from_(card)*/ quant;
170 
171  typedef void comp;
172  typedef mln::value::int_u<n> comp_0;
173  typedef mln::value::int_u<n> comp_1;
174  typedef mln::value::int_u<n> comp_2;
175 
176  template <typename V> static comp_0 get_comp_0(const V& v) { return v.red(); }
177  template <typename V> static comp_1 get_comp_1(const V& v) { return v.green(); }
178  template <typename V> static comp_2 get_comp_2(const V& v) { return v.blue(); }
179 
180  typedef algebra::vec<dim, float> sum;
181 
182  static const char* name()
183  {
184  static std::string
186  return s.c_str();
187  }
188 
189  };
190 
191  } // end of namespace trait
192 
193 
194 
195  namespace value
196  {
197 
204  template <unsigned n>
205  struct rgb
206  :
207  public Vectorial< rgb<n> >
208  ,
209  public internal::value_like_< algebra::vec< 3, int_u<n> >, // Equivalent.
210  algebra::vec< 3, int_u<n> >, // Encoding.
211  algebra::vec< 3, int >, // Interoperation.
212  rgb<n> > // Exact.
213  {
214  public:
215 
216  typedef int_u<n> red_t;
217  typedef int_u<n> green_t;
218  typedef int_u<n> blue_t;
219 
222  int_u<n> red() const { return this->v_[0]; }
223  int_u<n>& red() { return this->v_[0]; }
224 
225  int_u<n> green() const { return this->v_[1]; }
226  int_u<n>& green() { return this->v_[1]; }
227 
228  int_u<n> blue() const { return this->v_[2]; }
229  int_u<n>& blue() { return this->v_[2]; }
230 
231  int_u<n> comp(unsigned k) const { return this->v_[k]; }
232  int_u<n>& comp(unsigned k) { return this->v_[k]; }
234 
236  rgb<n>();
237 
239  rgb<n>(int r, int g, int b);
240 
246 
247  // Conversion to the interoperation type.
248  operator algebra::vec<3, int>() const { return this->v_; }
249  // Conversion to the sum type.
250  operator algebra::vec<3, float>() const { return this->v_; }
251 
256 
260 
261  rgb<n>(const mln::literal::red_t&);
276 
278  rgb<n>& operator=(const rgb<n>& rhs);
279 
281  static const rgb<n> zero;
282  };
283 
284 
285 
292  template <unsigned n>
293  std::ostream& operator<<(std::ostream& ostr, const rgb<n>& c);
294 
301  template <unsigned n>
302  std::istream& operator>>(std::istream& istr, rgb<n>& c);
303 
304 
305  /* FIXME: We should not need to define these operators, thanks to
306  Milena's global operator resolution mechanism based on
307  mln::Object. See what prevent us to use this mechanism. */
308 
309  /* FIXME: Cannot work for i negative; add traits! (2008-02-16,
310  Roland: What does this comment mean?) */
311 
314  template <unsigned n>
315  typename rgb<n>::interop
316  operator+(const rgb<n>& lhs, const rgb<n>& rhs);
317 
318  template <unsigned n>
319  typename rgb<n>::interop
320  operator+(const typename rgb<n>::interop& lhs, const rgb<n>& rhs);
321 
322  template <unsigned n>
323  typename rgb<n>::interop
324  operator+(const rgb<n>& lhs, const typename rgb<n>::interop& rhs);
326 
329  template <unsigned n>
330  typename rgb<n>::interop
331  operator-(const rgb<n>& lhs, const rgb<n>& rhs);
332 
333  template <unsigned n>
334  typename rgb<n>::interop
335  operator-(const typename rgb<n>::interop& lhs, const rgb<n>& rhs);
336 
337  template <unsigned n>
338  typename rgb<n>::interop
339  operator-(const rgb<n>& lhs, const typename rgb<n>::interop& rhs);
341 
344  template <unsigned n, typename S>
345  inline
346  typename rgb<n>::interop
347  operator*(const rgb<n>& lhs, const mln::value::scalar_<S>& s);
348 
349  template <unsigned n, typename S>
350  inline
351  typename rgb<n>::interop
352  operator*(const mln::value::scalar_<S>& s, const rgb<n>& lhs);
354 
357  template <unsigned n, typename S>
358  inline
359  typename rgb<n>::interop
360  operator/(const rgb<n>& lhs, const mln::value::scalar_<S>& s);
362 
363  } // end of namespace mln::value
364 
365 
366  // Conversions
367 
368  namespace value
369  {
370 
372  template <unsigned m>
373  void from_to_(const value::rgb<m>& from, bool& to);
374 
376  void
377  from_to_(const rgb<16>& from, hsl_<float,float,float>& to);
378 
380  void
381  from_to_(const rgb<8>& from, hsl_<float,float,float>& to);
382 
384  template <unsigned m>
385  void from_to_(bool from, value::rgb<m>& to);
386 
387  } // end of namespace mln::value
388 
389 } // end of namespace mln
390 
391 
392 // Used in from_to
393 # include <mln/value/hsl.hh>
394 # include <mln/fun/v2v/rgb_to_hsl.hh>
395 
396 
397 # ifndef MLN_INCLUDE_ONLY
398 
399 namespace mln
400 {
401 
402  namespace value
403  {
404 
405  /*---------------.
406  | Construction. |
407  `---------------*/
408 
409  template <unsigned n>
410  inline
411  rgb<n>::rgb()
412  {
413  }
414 
415  template <unsigned n>
416  inline
417  rgb<n>::rgb(const algebra::vec<3, int>& v)
418  {
419  this->v_ = v;
420  }
421 
422  template <unsigned n>
423  inline
424  rgb<n>::rgb(const algebra::vec<3, unsigned>& v)
425  {
426  this->v_ = v;
427  }
428 
429  template <unsigned n>
430  inline
431  rgb<n>::rgb(const algebra::vec<3, int_u<n> >& v)
432  {
433  this->v_ = v;
434  }
435 
436  template <unsigned n>
437  inline
438  rgb<n>::rgb(const algebra::vec<3, float>& v)
439  {
440  convert::from_to(v[0], this->v_[0]);
441  convert::from_to(v[1], this->v_[1]);
442  convert::from_to(v[2], this->v_[2]);
443  }
444 
445  template <unsigned n>
446  inline
447  rgb<n>::rgb(int r, int g, int b)
448  {
449  mln_precondition(r >= 0);
450  mln_precondition(g >= 0);
451  mln_precondition(b >= 0);
452  mln_precondition(unsigned(r) <= mln_max(int_u<n>));
453  mln_precondition(unsigned(g) <= mln_max(int_u<n>));
454  mln_precondition(unsigned(b) <= mln_max(int_u<n>));
455  this->v_[0] = r;
456  this->v_[1] = g;
457  this->v_[2] = b;
458  }
459 
460  template <unsigned n>
461  inline
463  {
464  this->v_[0] = mln_max(int_u<n>);
465  this->v_[1] = mln_max(int_u<n>);
466  this->v_[2] = mln_max(int_u<n>);
467  }
468 
469  template <unsigned n>
470  inline
472  {
473  this->v_[0] = 0;
474  this->v_[1] = 0;
475  this->v_[2] = 0;
476  }
477 
478  template <unsigned n>
479  inline
481  {
482  convert::from_to(mln_max(int_u<n>) * 0.75, this->v_[0]);
483  convert::from_to(mln_max(int_u<n>) * 0.75, this->v_[1]);
484  convert::from_to(mln_max(int_u<n>) * 0.75, this->v_[2]);
485  }
486 
487  template <unsigned n>
488  inline
490  {
491  convert::from_to(mln_max(int_u<n>) * 0.50, this->v_[0]);
492  convert::from_to(mln_max(int_u<n>) * 0.50, this->v_[1]);
493  convert::from_to(mln_max(int_u<n>) * 0.50, this->v_[2]);
494  }
495 
496  template <unsigned n>
497  inline
499  {
500  convert::from_to(mln_max(int_u<n>) * 0.25, this->v_[0]);
501  convert::from_to(mln_max(int_u<n>) * 0.25, this->v_[1]);
502  convert::from_to(mln_max(int_u<n>) * 0.25, this->v_[2]);
503  }
504 
505  template <unsigned n>
506  inline
508  {
509  this->v_[0] = mln_max(int_u<n>);
510  this->v_[1] = 0;
511  this->v_[2] = 0;
512  }
513 
514  template <unsigned n>
515  inline
517  {
518  this->v_[0] = 0;
519  this->v_[1] = mln_max(int_u<n>);
520  this->v_[2] = 0;
521  }
522 
523  template <unsigned n>
524  inline
526  {
527  this->v_[0] = 0;
528  this->v_[1] = 0;
529  this->v_[2] = mln_max(int_u<n>);
530  }
531 
532  template <unsigned n>
533  inline
535  {
536  convert::from_to(mln_max(int_u<n>) * 0.75, this->v_[0]);
537  convert::from_to(mln_max(int_u<n>) * 0.50, this->v_[1]);
538  convert::from_to(mln_max(int_u<n>) * 0.25, this->v_[2]);
539  }
540 
541  template <unsigned n>
542  inline
544  {
545  convert::from_to(mln_max(int_u<n>) * 0.75, this->v_[0]);
546  this->v_[1] = mln_max(int_u<n>);
547  this->v_[2] = 0;
548  }
549 
550  template <unsigned n>
551  inline
553  {
554  this->v_[0] = mln_max(int_u<n>);
555  convert::from_to(mln_max(int_u<n>) * 0.50, this->v_[1]);
556  this->v_[2] = 0;
557  }
558 
559  template <unsigned n>
560  inline
562  {
563  this->v_[0] = mln_max(int_u<n>);
564  convert::from_to(mln_max(int_u<n>) * 0.75, this->v_[1]);
565  convert::from_to(mln_max(int_u<n>) * 0.75, this->v_[2]);
566  }
567 
568  template <unsigned n>
569  inline
571  {
572  convert::from_to(mln_max(int_u<n>) * 0.75, this->v_[0]);
573  this->v_[1] = 0;
574  convert::from_to(mln_max(int_u<n>) * 0.25, this->v_[2]);
575  }
576 
577  template <unsigned n>
578  inline
580  {
581  this->v_[0] = 0;
582  convert::from_to(mln_max(int_u<n>) * 0.50, this->v_[1]);
583  convert::from_to(mln_max(int_u<n>) * 0.50, this->v_[2]);
584  }
585 
586  template <unsigned n>
587  inline
589  {
590  convert::from_to(mln_max(int_u<n>) * 0.50, this->v_[0]);
591  this->v_[1] = 0;
592  convert::from_to(mln_max(int_u<n>) * 0.50, this->v_[2]);
593  }
594 
595  template <unsigned n>
596  inline
598  {
599  this->v_[0] = 0;
600  this->v_[1] = mln_max(int_u<n>);
601  this->v_[2] = mln_max(int_u<n>);
602  }
603 
604  template <unsigned n>
605  inline
607  {
608  this->v_[0] = mln_max(int_u<n>);
609  this->v_[1] = 0;
610  this->v_[2] = mln_max(int_u<n>);
611  }
612 
613  template <unsigned n>
614  inline
616  {
617  this->v_[0] = mln_max(int_u<n>);
618  this->v_[1] = mln_max(int_u<n>);
619  this->v_[2] = 0;
620  }
621 
622  template <unsigned n>
623  inline
625  {
626  convert::from_to(mln_max(int_u<n>) * 0.50, this->v_[0]);
627  convert::from_to(mln_max(int_u<n>) * 0.50, this->v_[1]);
628  this->v_[2] = 0;
629  }
630 
631  template <unsigned n>
632  inline
633  rgb<n>&
634  rgb<n>::operator=(const rgb<n>& rhs)
635  {
636  if (& rhs == this)
637  return *this;
638  this->v_ = rhs.v_;
639  return *this;
640  }
641 
642  template <unsigned n>
643  const rgb<n> rgb<n>::zero(0,0,0);
644 
645  /*------------.
646  | Operators. |
647  `------------*/
648 
649  template <unsigned n>
650  inline
651  typename rgb<n>::interop
652  operator+(const rgb<n>& lhs, const rgb<n>& rhs)
653  {
654  typename rgb<n>::interop tmp(lhs.to_interop() + rhs.to_interop());
655  return tmp;
656  }
657 
658  template <unsigned n>
659  inline
660  typename rgb<n>::interop
661  operator+(const rgb<n>& lhs, const typename rgb<n>::interop& rhs)
662  {
663  typename rgb<n>::interop tmp(lhs.to_interop() + rhs);
664  return tmp;
665  }
666 
667  template <unsigned n>
668  inline
669  typename rgb<n>::interop
670  operator+(const typename rgb<n>::interop& lhs, const rgb<n>& rhs)
671  {
672  typename rgb<n>::interop tmp(lhs + rhs.to_interop());
673  return tmp;
674  }
675 
676  template <unsigned n>
677  inline
678  typename rgb<n>::interop
679  operator-(const rgb<n>& lhs, const rgb<n>& rhs)
680  {
681  typename rgb<n>::interop tmp(lhs.to_interop() - rhs.to_interop());
682  return tmp;
683  }
684 
685  template <unsigned n>
686  inline
687  typename rgb<n>::interop
688  operator-(const rgb<n>& lhs, const typename rgb<n>::interop& rhs)
689  {
690  typename rgb<n>::interop tmp(lhs.to_interop() - rhs);
691  return tmp;
692  }
693 
694  template <unsigned n>
695  inline
696  typename rgb<n>::interop
697  operator-(const typename rgb<n>::interop& lhs, const rgb<n>& rhs)
698  {
699  typename rgb<n>::interop tmp(lhs - rhs.to_interop());
700  return tmp;
701  }
702 
703  template <unsigned n, typename S>
704  inline
705  typename rgb<n>::interop
706  operator*(const rgb<n>& lhs, const mln::value::scalar_<S>& s)
707  {
708  typename rgb<n>::interop tmp(lhs.to_interop() * s.to_equiv());
709  return tmp;
710  }
711 
712  template <unsigned n, typename S>
713  inline
714  typename rgb<n>::interop
715  operator*(const mln::value::scalar_<S>& s, const rgb<n>& lhs)
716  {
717  typename rgb<n>::interop tmp(s.to_equiv() * lhs.to_interop());
718  return tmp;
719  }
720 
721  template <unsigned n, typename S>
722  inline
723  typename rgb<n>::interop
724  operator/(const rgb<n>& lhs, const mln::value::scalar_<S>& s)
725  {
726  typename rgb<n>::interop tmp(lhs.to_interop() / s.to_equiv());
727  return tmp;
728  }
729 
730  template <unsigned n>
731  inline
732  std::ostream& operator<<(std::ostream& ostr, const rgb<n>& v)
733  {
734  return ostr << '(' << debug::format(v.red())
735  << ',' << debug::format(v.green())
736  << ',' << debug::format(v.blue())
737  << ')';
738  }
739 
740  template <unsigned n>
741  inline
742  std::istream& operator>>(std::istream& istr, rgb<n>& c)
743  {
744  return istr >> c.red() >> c.green() >> c.blue();
745  }
746 
747 
748  // Conversions
749 
750  template <unsigned m>
751  void
752  from_to_(const rgb<m>& from, bool& to)
753  {
754  to = (from.red() != 0 && from.green() != 0 && from.blue() != 0);
755  }
756 
757  inline
758  void
759  from_to_(const rgb<16>& from, hsl_<float,float,float>& to)
760  {
761  to = fun::v2v::f_rgb_to_hsl_f(from);
762  }
763 
764  inline
765  void
766  from_to_(const rgb<8>& from, hsl_<float,float,float>& to)
767  {
768  to = fun::v2v::f_rgb_to_hsl_f(from);
769  }
770 
771  template <unsigned m>
772  void
773  from_to_(bool from, mln::value::rgb<m>& to)
774  {
775  static mln::literal::white_t* white_ = 0;
776  static mln::literal::black_t* black_ = 0;
777  // We do not use literal::white (the object) so that we
778  // do not introduce any coupling with the file where
779  // literals are defined.
780  if (from)
781  to = *white_;
782  else
783  to = *black_;
784  }
785 
786  } // end of namespace mln::value
787 
788 } // end of namespace mln
789 
790 # endif // ! MLN_INCLUDE_ONLY
791 
792 
793 #endif // ! MLN_VALUE_RGB_HH