
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena ChangeLog: 2007-12-05 Simon Nivault <simon.nivault@lrde.epita.fr> Add mono object based rle image and add test. * mln/core/mono_obased_rle_encode.hh: New. * mln/core/mono_obased_rle_image.hh: New. * mln/core/mono_rle_encode.hh: Fix. * mln/core/mono_rle_image.hh: Add get_value() method. * mln/core/obased_rle_image.hh: Add vector of value for easier acces to the image. * tests/core/Makefile.am: Add test. * tests/core/mono_obased_rle_image.cc: New. --- mln/core/mono_obased_rle_encode.hh | 120 ++++++++++++++++ mln/core/mono_obased_rle_image.hh | 255 ++++++++++++++++++++++++++++++++++++ mln/core/mono_rle_encode.hh | 5 mln/core/mono_rle_image.hh | 19 ++ mln/core/obased_rle_image.hh | 36 +---- tests/core/Makefile.am | 2 tests/core/mono_obased_rle_image.cc | 78 +++++++++++ 7 files changed, 483 insertions(+), 32 deletions(-) Index: trunk/milena/tests/core/Makefile.am =================================================================== --- trunk/milena/tests/core/Makefile.am (revision 1593) +++ trunk/milena/tests/core/Makefile.am (revision 1594) @@ -7,6 +7,7 @@ clone \ exact \ initialize \ + mono_obased_rle_image \ mono_rle_image \ obased_rle_image \ p_runs \ @@ -17,6 +18,7 @@ clone_SOURCES = clone.cc exact_SOURCES = exact.cc initialize_SOURCES = initialize.cc +mono_obased_rle_image_SOURCES = mono_obased_rle_image.cc mono_rle_image_SOURCES = mono_rle_image.cc obased_rle_image_SOURCES = obased_rle_image.cc p_runs_SOURCES = p_runs.cc Index: trunk/milena/tests/core/mono_obased_rle_image.cc =================================================================== --- trunk/milena/tests/core/mono_obased_rle_image.cc (revision 0) +++ trunk/milena/tests/core/mono_obased_rle_image.cc (revision 1594) @@ -0,0 +1,78 @@ +// 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. + +/*! \file tests/core/mono_obased_rle_image.cc + * + * \brief Test on mln::mono_obased_rle_image.hh. + */ + +#include <mln/core/image2d.hh> +#include <mln/value/int_u8.hh> +#include <mln/io/pgm/load.hh> +#include <mln/pw/all.hh> +#include <mln/core/neighb2d.hh> + +#include <mln/labeling/blobs.hh> +#include <mln/level/transform.hh> +#include <mln/level/paste.hh> +#include <mln/level/compare.hh> +#include <mln/io/pgm/save.hh> + +#include <mln/core/mono_obased_rle_encode.hh> + +struct fold_t : public mln::Function_v2v< fold_t > +{ + typedef mln::value::int_u8 result; + result operator()(unsigned i) const { return i == 0 ? 0 : (i - 1) % 255 + 1; } +}; + + + +int main() +{ + using namespace mln; + using value::int_u8; + + image2d<int_u8> lena; + io::pgm::load(lena, "../../img/tiny.pgm"); + image2d<int_u8> cmp(lena.domain()); + + unsigned n; + image2d<unsigned> + labels = labeling::blobs((pw::value(lena) > pw::cst(172u)) | lena.domain(), + c4(), n); + + mono_obased_rle_image<point2d, int_u8> + rle = mono_obased_rle_encode(level::transform(labels, fold_t())); + + std::cout << n << ", compression :" << rle.compression() << std::endl; + + level::fill(cmp, literal::zero); + level::paste(rle, cmp); + + mln_assertion(cmp == level::transform(labels, fold_t())); +} Index: trunk/milena/mln/core/mono_rle_encode.hh =================================================================== --- trunk/milena/mln/core/mono_rle_encode.hh (revision 1593) +++ trunk/milena/mln/core/mono_rle_encode.hh (revision 1594) @@ -94,11 +94,8 @@ else { output.insert(p_run<P>(rstart, len)); - if ((len = (!ignore_zero || ima(p) != literal::zero))) - { + if ((len = (ima(p) == val))) rstart = p; - rvalue = ima(p); - } } } return output; Index: trunk/milena/mln/core/mono_rle_image.hh =================================================================== --- trunk/milena/mln/core/mono_rle_image.hh (revision 1593) +++ trunk/milena/mln/core/mono_rle_image.hh (revision 1594) @@ -55,7 +55,7 @@ data_(const T& val); /// Image value. - T value; + T value_; /// domain of the image p_runs_<P> domain_; @@ -128,6 +128,9 @@ /// Test if this image has been initialized. bool has_data() const; + /// Give the uniq value of the image. + rvalue get_value() const; + /// Give the set of values of the image. const vset& values() const; @@ -147,7 +150,7 @@ template <typename P, typename T> inline data_< mono_rle_image<P,T> >::data_(const T& val) - : value(val) + : value_(val) { } @@ -201,7 +204,15 @@ const { mln_precondition(site.pset_pos_() < this->data_->domain_.nruns()); - return this->data_->value; + return this->data_->value_; + } + + template <typename P, typename T> + inline + typename mono_rle_image<P, T>::rvalue + mono_rle_image<P, T>::get_value() const + { + return this->data_->value_; } template <typename P, typename T> @@ -210,7 +221,7 @@ mono_rle_image<P, T>::operator() (const typename mono_rle_image<P, T>::psite& site) { mln_precondition(site.pset_pos_() < this->data_->domain_.nruns()); - return this->data_->value; + return this->data_->value_; } template <typename P, typename T> Index: trunk/milena/mln/core/obased_rle_image.hh =================================================================== --- trunk/milena/mln/core/obased_rle_image.hh (revision 1593) +++ trunk/milena/mln/core/obased_rle_image.hh (revision 1594) @@ -62,6 +62,9 @@ std::vector< accu::bbox<P> > bbox_; /// Value of Objects. + std::vector<T> v_obj_; + + /// Image values. std::vector<T> values_; /// domain of the image @@ -163,7 +166,7 @@ bbox_(values.size()) { std::copy(values.begin(), values.end(), - std::back_inserter(this->values_)); + std::back_inserter(this->v_obj_)); } template <typename P, typename T> @@ -173,7 +176,7 @@ { return domain_.size_mem() + bbox_.size() * (sizeof(T) + sizeof(box_<P>) + sizeof(std::vector<unsigned>)) - + sizeof(unsigned) * domain_.nruns(); + + (sizeof(unsigned) + sizeof(T)) * domain_.nruns(); } } // end of namespace mln::internal @@ -206,14 +209,15 @@ void obased_rle_image<P, T>::insert(const p_run<P>& pr, T value) { - mln_assertion(this->data_->values_.size() == 0 || this->data_->domain_.nruns() == 0 || + mln_assertion(this->data_->v_obj_.size() == 0 || this->data_->domain_.nruns() == 0 || pr.first() > this->data_->domain_[this->data_->domain_.nruns() - 1].first()); this->data_->domain_.insert(pr); + this->data_->values_.push_back(value); unsigned i; - for (i = 0; i < this->data_->values_.size() - && this->data_->values_[i] != value; ++i) + for (i = 0; i < this->data_->v_obj_.size() + && this->data_->v_obj_[i] != value; ++i) ; - mln_assertion(i != this->data_->values_.size()); + mln_assertion(i != this->data_->v_obj_.size()); this->data_->obj_[i].push_back(this->data_->domain_.nruns() - 1); this->data_->bbox_[i].take(pr.bbox().pmin()); this->data_->bbox_[i].take(pr.bbox().pmax()); @@ -227,15 +231,7 @@ { mln_precondition(this->has_data() && site.pset_pos_() < this->data_->domain_.nruns()); - for (unsigned i = 0; i < this->data_->obj_.size(); ++i) - { - for (typename std::vector<unsigned>::const_iterator it = this->data_->obj_[i].begin(); - it != this->data_->obj_[i].end(); it++) - if (*it == site.pset_pos_()) - return this->data_->values_[i]; - } - mln_assertion(false); - return this->data_->values_[0]; + return this->data_->values_[site.pset_pos_()]; } template <typename P, typename T> @@ -245,15 +241,7 @@ { mln_precondition(this->has_data() && site.pset_pos_() < this->data_->domain_.nruns()); - for (unsigned i = 0; i < this->data_->obj_.size(); ++i) - { - for (typename std::vector<unsigned>::const_iterator it = this->data_->obj_[i].begin(); - it != this->data_->obj_[i].end(); it++) - if (*it == site.pset_pos_()) - return this->data_->values_[i]; - } - mln_assertion(false); - return this->data_->values_[0]; + return this->data_->values_[site.pset_pos_()]; } template <typename P, typename T> Index: trunk/milena/mln/core/mono_obased_rle_encode.hh =================================================================== --- trunk/milena/mln/core/mono_obased_rle_encode.hh (revision 0) +++ trunk/milena/mln/core/mono_obased_rle_encode.hh (revision 1594) @@ -0,0 +1,120 @@ +// 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. + +#ifndef MLN_CORE_MONO_OBASED_RLE_ENCODE_HH +# define MLN_CORE_MONO_OBASED_RLE_ENCODE_HH + +/*! \file mln/core/mono_obased_rle_encode.hh + * + * \brief Definintion of function which encodes an image in mono_obased_rle_image. + */ + +# include <mln/core/mono_obased_rle_image.hh> + +namespace mln +{ + + /*! + ** encode an image class to a mono_obased_rle_image + ** + ** @param input has to respect the Image concept + ** + ** @return mono_obased_rle_image + */ + template <typename I> + mono_obased_rle_image<mln_point(I), mln_value(I)> + mono_obased_rle_encode(const Image<I>& input, bool ignore_zero = true); + +# ifndef MLN_INCLUDE_ONLY + /*! + ** test if Point p1 and p2 are on the same line + */ + template <typename P> + inline + bool + on_the_same_line(const P& p1, const P& p2) + { + const unsigned dim = P::dim; + bool same_line = true; + + for (unsigned n = 0; same_line && n < dim - 1; ++n) + same_line = (p1[n] == p2[n]); + return same_line; + } + + template <typename I> + inline + mono_obased_rle_image<mln_point(I), mln_value(I)> + mono_obased_rle_encode(const Image<I>& input, bool ignore_zero) + { + typedef mln_point(I) P; + + const I& ima = exact(input); + mln_piter(I) p (exact(input).domain()); + unsigned len = 0; + mln_point(I) rstart; + mln_value(I) rvalue; + std::set< mln_value(I) > sv; + + for_all(p) + { + if (!ignore_zero || ima(p) != literal::zero) + sv.insert(ima(p)); + } + + mono_obased_rle_image<mln_point(I), mln_value(I)> output(sv); + for_all(p) + if (!ignore_zero || ima(p) != literal::zero || len) + { + if (len == 0) + { + ++len; + rstart = p; + rvalue = ima(p); + } + else + if (rvalue == ima(p) + && on_the_same_line(rstart, mln_point(I)(p))) + ++len; + else + { + output.insert(p_run<P>(rstart, len), rvalue); + if ((len = (!ignore_zero || ima(p) != literal::zero))) + { + rstart = p; + rvalue = ima(p); + } + } + } + return output; + } + +#endif // ! MLN_INCLUDE_ONLY + +} + +#endif // ! MLN_CORE_MONO_OBASED_RLE_ENCODE_HH Index: trunk/milena/mln/core/mono_obased_rle_image.hh =================================================================== --- trunk/milena/mln/core/mono_obased_rle_image.hh (revision 0) +++ trunk/milena/mln/core/mono_obased_rle_image.hh (revision 1594) @@ -0,0 +1,255 @@ +// 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. + +#ifndef MLN_CORE_MONO_OBASED_RLE_IMAGE_HH +# define MLN_CORE_MONO_OBASED_RLE_IMAGE_HH + +/*! \file mln/core/mono_obased_rle_image.hh + * + * \brief Definition of an image with rle encoding. + */ + +# include <mln/core/internal/run_image.hh> +# include <mln/core/p_runs.hh> +# include <mln/core/runs_psite.hh> +# include <mln/core/box.hh> +# include <mln/value/set.hh> +# include <mln/core/mono_rle_image.hh> +# include <vector> + +namespace mln +{ + + // Fwd decl. + template <typename P, typename T> struct mono_obased_rle_image; + + + namespace internal + { + + template <typename P, typename T> + struct data_< mono_obased_rle_image<P,T> > + { + data_(const std::set<T>& values); + + /// Objects. + std::vector< mono_rle_image<P, T> > ima_; + + /// Image value. + std::vector<T> values_; + + /// domain of the image + p_runs_<P> domain_; + + /// Return the size of the data in memory. + unsigned size_mem() const; + }; + + } // end of namespace mln::internal + + + namespace trait + { + + template <typename P, typename T> + struct image_< mono_obased_rle_image<P,T> > : default_image_< T, mono_obased_rle_image<P,T> > + { + typedef trait::image::category::primary category; + + typedef trait::image::access::browsing access; + // FIXME: Put the right dimension. + typedef trait::image::space::two_d space; + typedef trait::image::size::regular size; + typedef trait::image::support::aligned support; + + typedef trait::image::border::none border; + typedef trait::image::data::linear data; + typedef trait::image::io::read_only io; + typedef trait::image::speed::slow speed; + }; + + } // end of namespace mln::trait + + + /*! \brief RLE image. + * + * + * Parameter \c P is the type of the image points. + * Parameter \c T is the type of the pixel values. + * This image is not point wise accessible. + */ + template <typename P, typename T> + class mono_obased_rle_image : public internal::run_image_< T, P, mono_obased_rle_image<P, T> > + { + public: + typedef T value; + typedef T& lvalue; + typedef const T rvalue; + typedef runs_psite<P> psite; + typedef mln::value::set<T> vset; + typedef p_runs_<P> pset; + + + /// Skeleton. + typedef mono_obased_rle_image< tag::psite_<P>, tag::value_<T> > skeleton; + + + mono_obased_rle_image(const std::set<T>& values); + + /// Add a new range to the image. + void insert(const p_run<P>& pr, T value); + + /// Read-only access to the image value located at point \p p. + rvalue operator() (const psite& site) const; + + /// Read-write access to the image value located at point \p p. + lvalue operator() (const psite& site); + + /// Test if this image has been initialized. + bool has_data() const; + + /// Give the set of values of the image. + const vset& values() const; + + /// Give the definition domain. + const pset& domain() const; + + /// Give the index vector of the i-th object. + const mono_rle_image<P, T>& object(unsigned i) const; + + }; + + +# ifndef MLN_INCLUDE_ONLY + + namespace internal + { + + // internal::data_< mono_obased_rle_image<P,T> > + + template <typename P, typename T> + inline + data_< mono_obased_rle_image<P,T> >::data_(const std::set<T>& values) + : ima_(values.begin(), values.end()) + { + } + + template <typename P, typename T> + inline + unsigned + data_< mono_obased_rle_image<P,T> >::size_mem() const + { + return domain_.size_mem() * 2 + sizeof(T) * (values_.size() + ima_.size()); + } + + } // end of namespace mln::internal + + template <typename P, typename T> + inline + mono_obased_rle_image<P, T>::mono_obased_rle_image(const std::set<T>& values) + { + this->data_ = new internal::data_< mono_obased_rle_image<P,T> >(values); + } + + template <typename P, typename T> + inline + bool + mono_obased_rle_image<P, T>::has_data() const + { + return this->data_->ima_.size() != 0; + } + + template <typename P, typename T> + inline + const typename mono_obased_rle_image<P, T>::vset& + mono_obased_rle_image<P, T>::values() const + { + return vset::the(); + } + + template <typename P, typename T> + inline + void + mono_obased_rle_image<P, T>::insert(const p_run<P>& pr, T value) + { + mln_assertion(this->data_->values_.size() == 0 || this->data_->domain_.nruns() == 0 || + pr.first() > this->data_->domain_[this->data_->domain_.nruns() - 1].first()); + this->data_->domain_.insert(pr); + this->data_->values_.push_back(value); + unsigned i; + for (i = 0; i < this->data_->ima_.size() + && this->data_->ima_[i].get_value() != value; ++i) + ; + mln_assertion(i != this->data_->ima_.size()); + this->data_->ima_[i].insert(pr); + } + + template <typename P, typename T> + inline + typename mono_obased_rle_image<P, T>::rvalue + mono_obased_rle_image<P, T>::operator() (const typename mono_obased_rle_image<P, T>::psite& site) + const + { + mln_precondition(this->has_data() && + site.pset_pos_() < this->data_->domain_.nruns()); + return this->data_->values_[site.pset_pos_()]; + } + + template <typename P, typename T> + inline + typename mono_obased_rle_image<P, T>::lvalue + mono_obased_rle_image<P, T>::operator() (const typename mono_obased_rle_image<P, T>::psite& site) + { + mln_precondition(this->has_data() && + site.pset_pos_() < this->data_->domain_.nruns()); + return this->data_->values_[site.pset_pos_()]; + } + + template <typename P, typename T> + inline + const typename mono_obased_rle_image<P, T>::pset& + mono_obased_rle_image<P, T>::domain() const + { + return this->data_->domain_; + } + + template <typename P, typename T> + inline + const mono_rle_image<P, T>& + mono_obased_rle_image<P, T>::object(unsigned i) const + { + mln_assertion(i < this->data_->ima_.size()); + return this->data_->ima_[i]; + } + +# endif // ! MLN_INCLUDE_ONLY + + +} // end of namespace mln + + +#endif // ! MLN_CORE_MONO_OBASED_RLE_IMAGE_HH