
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena ChangeLog: 2007-10-01 Matthieu Garrigues <garrigues@lrde.epita.fr> Add gray values. * mln/value/gray.hh: General gray-level class where n bits is not know at compile-time. This class is used for exchange between gray-level types purpose. * mln/value/graylevel.hh: Graylevel class on n bits. * tests/value_gray.cc: Some tests. --- diffstat not available Index: trunk/milena/tests/value_gray.cc =================================================================== --- trunk/milena/tests/value_gray.cc (revision 0) +++ trunk/milena/tests/value_gray.cc (revision 1203) @@ -0,0 +1,44 @@ +// Copyright (C) 2007 EPITA Research and Development Laboratory +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to +// produce an executable, this file does not by itself cause the +// resulting executable to be covered by the GNU General Public +// License. This exception does not however invalidate any other +// reasons why the executable file might be covered by the GNU General +// Public License. + +#include <mln/value/graylevel.hh> + +int main() +{ + using namespace mln::value; + + gl8 a = white; + gl16 b = white; + assert((a == b) == true); + gl8 c = (a + b) / 2; + assert(c == white); + c = a; + assert(c == white); + + c = (a * 2) / 2; + assert(c == white); +} Index: trunk/milena/mln/value/graylevel.hh =================================================================== --- trunk/milena/mln/value/graylevel.hh (revision 0) +++ trunk/milena/mln/value/graylevel.hh (revision 1203) @@ -0,0 +1,208 @@ +// Copyright (C) 2006, 2007 EPITA Research and Development Laboratory +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to +// produce an executable, this file does not by itself cause the +// resulting executable to be covered by the GNU General Public +// License. This exception does not however invalidate any other +// reasons why the executable file might be covered by the GNU General +// Public License. + +#ifndef MLN_CORE_VALUE_GRAYLEVEL_HH +# define MLN_CORE_VALUE_GRAYLEVEL_HH + +# include <iostream> +# include <mln/core/contract.hh> +# include <mln/metal/math.hh> +# include <mln/metal/bexpr.hh> +# include <mln/value/internal/value_like.hh> +# include <mln/value/internal/encoding.hh> +# include <mln/value/gray.hh> +# include <mln/value/props.hh> + +namespace mln +{ + + namespace value + { + + /// Fwd decl. + class gray; + + + /// General gray-level class on n bits. + template <unsigned n> + class graylevel + : public internal::value_like_< typename internal::encoding_unsigned_<n>::ret, + graylevel<n> > + { + protected: + typedef internal::value_like_< typename internal::encoding_unsigned_<n>::ret, + graylevel<n> > super; + + public: + + /// Encoding associated type. + typedef typename super::enc enc; + + /// Ctor. + graylevel(); + + /// Ctor. + explicit graylevel(const int val); + + /// Access to std type. + enc value() const; + + /// Op encoding_t. + operator enc() const; + + /// Op graylevel. + operator graylevel() const; + + /// Op<. + bool operator<(const graylevel<n>& rhs) const; + + graylevel<n>& operator=(const int val); + /// Op==. + // bool operator==(const graylevel<n>& rhs) const; + + protected: + enc val_; + }; + + + template <unsigned n> + struct props< graylevel<n> > + { + static const std::size_t card_ = metal::pow<2, n>::value; + static const graylevel<n> min() { return 0; } + static const graylevel<n> max() { return card_ - 1; } + static const unsigned nbits = n; + typedef data_kind kind; + typedef float sum; + typedef int interop; + }; + + + /// Op<<. + template <unsigned n> + std::ostream& operator<<(std::ostream& ostr, const graylevel<n>& g); + + + /// Aliases. + typedef graylevel<8> gl8; + typedef graylevel<16> gl16; + typedef graylevel<32> gl32; + + + template <unsigned n, unsigned m> + bool operator==(const graylevel<n>& lhs, const graylevel<m>& rhs); + + template <unsigned n, unsigned m> + gray operator+(const graylevel<n>& lhs, const graylevel<m>& rhs); + + template <unsigned n, unsigned m> + gray operator-(const graylevel<n>& lhs, const graylevel<m>& rhs); + + template <unsigned n> + gray operator*(int s, const graylevel<n>& rhs); + + template <unsigned n> + gray operator*(const graylevel<n>& lhs, int s); + + template <unsigned n> + gray operator/(const graylevel<n>& lhs, int s); + + + +# ifndef MLN_INCLUDE_ONLY + + // Graylevel<n>. + + template <unsigned n> + graylevel<n>::graylevel() + { + } + + template <unsigned n> + graylevel<n>::graylevel(const int val) + : val_(val) + { + mln_precondition(val >= 0); + mln_precondition(unsigned(val) <= mln_max(enc)); + } + + template <unsigned n> + typename graylevel<n>::enc + graylevel<n>::value() const + { + return val_; + } + + template <unsigned n> + graylevel<n>& + graylevel<n>::operator=(const int val) + { + mln_precondition(val >= 0); + mln_precondition(unsigned(val) <= mln_max(enc)); + this->val_ = val; + return *this; + } + + template <unsigned n> + graylevel<n>::operator graylevel() const + { + gray tmp(n, val_); + return tmp; + } + + template <unsigned n> + graylevel<n>::operator typename graylevel<n>::enc() const + { + return val_; + } + + template <unsigned n> + bool graylevel<n>::operator<(const graylevel<n>& rhs) const + { + return val_ < rhs.val_; + } + + template <unsigned n> + std::ostream& operator<<(std::ostream& ostr, const graylevel<n>& g) + { + return ostr << g.value(); + } + + template <unsigned n, unsigned m> + bool operator==(const graylevel<n>& lhs, const graylevel<m>& rhs) + { + return gray(lhs) == gray(rhs); + } + +# endif + + + } // end of namespace mln::value + +} // end of namespace mln + +#endif // ! MLN_CORE_VALUE_GRAYLEVEL_HH Index: trunk/milena/mln/value/gray.hh =================================================================== --- trunk/milena/mln/value/gray.hh (revision 0) +++ trunk/milena/mln/value/gray.hh (revision 1203) @@ -0,0 +1,350 @@ +// Copyright (C) 2006, 2007 EPITA Research and Development Laboratory +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to +// produce an executable, this file does not by itself cause the +// resulting executable to be covered by the GNU General Public +// License. This exception does not however invalidate any other +// reasons why the executable file might be covered by the GNU General +// Public License. + +#ifndef MLN_VALUE_GRAY_HH +# define MLN_VALUE_GRAY_HH + +# include <iostream> +# include <mln/value/graylevel.hh> + + + +namespace mln +{ + + // Fwd decls. + namespace value + { + template <unsigned N> class graylevel; + class gray; + + /// General gray-level class where n bits is not know at compile-time. + /// This class is used for exchange between gray-level types purpose. + + class gray // FIXME do we need a super class? + //: public mln::internal::graylevel_value_< gray > + { + public: + + /// Ctor. + gray(); + + /// Ctor. + template <unsigned N> + gray(const graylevel<N>& val); + + /// Ctor. + gray(unsigned nbits, unsigned long val); + + /// Access to std type. + unsigned long value() const; + + unsigned nbits() const; + + void set_nbits(unsigned nbits); + + gray to_nbits(unsigned nbits) const; + + template <unsigned N> + operator graylevel<N>() const; + + protected: + unsigned nbits_; + unsigned long val_; + }; + + /// White. + extern const gray white; + + /// Black. + extern const gray black; + + std::ostream& operator<<(std::ostream& ostr, const gray& g); + + bool operator==(const gray& lhs, const gray& rhs); + bool operator<(const gray& lhs, const gray& rhs); + + gray operator+(const gray& lhs, const gray& rhs); + gray operator-(const gray& lhs, const gray& rhs); + + gray operator*(int s, const gray& rhs); + gray operator*(const gray& lhs, int s); + + gray operator/(const gray& lhs, int s); + + + + +# ifndef MLN_INCLUDE_ONLY + + const gray white = gray(1, 1); + const gray black = gray(1, 0); + + template <unsigned N, unsigned M> + gray operator+(const graylevel<N>& lhs, const graylevel<M>& rhs) + { + return gray(lhs) + gray(rhs); + } + + template <unsigned N, unsigned M> + gray operator-(const graylevel<N>& lhs, const graylevel<M>& rhs) + { + return gray(lhs) - gray(rhs); + } + + template <unsigned N> + gray operator*(int s, const graylevel<N>& rhs) + { + mln_precondition(s >= 0); + gray tmp(N, s * rhs.value()); + return tmp; + } + + template <unsigned N> + gray operator*(const graylevel<N>& lhs, int s) + { + mln_precondition(s >= 0); + gray tmp(N, lhs.value() * s); + return tmp; + } + + template <unsigned N> + gray operator/(const graylevel<N>& lhs, int s) + { + mln_precondition(s > 0); + gray tmp(N, lhs.value() / s); + return tmp; + } + + + + // Gray. + + gray::gray() + : nbits_(0) + { + } + + template <unsigned n> + gray::gray(const graylevel<n>& g) + : nbits_(n), + val_(g.value()) + { + } + + gray::gray(unsigned nbits, unsigned long val) + : nbits_(nbits), + val_(val) + { + } + + unsigned long gray::value() const + { + mln_invariant(nbits_ != 0); + return val_; + } + + unsigned gray::nbits() const + { + return nbits_; + } + + namespace internal + { + + unsigned long two_pow_(unsigned n) + { + if (n == 0) + return 1; + else + return 2 * two_pow_(n - 1); + } + + unsigned long two_pow_n_minus_1(unsigned n) + { + return two_pow_(n) - 1; + } + + template <unsigned n_dest> + unsigned long convert(unsigned n_src, unsigned long val) + { + if (n_dest == n_src) + return val; + else + if (n_dest > n_src) + return val * two_pow_n_minus_1(n_dest) / two_pow_n_minus_1(n_src); + else + return val / two_pow_(n_src - n_dest); + } + + } // end of mln::value::internal + + + void gray::set_nbits(unsigned nbits) + { + mln_precondition(nbits != 0); + mln_invariant(nbits_ != 0); + if (nbits == nbits_) + return; + if (nbits > nbits_) + { + val_ *= internal::two_pow_n_minus_1(nbits); + val_ /= internal::two_pow_n_minus_1(nbits_); + } + else // nbits < nbits_ + { + val_ /= internal::two_pow_(nbits_ - nbits); + } + nbits_ = nbits; + } + + + gray gray::to_nbits(unsigned nbits) const + { + mln_precondition(nbits != 0); + mln_invariant(nbits_ != 0); + gray tmp(*this); + tmp.set_nbits(nbits); + return tmp; + } + + + template <unsigned n> + gray::operator graylevel<n>() const + { + mln_precondition(nbits_ != 0); + graylevel<n> tmp(internal::convert<n>(nbits_, val_)); + + mln_assertion(tmp.value() < internal::two_pow_(n)); + return tmp; + } + + // operators + + std::ostream& operator<<(std::ostream& ostr, const gray& g) + { + return ostr << g.value() << '/' << g.nbits() << "nbits"; + } + + bool operator==(const gray& lhs, const gray& rhs) + { + mln_precondition(lhs.nbits() != 0 and rhs.nbits() != 0); + if (rhs.nbits() == lhs.nbits()) + return lhs.value() == rhs.value(); + if (lhs.nbits() > rhs.nbits()) + return lhs.value() == rhs.to_nbits(lhs.nbits()).value(); + else + return lhs.to_nbits(rhs.nbits()).value() == rhs.value(); + } + + bool operator<(const gray& lhs, const gray& rhs) + { + mln_precondition(lhs.nbits() != 0 and rhs.nbits() != 0); + if (rhs.nbits() == lhs.nbits()) + return lhs.value() < rhs.value(); + if (lhs.nbits() > rhs.nbits()) + return lhs.value() < rhs.to_nbits(lhs.nbits()).value(); + else + return lhs.to_nbits(rhs.nbits()).value() < rhs.value(); + } + + gray operator+(const gray& lhs, const gray& rhs) + { + mln_precondition(lhs.nbits() != 0 and rhs.nbits() != 0); + if (lhs.nbits() > rhs.nbits()) + { + gray tmp(lhs.nbits(), + lhs.value() + rhs.to_nbits(lhs.nbits()).value()); + return tmp; + } + else + { + gray tmp(rhs.nbits(), + lhs.to_nbits(rhs.nbits()).value() + rhs.value()); + return tmp; + } + } + + gray operator-(const gray& lhs, const gray& rhs) + { + mln_precondition(lhs.nbits() != 0 and rhs.nbits() != 0); + if (lhs.nbits() > rhs.nbits()) + { + unsigned long l = rhs.to_nbits(lhs.nbits()).value(); + assert(lhs.value() >= l); + gray tmp(lhs.nbits(), + lhs.value() - l); + return tmp; + } + else + { + unsigned long l = lhs.to_nbits(rhs.nbits()).value(); + assert(l >= rhs.value()); + gray tmp(rhs.nbits(), + l - rhs.value()); + return tmp; + } + } + + gray operator*(int s, const gray& rhs) + { + mln_precondition(s >= 0); + gray tmp(rhs.nbits(), rhs.value() * s); + return tmp; + } + + gray operator*(const gray& lhs, int s) + { + mln_precondition(s >= 0); + gray tmp(lhs.nbits(), lhs.value() * s); + return tmp; + } + + gray operator/(const gray& lhs, int s) + { + mln_precondition(s > 0); + gray tmp(lhs.nbits(), lhs.value() / s); + return tmp; + } + +// template <unsigned N> +// graylevel<N>& +// graylevel<N>::operator=(const gray& g) +// { +// mln_precondition(g.nbits() == N); +// assert(g.value() < internal::two_pow_(N)); +// this->val = g.value(); // FIXME: Add static_cast. +// } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::value + +} // end of namespace mln + + +#endif // ! MLN_VALUE_GRAY_HH