$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
gray_.hh
1 // Copyright (C) 2006, 2007, 2008, 2009, 2011 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_INTERNAL_GRAY__HH
28 # define MLN_VALUE_INTERNAL_GRAY__HH
29 
33 
34 # include <iostream>
35 # include <cmath>
36 
37 # include <mln/metal/math/max.hh>
38 # include <mln/metal/math/pow.hh>
39 
40 # include <mln/value/concept/integer.hh>
41 # include <mln/value/internal/value_like.hh>
42 
43 # include <mln/value/graylevel_f.hh>
44 
45 namespace mln
46 {
47 
48  namespace literal
49  {
51  struct black_t;
52  struct white_t;
54  }
55 
56  namespace value
57  {
59  template <unsigned n>
60  struct graylevel;
61  template <unsigned N> struct graylevel;
62  struct graylevel_f;
63  namespace internal
64  {
65  template <unsigned n> class gray_;
66  struct gray_f;
67  }
69  }
70 
71 
72  namespace trait
73  {
74 
75  template < template <class, class> class Name, unsigned n, unsigned m>
76  struct set_precise_binary_< Name, mln::value::internal::gray_<n>, mln::value::internal::gray_<m> >
77  {
79  };
80 
81  template <unsigned n, unsigned m>
82  struct set_precise_binary_< op::greater, mln::value::internal::gray_<n>, mln::value::internal::gray_<m> >
83  {
84  typedef bool ret;
85  };
86 
87  template <unsigned n, unsigned m>
88  struct set_precise_binary_< op::eq, mln::value::internal::gray_<n>, mln::value::internal::gray_<m> >
89  {
90  typedef bool ret;
91  };
92 
93  // 'gray_' as a value.
94 
95  template <unsigned n>
96  struct value_< mln::value::internal::gray_<n> >
97  {
98  private:
99  typedef mln::value::internal::gray_<n> self_;
100  public:
101 
102  enum {
103  nbits = 8 * (sizeof(unsigned) + sizeof(long)),
104  card = 0
105  };
106 
107  typedef trait::value::nature::integer nature; // FIXME: Or scalar?.
108  typedef trait::value::kind::gray kind;
109  typedef trait::value::quant::high quant;
110 
111  static self_ min();
112  static self_ max();
113  static self_ epsilon();
114 
115  typedef self_ sum; // FIXME: OK?.
116  };
117 
118  } // end of namespace mln::trait
119 
120 
121 
122  namespace value
123  {
124 
125  namespace internal
126  {
127 
130  template <unsigned n>
131  class gray_
132  :
133  public Integer< gray_<n> >,
134 
135  public internal::value_like_< int, // Equivalent.
136  int, // Encoding.
137  gray_<n>, // Interoperation.
138  gray_<n> > // Exact.
139 
140  {
141  public:
142 
144  typedef int enc;
145 
147  typedef int equiv;
148 
150  gray_();
152  gray_(int val);
153 
155  explicit gray_(const literal::white_t&);
156  explicit gray_(const literal::black_t&);
158 
159 
161  template <unsigned m>
162  gray_(const graylevel<m>& val);
163  template <unsigned m>
164  gray_<n>& operator=(const graylevel<m>& val);
166 
168  int value() const;
169 
171  template <unsigned m>
172  operator gray_<m>() const;
173 
175  template <unsigned m>
176  operator graylevel<m>() const;
177 
179  operator graylevel_f() const;
180 
181  };
182 
183 
184  // Operators.
185 
186  template <unsigned n>
187  std::ostream& operator<<(std::ostream& ostr, const gray_<n>& g);
188 
189  template <unsigned n, unsigned m>
190  bool operator==(const gray_<n>& lhs, const gray_<m>& rhs);
191  template <unsigned n, unsigned m>
192  bool operator<(const gray_<n>& lhs, const gray_<m>& rhs);
193 
194  template <unsigned n, unsigned m>
195  mln_trait_op_plus(gray_<n>, gray_<m>)
196  operator+(const gray_<n>& lhs, const gray_<m>& rhs);
197 
198  template <unsigned n, unsigned m>
199  mln_trait_op_minus(gray_<n>, gray_<m>)
200  operator-(const gray_<n>& lhs, const gray_<m>& rhs);
201 
202  template <unsigned n>
203  gray_<n> operator*(int s, const gray_<n>& rhs);
204  template <unsigned n>
205  gray_<n> operator*(const gray_<n>& lhs, int s);
206  template <unsigned n>
207  gray_<n> operator/(const gray_<n>& lhs, int s);
208 
209  } // end of namespace mln::value::internal
210 
211  } // end of namespace mln::value
212 
213 } // end of namespace mln
214 
215 
216 # include <mln/value/internal/gray_f.hh>
217 
218 
219 namespace mln
220 {
221 
222 # ifndef MLN_INCLUDE_ONLY
223 
224  namespace value
225  {
226  namespace internal
227  {
228 
229  template <unsigned n_src, unsigned n_dest>
230  inline
231  long convert(int val)
232  {
233  using mln::metal::int_;
234  typedef mlc_max(int_<n_dest - n_src> , int_<n_src - n_dest>) m;
235 
236  if (n_dest == n_src)
237  return val;
238  else
239  if (n_dest > n_src)
240  return val * mlc_pow_int(2, m::value);
241  else
242  return val / mlc_pow_int(2, m::value);
243  }
244 
245  // Gray_<N>.
246 
247  template <unsigned n>
248  inline
249  gray_<n>::gray_()
250  {
251  }
252 
253  template <unsigned n>
254  template <unsigned m>
255  gray_<n>::gray_(const graylevel<m>& g)
256  {
257  this->v_ = convert<m, n>(g.value());
258  }
259 
260  template <unsigned n>
261  template <unsigned m>
262  inline
263  gray_<n>&
264  gray_<n>::operator=(const graylevel<m>& g)
265  {
266  this->v_ = convert<m, n>(g.value());
267  return *this;
268  }
269 
270  template <unsigned n>
271  inline
272  gray_<n>::gray_(const literal::white_t&)
273  {
274  this->v_ = mlc_pow_int(2, n) - 1;
275  }
276 
277  template <unsigned n>
278  inline
279  gray_<n>::gray_(const literal::black_t&)
280  {
281  this->v_ = 0;
282  }
283 
284  template <unsigned n>
285  inline
286  gray_<n>::gray_(int val)
287  {
288  this->v_ = val;
289  }
290 
291  template <unsigned n>
292  inline
293  int
294  gray_<n>::value() const
295  {
296  return this->v_;
297  }
298 
299  template <unsigned n>
300  template <unsigned m>
301  inline
302  gray_<n>::operator gray_<m>() const
303  {
304  return gray_<m>(convert<n, m>(this->v_));
305  }
306 
307 
308  template <unsigned n>
309  template <unsigned m>
310  inline
311  gray_<n>::operator graylevel<m>() const
312  {
313  graylevel<m> tmp(convert<n, m>(this->v_));
314  mln_assertion(tmp.value() < std::pow(2.f, int(m)));
315  return tmp;
316  }
317 
318 
319  template <unsigned n>
320  inline
321  gray_<n>::operator graylevel_f() const
322  {
323  static const float denom = float(metal::math::pow_int<2, n>::value) - 1.f;
324  return graylevel_f(float(this->v_) / denom);
325  }
326 
327  // Operators.
328 
329  template <unsigned n>
330  inline
331  std::ostream& operator<<(std::ostream& ostr, const gray_<n>& g)
332  {
333  return ostr << g.value() << "g/" << n << "bits";
334  }
335 
336  template <unsigned n, unsigned m>
337  inline
338  bool operator==(const gray_<n>& lhs, const gray_<m>& rhs)
339  {
340  if (n == m)
341  return internal::gray_<mlc_max_int(n, m)>(lhs).value() ==
342  internal::gray_<mlc_max_int(n, m)>(rhs).value();
343  if (n > m)
344  {
345  gray_<n> down = rhs;
346  gray_<n> up(down.value() +
347  mlc_pow_int(2, m));
348  return (lhs.value() >= down.value() && lhs.value() < up.value());
349  }
350  else
351  {
352  gray_<m> down = lhs;
353  gray_<m> up(down.value() +
354  mlc_pow_int(2, n));
355  return (rhs.value() >= down.value() && rhs.value() < up.value());
356  }
357  }
358 
359  template <unsigned n, unsigned m>
360  inline
361  bool operator<(const gray_<n>& lhs, const gray_<m>& rhs)
362  {
363  if (m == n)
364  return lhs.value() < rhs.value();
365  if (n > m)
366  return lhs.value() < gray_<n>(rhs).value();
367  else
368  return gray_<m>(lhs).value() < rhs.value();
369  }
370 
371  template <unsigned n, unsigned m>
372  inline
373  mln_trait_op_plus(gray_<n>, gray_<m>)
374  operator+(const gray_<n>& lhs, const gray_<m>& rhs)
375  {
376  typedef mln_trait_op_plus(gray_<n>, gray_<m>) ret;
377  if (n > m)
378  {
379  ret tmp(ret(lhs).value() + ret(rhs).value());
380  return tmp;
381  }
382  else
383  {
384  ret tmp(ret(lhs).value() + ret(rhs).value());
385  return tmp;
386  }
387  }
388 
389  template <unsigned n, unsigned m>
390  inline
391  mln_trait_op_minus(gray_<n>, gray_<m>)
392  operator-(const gray_<n>& lhs, const gray_<m>& rhs)
393  {
394  typedef mln_trait_op_minus(gray_<n>, gray_<m>) ret;
395 
396 
397  if (lhs == rhs)
398  return ret(0);
399  if (n == m)
400  return ret(lhs.value() - rhs.value());
401  if (n > m)
402  {
403  ret l = rhs;
404  mln_assertion(lhs.value() >= l.value());
405  ret tmp(lhs.value() - l.value());
406  return tmp;
407  }
408  else
409  {
410  ret l = lhs;
411  mln_assertion(l.value() >= rhs.value());
412  ret tmp(l.value() - rhs.value());
413  return tmp;
414  }
415  }
416 
417  template <unsigned n, unsigned m>
418  inline
419  mln_trait_op_times(gray_<n>, gray_<m>)
420  operator*(const gray_<n>& lhs, const gray_<m>& rhs)
421  {
422  typedef mln_trait_op_times(gray_<n>, gray_<m>) ret;
423 
424  return ret(ret(lhs).value() * ret(rhs).value());
425  }
426 
427  template <unsigned n>
428  inline
429  gray_<n> operator*(int s, const gray_<n>& rhs)
430  {
431  gray_<n> tmp(rhs.value() * s);
432  return tmp;
433  }
434 
435  template <unsigned n>
436  inline
437  gray_<n> operator*(const gray_<n>& lhs, int s)
438  {
439  gray_<n> tmp(lhs.value() * s);
440  return tmp;
441  }
442 
443  template <unsigned n>
444  inline
445  gray_<n> operator/(const gray_<n>& lhs, int s)
446  {
447  mln_precondition(s != 0);
448  gray_<n> tmp(lhs.value() / s);
449  return tmp;
450  }
451 
452  } // end of namespace mln::value::internal
453 
454  // Graylevel operators.
455 
456  // Op gl == Int.
457 
458  template <typename I, unsigned n>
459  inline
460  bool
461  operator==(const Integer<I>& lhs, const graylevel<n>& rhs)
462  {
463  return rhs.value() == exact(lhs);
464  }
465 
466  // Op gl == gl.
467 
468  template <unsigned n, unsigned m>
469  inline
470  bool
471  operator==(const graylevel<n>& lhs, const graylevel<m>& rhs)
472  {
473  return internal::gray_<n>(rhs) == internal::gray_<m>(lhs);
474  }
475 
476  // Op gl + gl.
477 
478  template <unsigned n, unsigned m>
479  inline
480  mln_trait_op_plus(graylevel<n>, graylevel<m>)
481  operator+(const graylevel<n>& lhs, const graylevel<m>& rhs)
482  {
483  return internal::gray_<n>(lhs) + internal::gray_<m>(rhs);
484  }
485 
486  // Op gl + Another type.
487  template <unsigned n, typename I>
488  inline
489  void
490  operator+(const graylevel<n>& lhs, const I& i)
491  {
492  (void) lhs;
493  (void) i;
494  typename graylevel<n>::wrong_use_of_graylevel___Please_use_the__to_enc__method a;
495  }
496 
497 
498  // Op Another type + gl.
499  template <unsigned n, typename I>
500  inline
501  void
502  operator+(const I& i, const graylevel<n>& rhs)
503  {
504  (void) i;
505  (void) rhs;
506  typename graylevel<n>::wrong_use_of_graylevel___Please_use_the__to_enc__method a;
507  }
508 
509  // Op gl - gl.
510  template <unsigned n, unsigned m>
511  inline
512  mln_trait_op_minus(graylevel<n>, graylevel<m>)
513  operator-(const graylevel<n>& lhs, const graylevel<m>& rhs)
514  {
515  return internal::gray_<n>(lhs) - internal::gray_<m>(rhs);
516  }
517 
518  // Op gl - Another type.
519  template <unsigned n, typename I>
520  inline
521  void
522  operator-(const graylevel<n>& lhs, const I& i)
523  {
524  (void) lhs;
525  (void) i;
526  typename graylevel<n>::wrong_use_of_graylevel___Please_use_the__to_enc__method a;
527  }
528 
529 
530  // Op Another type - gl.
531  template <unsigned n, typename I>
532  inline
533  void
534  operator-(const I& i, const graylevel<n>& rhs)
535  {
536  (void) i;
537  (void) rhs;
538  typename graylevel<n>::wrong_use_of_graylevel___Please_use_the__to_enc__method a;
539  }
540 
541  // Op gl * gl.
542  template <unsigned n, unsigned m>
543  inline
544  mln_trait_op_times(graylevel<n>, graylevel<m>)
545  operator*(const graylevel<n>& lhs, const graylevel<m>& rhs)
546  {
547  return internal::gray_<n>(lhs) * internal::gray_<m>(rhs);
548  }
549 
550  // Op symm gl * Integer.
551  template <unsigned n, typename I>
552  inline
553  internal::gray_<n>
554  operator*(const graylevel<n>& lhs, const Integer<I>& rhs)
555  {
556  return internal::gray_<n>(lhs) * int(exact(rhs));
557  }
558 
559  template <typename I, unsigned n>
560  inline
561  mln_trait_op_times(I, graylevel<n>)
562  operator*(const Integer<I>& lhs, const graylevel<n>& rhs)
563  {
564  return internal::gray_<n>(rhs) * int(exact(lhs));
565  }
566 
567  // Op symm gl * Floating.
568  template <unsigned n, typename F>
569  inline
570  mln_trait_op_times(graylevel<n>, F)
571  operator*(const graylevel<n>& lhs, const Floating<F>& rhs)
572  {
573  return lhs.to_float() * float(exact(rhs));
574  }
575 
576  template <typename F, unsigned n>
577  inline
578  mln_trait_op_times(F, graylevel<n>)
579  operator*(const Floating<F>& lhs, const graylevel<n>& rhs)
580  {
581  return rhs.to_float() * float(exact(lhs));
582  }
583 
584  // Op * Builtin.
585  template <unsigned n, typename T>
586  mln_trait_op_times(graylevel<n>, T)
587  operator*(const graylevel<n>& lhs, const T& rhs)
588  {
589  return lhs * scalar_<T>(rhs);
590  }
591 
592  template <unsigned n, typename T>
593  mln_trait_op_times(graylevel<n>, T)
594  operator*(const T& lhs, const graylevel<n>& rhs)
595  {
596  return rhs * scalar_<T>(lhs);
597  }
598 
599 
600  // Op / Builtin.
602  namespace internal
603  {
604  struct gray_f;
605  }
607 
608  template <unsigned n, typename T>
610  operator/(const graylevel<n>& lhs, const T& rhs)
611  {
612  return lhs / scalar_<T>(rhs);
613  }
614 
615 
616  // Op * scalar.
617  namespace internal
618  {
619 
620  template <typename ret>
621  struct helper_gray__op_;
622 
623  template <unsigned n>
624  struct helper_gray__op_< gray_<n> >
625  {
626  template <unsigned m, typename S>
627  inline static
628  mln_trait_op_times(graylevel<m>, scalar_<S>)
629  times(const graylevel<m>& lhs, const scalar_<S>& rhs)
630  {
631  typedef mln_trait_op_times(graylevel<m>, scalar_<S>) ret;
632  ret tmp(typename ret::equiv
633  (lhs.value() * typename ret::equiv(rhs.to_equiv())));
634  return tmp;
635  }
636 
637  template <unsigned m, typename S>
638  inline static
639  mln_trait_op_times(graylevel<m>, scalar_<S>)
640  div(const graylevel<m>& lhs, const scalar_<S>& rhs)
641  {
642  typedef mln_trait_op_times(graylevel<m>, scalar_<S>) ret;
643  ret tmp(typename ret::equiv
644  (lhs.value() / typename ret::equiv(rhs.to_equiv())));
645  return tmp;
646  }
647  };
648 
649  template <>
650  struct helper_gray__op_< gray_f >
651  {
652  template <unsigned n, typename S>
653  inline static
654  mln_trait_op_times(graylevel<n>, scalar_<S>)
655  times(const graylevel<n>& lhs, const scalar_<S>& rhs)
656  {
657  typedef mln_trait_op_times(graylevel<n>, scalar_<S>) ret;
658  ret tmp(lhs.to_float() * typename ret::equiv(rhs.to_equiv()));
659  return tmp;
660  }
661  template <unsigned n, typename S>
662  inline static
663  mln_trait_op_div(graylevel<n>, scalar_<S>)
664  div(const graylevel<n>& lhs, const scalar_<S>& rhs)
665  {
666  typedef mln_trait_op_div(graylevel<n>, scalar_<S>) ret;
667  ret tmp(typename ret::equiv
668  (lhs.to_float() / typename ret::equiv(rhs.to_equiv())));
669  return tmp;
670  }
671  };
672 
673  } // end of namespace mln::value::internal
674 
675  // Op graylevel<n> * scalar_<S>.
676  template <unsigned n, typename S>
677  inline
678  mln_trait_op_times(graylevel<n>, scalar_<S>)
679  operator*(const graylevel<n>& lhs, const scalar_<S>& rhs)
680  {
681  typedef mln_trait_op_times(graylevel<n>, scalar_<S>) ret;
682  return internal::helper_gray__op_<ret>::times(lhs, rhs);
683  }
684 
685  // Op graylevel<n> / scalar_<S>.
686  template <unsigned n, typename S>
687  inline
688  mln_trait_op_div(graylevel<n>, scalar_<S>)
689  operator/(const graylevel<n>& lhs, const scalar_<S>& rhs)
690  {
691  mln_precondition(rhs.to_equiv() != S(0));
692  typedef mln_trait_op_div(graylevel<n>, scalar_<S>) ret;
693  return internal::helper_gray__op_<ret>::div(lhs, rhs);
694  }
695 
696  } //end of namespace mln::value
697 
698 
699 
700 namespace trait
701 {
702 
703  // 'gray_<n>' as a value.
704 
705  template <unsigned n>
706  inline
708  value_< mln::value::internal::gray_<n> >::min()
709  {
710  return mln::value::internal::gray_<n>(1, 0);
711  }
712 
713  template <unsigned n>
714  inline
716  value_< mln::value::internal::gray_<n> >::max()
717  {
718  return mln::value::internal::gray_<n>(1, 1);
719  }
720 
721  template <unsigned n>
722  inline
724  value_< mln::value::internal::gray_<n> >::epsilon()
725  {
726  return mln::value::internal::gray_<n>(1, 0); // Means '0'.
727  }
728 
729 } // end of namespace mln::trait
730 
731 
732 # endif // ! MLN_INCLUDE_ONLY
733 
734 } // end of namespace mln
735 
736 #endif // ! MLN_VALUE_INTERNAL_GRAY__HH