r4335: Implement support for 2D tiled images and other drafts

URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox ChangeLog: 2009-08-03 Fabien Freling <fabien.freling@lrde.epita.fr> Implement support for 2D tiled images and other drafts. * fabien/igr/segment_us_morpho.sh: Small update. * fabien/magick/Makefile: Minor fix. * fabien/mln/canvas/browsing/directional.hh: Draft. * fabien/mln/canvas/browsing/snake.hh: Draft. * fabien/mln/core/image/magick_tiled2d.hh: Implement 2D tiled image with ImageMagick. * fabien/mln/core/image/tiled2d.hh: Implement 2D tiled image. * fabien/mln/data/fast_median.hh: Draft. * fabien/mln/io/pnm/load.hh: Add support for tiled images. * fabien/tests/core/image/Makefile: New Makefile for building. * fabien/tests/core/image/tiled2d.cc: New test for tiled images. --- igr/segment_us_morpho.sh | 4 mln/core/image/magick_tiled2d.hh | 56 ++++++ mln/io/pnm/load.hh | 334 +++++++++++++++++++++++++++++++++++++++ tests/core/image/Makefile | 7 tests/core/image/tiled2d.cc | 37 ++++ 5 files changed, 434 insertions(+), 4 deletions(-) Index: trunk/milena/sandbox/fabien/igr/segment_us_morpho.sh =================================================================== --- trunk/milena/sandbox/fabien/igr/segment_us_morpho.sh (revision 4334) +++ trunk/milena/sandbox/fabien/igr/segment_us_morpho.sh (revision 4335) @@ -4,10 +4,6 @@ process () { nlabels=`./filter_morpho_us $@` -#if [ $? -gt 0 ]; then -# echo "error: filter_morpho_us failed" -# exit -# fi ../bin/dump2pgm8b closing.dump closing.pgm convert closing.pgm 01_closing.png Index: trunk/milena/sandbox/fabien/tests/core/image/tiled2d.cc =================================================================== --- trunk/milena/sandbox/fabien/tests/core/image/tiled2d.cc (revision 0) +++ trunk/milena/sandbox/fabien/tests/core/image/tiled2d.cc (revision 4335) @@ -0,0 +1,37 @@ +#include <mln/core/image/tiled2d.hh> + +#include <mln/io/ppm/load.hh> +#include <mln/literal/colors.hh> +#include <mln/value/rgb8.hh> + +#include <mln/debug/quiet.hh> + + +using namespace mln; +using value::rgb8; + + +int main(int argc, char* argv[]) +{ + if (argc != 2) + { + std::cout << "Usage: " << argv[0] << " input output" << std::endl; + return 1; + } + + tiled2d<rgb8> tiled_ima; + + io::ppm::load(tiled_ima, argv[1]); + + std::cout << "bbox: " << tiled_ima.bbox() << std::endl; + /*mln_piter_(tiled2d<rgb8>) p(tiled_ima.domain()); + for_all(p) + { + if (p.col() % 64 == 0) + { + tiled_ima(p) = literal::purple; + } + }*/ + + return 0; +} Index: trunk/milena/sandbox/fabien/tests/core/image/Makefile =================================================================== --- trunk/milena/sandbox/fabien/tests/core/image/Makefile (revision 0) +++ trunk/milena/sandbox/fabien/tests/core/image/Makefile (revision 4335) @@ -0,0 +1,7 @@ +CXX = g++ +CXXFLAGS = -DNDEBUG -O1 +LIBS = `Magick++-config --cppflags --cxxflags --ldflags --libs` +INC = -I../../../ -I../../../../../ + +tiled2d: tiled2d.cc + ${CXX} ${CXXFLAGS} ${INC} $^ -o tiled2d Index: trunk/milena/sandbox/fabien/mln/io/pnm/load.hh =================================================================== --- trunk/milena/sandbox/fabien/mln/io/pnm/load.hh (revision 0) +++ trunk/milena/sandbox/fabien/mln/io/pnm/load.hh (revision 4335) @@ -0,0 +1,334 @@ +// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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_IO_PNM_LOAD_HH +# define MLN_IO_PNM_LOAD_HH + +/// \file +/// +/// Define a function which loads an image of kind PNM 8/16bits with +/// given path. + +# include <iostream> +# include <fstream> +# include <string> + +# include <mln/core/image/image2d.hh> +# include <mln/core/image/tiled2d.hh> + +# include <mln/value/int_u8.hh> +# include <mln/value/rgb.hh> + +# include <mln/io/pnm/load_header.hh> +# include <mln/io/pnm/max_component.hh> +# include <mln/io/pnm/macros.hh> + +# include <mln/metal/is_a.hh> + +namespace mln +{ + + namespace io + { + + namespace pnm + { + + +# ifndef MLN_INCLUDE_ONLY + + template <typename I> + void load_ascii_value(std::ifstream& file, I& ima); + + template <typename I> + void load_ascii_builtin(std::ifstream& file, I& ima); + + + namespace internal + { + + template <typename I> + inline + void + load_ascii_dispatch(std::ifstream& file, I& ima, const metal::bool_<true>&) + { + load_ascii_value(file, ima); + } + + template <typename I> + inline + void + load_ascii_dispatch(std::ifstream& file, I& ima, const metal::bool_<false>&) + { + load_ascii_builtin(file, ima); + } + + } // end of namespace mln::io::pnm::internal + + + // Read a Milena rgb value (sizeof(int_u8) != 1). + template <unsigned int n> + inline + void read_value(std::ifstream& file, value::rgb<n>& v) + { + typedef typename value::int_u<n>::enc E; + + E c; + file.read((char*)(&c), sizeof(E)); + v.red() = c; + file.read((char*)(&c), sizeof(E)); + v.green() = c; + file.read((char*)(&c), sizeof(E)); + v.blue() = c; + } + + // Read a Milena scalar value (sizeof(int_u8) != 1). + template <class V> + inline + void read_value(std::ifstream& file, value::Scalar<V>& v) + { + typedef typename V::enc E; + + E c; + file.read((char*)(&c), sizeof(E)); + exact(v) = c; + } + + // Read a builtin scalar value. + template <typename V> + inline + void read_value(std::ifstream& file, V& v) + { + V c; + file.read((char*)(&c), sizeof(V)); + v = c; + } + + // used when (sizeof(int_u8) != 1) + template <typename V> + inline + void load_raw_2d_uncontiguous(std::ifstream& file, image2d<V>& ima) + { + const def::coord + min_row = geom::min_row(ima), + max_row = geom::max_row(ima), + min_col = geom::min_col(ima), + max_col = geom::max_col(ima); + + point2d p; + for (p.row() = min_row; p.row() <= max_row; ++p.row()) + for (p.col() = min_col; p.col() <= max_col; ++p.col()) + read_value(file, ima(p)); + } + + // Warning if we try to load uncontiguous 2D PNM file into a tiled + // image, this is not currently supported. + template <typename V> + inline + void load_raw_2d_uncontiguous(std::ifstream& file, tiled2d<V>& ima) + { + (void) file; + (void) ima; + std::cout << "You can't load an uncontiguous 2D PNM file into "; + std::cout << "a tiled image" << std::endl; + abort(); + } + + // used in g++ > 2.95 + template <typename I> + inline + void load_raw_2d_contiguous(std::ifstream& file, I& ima, std::string& filename) + { + (void) filename; + point2d p = point2d(0, ima.domain().pmin().col()); + typedef mln_value(I) V; + const mln_deduce(I, site, coord) + min_row = geom::min_row(ima), + max_row = geom::max_row(ima); + + std::size_t len = geom::ncols(ima) * sizeof(V); + for (p.row() = min_row; p.row() <= max_row; ++p.row()) + file.read((char*)(&ima(p)), len); + } + + // Load raw 2d for tiled images. + template <typename T> + inline + void load_raw_2d_contiguous(std::ifstream& file, tiled2d<T>& ima, std::string& filename) + { + ima.pos_() = file.tellg(); + ima.file_() = filename; + } + + /// load_ascii for Milena value types. + template <typename I> + inline + void load_ascii_value(std::ifstream& file, I& ima) + { + mln_equiv(mln_value_(I)) c; + mln_fwd_piter(I) p(ima.domain()); + for_all(p) + { + file >> c; + ima(p) = c; + } + } + + /// load_ascii for builtin value types. + template <typename I> + inline + void load_ascii_builtin(std::ifstream& file, I& ima) + { + mln_fwd_piter(I) p(ima.domain()); + + // FIXME: May be wrong! + // Worked out with an image with a max value of 255 + // loaded in an image2d<unsigned char>. + unsigned n; + + for_all(p) + { + file >> n; + ima(p) = n; + } + } + + /// load_raw_2d. + /// for all pnm 8/16 bits formats + template <typename I> + inline + void load_raw_2d(std::ifstream& file, I& ima, std::string& filename) + { + if (sizeof(value::int_u8) == 1) + load_raw_2d_contiguous(file, ima, filename); + else + load_raw_2d_uncontiguous(file, ima); + } + + /// main function : load pnm format + template <typename V> + inline + image2d<V> load(char type_, const std::string& filename) + { + trace::entering("mln::io::pnm::load"); + + std::ifstream file(filename.c_str()); + if (! file) + { + std::cerr << "error: file '" << filename + << "' not found!"; + abort(); + } + char type = 0; + int nrows, ncols; + unsigned int maxval; + read_header(static_cast<char>(type_ - 3), type_, file, type, + nrows, ncols, maxval); + + if (max_component(V()) != maxval) + { + std::cerr << "error: file '" << filename + << "' cannot be loaded into this type of image" + << std::endl; + + std::cerr << "input image have " << maxval + << " as maximum value while the destination's one is " + << max_component(V()) << " (should be the same)." + << std::endl; + abort(); + } + + image2d<V> ima(nrows, ncols); + if (type == type_) + load_raw_2d(file, ima, filename); + else + if (type == (type_ - 3)) + pnm::internal::load_ascii_dispatch(file, ima, mlc_is_a(V, mln::Value)()); + + trace::exiting("mln::io::pnm::load"); + + return ima; + } + + /// An other way to load pnm files : + /// the destination is an argument to check if + /// the type match the file to load. + template <typename I> + inline + void load(char type_, + Image<I>& ima_, + const std::string& filename) + { + trace::entering("mln::io::pnm::load"); + + std::ifstream file(filename.c_str()); + if (! file) + { + std::cerr << "error: file '" << filename + << "' not found!"; + abort(); + } + + I& ima = exact(ima_); + + char type = 0; + int nrows, ncols; + unsigned int maxval; + read_header(static_cast<char>(type_ - 3), type_, file, type, + nrows, ncols, maxval); + + if (max_component(mln_value(I)()) != maxval) + { + std::cerr << "error: file '" << filename + << "' cannot be loaded into this type of image" + << std::endl; + + std::cerr << "input image have " << maxval + << " as maximum value while the destination's one is " + << max_component(mln_value(I)()) << "." + << std::endl; + abort(); + } + + ima.init_(make::box2d(nrows, ncols)); + if (type == type_) + load_raw_2d(file, ima); + else + if (type == (type_ - 3)) + pnm::internal::load_ascii_dispatch(file, ima, mlc_is_a(mln_value(I), mln::Value)()); + + trace::exiting("mln::io::pnm::load"); + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::io::pnm + + } // end of namespace mln::io + +} // end of namespace mln + + +#endif // ! MLN_IO_PNM_LOAD_HH Index: trunk/milena/sandbox/fabien/mln/core/image/magick_tiled2d.hh =================================================================== --- trunk/milena/sandbox/fabien/mln/core/image/magick_tiled2d.hh (revision 0) +++ trunk/milena/sandbox/fabien/mln/core/image/magick_tiled2d.hh (revision 4335) @@ -0,0 +1,659 @@ +// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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_IMAGE_TILED2D_HH +# define MLN_CORE_IMAGE_TILED2D_HH + +/// \file +/// Definition of the basic mln::tiled2d class. + +# include <Magick++.h> + +# include <mln/core/internal/image_primary.hh> +# include <mln/core/internal/fixme.hh> +# include <mln/core/alias/box2d.hh> +# include <mln/core/routine/init.hh> + +# include <mln/border/thickness.hh> +# include <mln/value/set.hh> +# include <mln/fun/i2v/all_to.hh> +# include <mln/value/proxy.hh> + + + +namespace mln +{ + + // Forward declaration. + template <typename T> struct tiled2d; + + + namespace internal + { + + /// Data structure for \c mln::tiled2d<T>. + template <typename T> + struct data< tiled2d<T> > + { +// data(const box2d& b, unsigned bdr); + data(const std::string& filename); + ~data(); + + Magick::Image buffer_; + Magick::PixelPacket* pixel_cache; + T value_; + + box2d b_; // theoretical box + unsigned bdr_; + box2d vb_; // virtual box, i.e., box including the virtual border + + void update_vb_(); + void allocate_(); + void deallocate_(); + void swap_(data< tiled2d<T> >& other_); + void reallocate_(unsigned new_border); + }; + + } // end of namespace mln::internal + + + namespace trait + { + + template <typename T> + struct image_< tiled2d<T> > : default_image_< T, tiled2d<T> > + { + // misc + typedef trait::image::category::primary category; + typedef trait::image::speed::slow speed; + typedef trait::image::size::regular size; + + // value + typedef trait::image::vw_io::none vw_io; + typedef trait::image::vw_set::none vw_set; + typedef trait::image::value_access::direct value_access; + typedef trait::image::value_storage::one_block value_storage; + typedef trait::image::value_browsing::site_wise_only value_browsing; + typedef trait::image::value_alignment::with_grid value_alignment; + typedef trait::image::value_io::read_only value_io; + + // site / domain + typedef trait::image::pw_io::read_write pw_io; + typedef trait::image::localization::basic_grid localization; + typedef trait::image::dimension::two_d dimension; + + // extended domain + typedef trait::image::ext_domain::extendable ext_domain; + typedef trait::image::ext_value::multiple ext_value; + typedef trait::image::ext_io::read_only ext_io; + }; + + } // end of namespace mln::trait + + + + /// Basic 2D image class. + /// + /// The parameter \c T is the type of pixel values. This image class + /// stores data in memory and has a virtual border with constant + /// thickness around data. + /// + /// \ingroup modimageconcrete + // + template <typename T> + class tiled2d : public internal::image_primary< T, mln::box2d, tiled2d<T> > + { + typedef internal::image_primary< T, mln::box2d, tiled2d<T> > super_; + public: + + /// Value associated type. + typedef T value; + + /// Return type of read-only access. + typedef const T& rvalue; + + /// Return type of read-write access. + typedef mln::value::proxy< tiled2d<T> > lvalue; + + + /// Skeleton. + typedef tiled2d< tag::value_<T> > skeleton; + + + /// Constructor without argument. + tiled2d(); + + /// Constructor with the numbers of rows and columns and the + /// border thickness. + //tiled2d(int nrows, int ncols, unsigned bdr = border::thickness); + + /// Constructor with a box and the border thickness (default is + /// 3). + // tiled2d(const box2d& b, unsigned bdr = border::thickness); + + /// Constructor with a filename. + tiled2d(const std::string& filename); + + + /// Initialize an empty image. + //void init_(const box2d& b, unsigned bdr = border::thickness); + + /// Initialize an empty image. + void init_(const std::string& filename); + + + /// Test if \p p is valid. + bool has(const point2d& p) const; + + /// Give the definition domain. + const box2d& domain() const; + + /// Give the bounding box domain. + const box2d& bbox() const; + + /// Read-only access to the image value located at point \p p. + const T& operator()(const point2d& p) const; + + /// Read-write access to the image value located at point \p p. + mln::value::proxy< tiled2d<T> > operator()(const point2d& p); + + // Read access to the image value located at point \p p. + const T& read_(const point2d& p) const; + + // Write access to the image value located at point \p p. + void write_(const point2d& p, const T& value); + + + template <typename P> + T& alt(const P& p) + { + typedef def::coord coord_t; + mln_precondition(this->has(p)); + + return this->data_->array_ [*(coord_t*)(&p.p_hook_())] [*((coord_t*)(&p.p_hook_()) + 1)]; + } + + + // Specific methods: + // ----------------- + + /// Read-only access to the image value located at (\p row, \p col). + const T& at_(unsigned row, unsigned col) const; + + /// Read-write access to the image value located at (\p row, \p col). + T& at_(unsigned row, unsigned col); + + /// Give the number of rows. + unsigned nrows() const; + + /// Give the number of columns. + unsigned ncols() const; + + + // As a fastest image: + // ------------------- + + // Give the index of a point. + //using super_::index_of_point; + + /// Give the border thickness. + unsigned border() const; + + /// Give the number of elements (points including border ones). + unsigned nelements() const; + + /// Read-only access to the image value located at index \p i. + const T& element(unsigned i) const; + + /// Read-write access to the image value located at index \p i. + T& element(unsigned i); + + /// Give the delta-index corresponding to the delta-point \p dp. + int delta_index(const dpoint2d& dp) const; + + /// Give the point corresponding to the index \p i. + point2d point_at_index(unsigned i) const; + + /// Give a hook to the value buffer. + const Magick::Image buffer() const; + + /// Give a hook to the value buffer. + Magick::Image buffer(); + + + /// Resize image border with new_border. + void resize_(unsigned new_border); + }; + + + + // Forward declaration + + template <typename T> + void init_(tag::border_t, unsigned& bdr, const tiled2d<T>& model); + + template <typename T, typename J> + void init_(tag::image_t, mln::tiled2d<T>& target, const J& model); + + + +# ifndef MLN_INCLUDE_ONLY + + // init_ + + template <typename T> + inline + void init_(tag::border_t, unsigned& bdr, const tiled2d<T>& model) + { + bdr = model.border(); + } + + template <typename T, typename J> + inline + void init_(tag::image_t, tiled2d<T>& target, const J& model) + { + box2d b; + init_(tag::bbox, b, model); + unsigned bdr; + init_(tag::border, bdr, model); + target.init_(b, bdr); + } + + + // internal::data< tiled2d<T> > + + namespace internal + { +/* template <typename T> + inline + data< tiled2d<T> >::data(const box2d& b, unsigned bdr) + : buffer_(0), + b_ (b), + bdr_ (bdr) + { + allocate_(); + }*/ + + template <typename T> + inline + data< tiled2d<T> >::data(const std::string& filename) + { + buffer_.read(filename); + // DELETEME + std::cout << "columns: " << buffer_.columns() << std::endl; + std::cout << "rows: " << buffer_.rows() << std::endl; + // ! DELETEME + b_ = make::box2d(buffer_.rows(), buffer_.columns()); + std::cout << "bbox: " << b_ << std::endl; // DELETEME + } + + template <typename T> + inline + data< tiled2d<T> >::~data() + { + deallocate_(); + } + + template <typename T> + inline + void + data< tiled2d<T> >::update_vb_() + { + vb_.pmin() = b_.pmin() - dpoint2d(all_to(bdr_)); + vb_.pmax() = b_.pmax() + dpoint2d(all_to(bdr_)); + } + + template <typename T> + inline + void + data< tiled2d<T> >::allocate_() + { + update_vb_(); +// unsigned +// nr = vb_.len(0), +// nc = vb_.len(1); +// buffer_ = new T[nr * nc]; +// array_ = new T*[nr]; +// T* buf = buffer_ - vb_.pmin().col(); +// for (unsigned i = 0; i < nr; ++i) +// { +// array_[i] = buf; +// buf += nc; +// } +// array_ -= vb_.pmin().row(); + mln_postcondition(vb_.len(0) == b_.len(0) + 2 * bdr_); + mln_postcondition(vb_.len(1) == b_.len(1) + 2 * bdr_); + } + + template <typename T> + inline + void + data< tiled2d<T> >::deallocate_() + { +// if (buffer_) +// { +// delete[] buffer_; +// buffer_ = 0; +// } +// if (array_) +// { +// array_ += vb_.pmin().row(); +// delete[] array_; +// array_ = 0; +// } + } + + template <typename T> + inline + void + data< tiled2d<T> >::swap_(data< tiled2d<T> >& other_) + { + data< tiled2d<T> > self_ = *this; + *this = other_; + other_ = self_; + } + + template <typename T> + inline + void + data< tiled2d<T> >::reallocate_(unsigned new_border) + { + data< tiled2d<T> >& tmp = *(new data< tiled2d<T> >(this->b_, new_border)); + this->swap_(tmp); + } + + + } // end of namespace mln::internal + + + // tiled2d<T> + + template <typename T> + inline + tiled2d<T>::tiled2d() + { + } + + template <typename T> + inline + tiled2d<T>::tiled2d(const std::string& filename) + { + init_(filename); + } + + template <typename T> + inline + void + tiled2d<T>::init_(const std::string& filename) + { + mln_precondition(! this->is_valid()); + this->data_ = new internal::data< tiled2d<T> >(filename); + } + + template <typename T> + inline + const box2d& + tiled2d<T>::domain() const + { + mln_precondition(this->is_valid()); + return this->data_->b_; + } + + template <typename T> + inline + const box2d& + tiled2d<T>::bbox() const + { + mln_precondition(this->is_valid()); + return this->data_->b_; + } + + template <typename T> + inline + bool + tiled2d<T>::has(const point2d& p) const + { + mln_precondition(this->is_valid()); + return this->data_->vb_.has(p); + } + + template <typename T> + inline + const T& + tiled2d<T>::operator()(const point2d& p) const + { + return read_(p); + } + + template <typename T> + inline + mln::value::proxy< tiled2d<T> > + tiled2d<T>::operator()(const point2d& p) + { + mln::value::proxy<tiled2d> prx(*this, p); + return prx; + } + + template <typename T> + inline + const T& + tiled2d<T>::read_(const point2d& p) const + { + mln::tiled2d<T>* this_ = const_cast<mln::tiled2d<T>* >(this); // Trust me, I have to do this(_). + this_->data_->pixel_cache = this_->data_->buffer_.getPixels(p.col(), p.row(), p.col(), p.row()); + this->data_->value_.red() = this->data_->pixel_cache->red % 256; + this->data_->value_.green() = this->data_->pixel_cache->green % 256; + this->data_->value_.blue() = this->data_->pixel_cache->blue % 256; + return this->data_->value_; + } + + template <typename T> + inline + void + tiled2d<T>::write_(const point2d& p, const T& value) + { + std::cout << "setting value " << value << " at point " << p << std::endl; // DELETEME + /*this->data_->pixel_cache = this->data_->buffer_.getPixels(p.col(), p.row(), p.col(), p.row()); + *(this->data_->pixel_cache) = Magick::ColorRGB(256 - value.red(), + 256 - value.green(), + 256 - value.blue());*/ + } + + + // Specific methods: + + template <typename T> + inline + const T& + tiled2d<T>::at_(unsigned row, unsigned col) const + { + mln_precondition(this->has(point2d(row, col))); + //FIXME: use the cache Luke. + this->data_->pixel_cache = this->data_->buffer_.getPixels(col, row, col, row); + this->data_->value_.red() = this->data_->pixel_cache->red % 256; + this->data_->value_.green() = this->data_->pixel_cache->green % 256; + this->data_->value_.blue() = this->data_->pixel_cache->blue % 256; + return this->data_->value_; + } + + template <typename T> + inline + T& + tiled2d<T>::at_(unsigned row, unsigned col) + { + mln_precondition(this->has(point2d(row, col))); + //FIXME: use the cache Luke. + this->data_->pixel_cache = this->data_->buffer_.getPixels(col, row, col, row); + this->data_->value_.red() = this->data_->pixel_cache->red % 256; + this->data_->value_.green() = this->data_->pixel_cache->green % 256; + this->data_->value_.blue() = this->data_->pixel_cache->blue % 256; + return this->data_->value_; + } + + template <typename T> + inline + unsigned + tiled2d<T>::nrows() const + { + mln_precondition(this->is_valid()); + return this->data_->b_.len(0); + } + + template <typename T> + inline + unsigned + tiled2d<T>::ncols() const + { + mln_precondition(this->is_valid()); + return this->data_->b_.len(1); + } + + + // Hooks. + + template <typename T> + inline + const Magick::Image + tiled2d<T>::buffer() const + { + mln_precondition(this->is_valid()); + return this->data_->buffer_; + } + + template <typename T> + inline + Magick::Image + tiled2d<T>::buffer() + { + mln_precondition(this->is_valid()); + return this->data_->buffer_; + } + + +# endif // ! MLN_INCLUDE_ONLY + +} // end of namespace mln + + + +# include <mln/core/trait/pixter.hh> +# include <mln/core/dpoints_pixter.hh> +# include <mln/core/pixter2d.hh> +// # include <mln/core/w_window.hh> + + +namespace mln +{ + + namespace trait + { + + // pixter + + template <typename T> + struct fwd_pixter< tiled2d<T> > + { + typedef fwd_pixter2d< tiled2d<T> > ret; + }; + + template <typename T> + struct fwd_pixter< const tiled2d<T> > + { + typedef fwd_pixter2d< const tiled2d<T> > ret; + }; + + template <typename T> + struct bkd_pixter< tiled2d<T> > + { + typedef bkd_pixter2d< tiled2d<T> > ret; + }; + + template <typename T> + struct bkd_pixter< const tiled2d<T> > + { + typedef bkd_pixter2d< const tiled2d<T> > ret; + }; + + // qixter + + template <typename T, typename W> + struct fwd_qixter< tiled2d<T>, W > + { + typedef dpoints_fwd_pixter< tiled2d<T> > ret; + }; + + template <typename T, typename W> + struct fwd_qixter< const tiled2d<T>, W > + { + typedef dpoints_fwd_pixter< const tiled2d<T> > ret; + }; + + template <typename T, typename W> + struct bkd_qixter< tiled2d<T>, W > + { + typedef dpoints_bkd_pixter< tiled2d<T> > ret; + }; + + template <typename T, typename W> + struct bkd_qixter< const tiled2d<T>, W > + { + typedef dpoints_bkd_pixter< const tiled2d<T> > ret; + }; + + // nixter + + template <typename T, typename N> + struct fwd_nixter< tiled2d<T>, N > + { + typedef dpoints_fwd_pixter< tiled2d<T> > ret; + }; + + template <typename T, typename N> + struct fwd_nixter< const tiled2d<T>, N > + { + typedef dpoints_fwd_pixter< const tiled2d<T> > ret; + }; + + template <typename T, typename N> + struct bkd_nixter< tiled2d<T>, N > + { + typedef dpoints_bkd_pixter< tiled2d<T> > ret; + }; + + template <typename T, typename N> + struct bkd_nixter< const tiled2d<T>, N > + { + typedef dpoints_bkd_pixter< const tiled2d<T> > ret; + }; + + } // end of namespace mln::trait + +} // end of namespace mln + + +# include <mln/make/image.hh> + + +#endif // ! MLN_CORE_IMAGE_TILED2D_HH Index: trunk/milena/sandbox/fabien/mln/core/image/tiled2d.hh =================================================================== --- trunk/milena/sandbox/fabien/mln/core/image/tiled2d.hh (revision 0) +++ trunk/milena/sandbox/fabien/mln/core/image/tiled2d.hh (revision 4335) @@ -0,0 +1,676 @@ +// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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_IMAGE_TILED2D_HH +# define MLN_CORE_IMAGE_TILED2D_HH + +/// \file +/// Definition of the basic mln::tiled2d class. + +# include <mln/core/internal/image_primary.hh> +# include <mln/core/internal/fixme.hh> +# include <mln/core/alias/box2d.hh> +# include <mln/core/routine/init.hh> + +# include <mln/border/thickness.hh> +# include <mln/value/set.hh> +# include <mln/fun/i2v/all_to.hh> +# include <mln/value/proxy.hh> + + + +namespace mln +{ + + // Forward declaration. + template <typename T> struct tiled2d; + + + namespace internal + { + + /// Data structure for \c mln::tiled2d<T>. + template <typename T> + struct data< tiled2d<T> > + { +// data(const box2d& b, unsigned bdr); + data(const box2d& b, unsigned bdr); + ~data(); + + std::fstream* f_; + std::streampos pos_; + T value_; + + box2d b_; // theoretical box + unsigned bdr_; + box2d vb_; // virtual box, i.e., box including the virtual border + + void update_vb_(); + void allocate_(); + void deallocate_(); + void swap_(data< tiled2d<T> >& other_); + void reallocate_(unsigned new_border); + }; + + } // end of namespace mln::internal + + + namespace trait + { + + template <typename T> + struct image_< tiled2d<T> > : default_image_< T, tiled2d<T> > + { + // misc + typedef trait::image::category::primary category; + typedef trait::image::speed::slow speed; + typedef trait::image::size::regular size; + + // value + typedef trait::image::vw_io::none vw_io; + typedef trait::image::vw_set::none vw_set; + typedef trait::image::value_access::direct value_access; + typedef trait::image::value_storage::one_block value_storage; + typedef trait::image::value_browsing::site_wise_only value_browsing; + typedef trait::image::value_alignment::with_grid value_alignment; + typedef trait::image::value_io::read_only value_io; + + // site / domain + typedef trait::image::pw_io::read_write pw_io; + typedef trait::image::localization::basic_grid localization; + typedef trait::image::dimension::two_d dimension; + + // extended domain + typedef trait::image::ext_domain::extendable ext_domain; + typedef trait::image::ext_value::multiple ext_value; + typedef trait::image::ext_io::read_only ext_io; + }; + + } // end of namespace mln::trait + + + + /// Basic 2D image class. + /// + /// The parameter \c T is the type of pixel values. This image class + /// stores data in memory and has a virtual border with constant + /// thickness around data. + /// + /// \ingroup modimageconcrete + // + template <typename T> + class tiled2d : public internal::image_primary< T, mln::box2d, tiled2d<T> > + { + typedef internal::image_primary< T, mln::box2d, tiled2d<T> > super_; + public: + + /// Value associated type. + typedef T value; + + /// Return type of read-only access. + typedef const T& rvalue; + + /// Return type of read-write access. + typedef mln::value::proxy< tiled2d<T> > lvalue; + + + /// Skeleton. + typedef tiled2d< tag::value_<T> > skeleton; + + + /// Constructor without argument. + tiled2d(); + + /// Constructor with the numbers of rows and columns and the + /// border thickness. + //tiled2d(int nrows, int ncols, unsigned bdr = border::thickness); + + /// Constructor with a box and the border thickness (default is + /// 3). + tiled2d(const box2d& b, unsigned bdr = border::thickness); + + /// Constructor with a filename. + //tiled2d(const std::string& filename); + + + /// Initialize an empty image. + void init_(const box2d& b, unsigned bdr = border::thickness); + + /// Initialize an empty image. + //void init_(const std::string& filename); + + + /// Test if \p p is valid. + bool has(const point2d& p) const; + + /// Give the definition domain. + const box2d& domain() const; + + /// Give the bounding box domain. + const box2d& bbox() const; + + /// Read-only access to the image value located at point \p p. + const T& operator()(const point2d& p) const; + + /// Read-write access to the image value located at point \p p. + mln::value::proxy< tiled2d<T> > operator()(const point2d& p); + + // Read access to the image value located at point \p p. + const T& read_(const point2d& p) const; + + // Write access to the image value located at point \p p. + void write_(const point2d& p, const T& value); + + + template <typename P> + T& alt(const P& p) + { + typedef def::coord coord_t; + mln_precondition(this->has(p)); + + return this->data_->array_ [*(coord_t*)(&p.p_hook_())] [*((coord_t*)(&p.p_hook_()) + 1)]; + } + + + // Specific methods: + // ----------------- + + /// Read-only access to the image value located at (\p row, \p col). + const T& at_(unsigned row, unsigned col) const; + + /// Read-write access to the image value located at (\p row, \p col). + T& at_(unsigned row, unsigned col); + + /// Give the number of rows. + unsigned nrows() const; + + /// Give the number of columns. + unsigned ncols() const; + + + + /// Give the border thickness. + unsigned border() const; + + /// Give the number of elements (points including border ones). + unsigned nelements() const; + + /// Read-only access to the image value located at index \p i. + const T& element(unsigned i) const; + + /// Read-write access to the image value located at index \p i. + T& element(unsigned i); + + /// Give the delta-index corresponding to the delta-point \p dp. + int delta_index(const dpoint2d& dp) const; + + /// Give the point corresponding to the index \p i. + point2d point_at_index(unsigned i) const; + + + // Hooks + + /// Give a hook to the value buffer. + const std::fstream* buffer() const; + + /// Give a hook to the value buffer. + std::fstream* buffer(); + + /// Give a hook to the offset for accessing data. + const std::streampos pos_() const; + + /// Give a hook to the offset for accessing data. + std::streampos pos_(); + + + /// Resize image border with new_border. + void resize_(unsigned new_border); + }; + + + + // Forward declaration + + template <typename T> + void init_(tag::border_t, unsigned& bdr, const tiled2d<T>& model); + + template <typename T, typename J> + void init_(tag::image_t, mln::tiled2d<T>& target, const J& model); + + + +# ifndef MLN_INCLUDE_ONLY + + // init_ + + template <typename T> + inline + void init_(tag::border_t, unsigned& bdr, const tiled2d<T>& model) + { + bdr = model.border(); + } + + template <typename T, typename J> + inline + void init_(tag::image_t, tiled2d<T>& target, const J& model) + { + box2d b; + init_(tag::bbox, b, model); + unsigned bdr; + init_(tag::border, bdr, model); + target.init_(b, bdr); + } + + + // internal::data< tiled2d<T> > + + namespace internal + { + template <typename T> + inline + data< tiled2d<T> >::data(const box2d& b, unsigned bdr) + : b_ (b), + bdr_ (bdr) + { + allocate_(); + } + + /*template <typename T> + inline + data< tiled2d<T> >::data(const std::string& filename) + { + // FIXME + //b_ = make::box2d(buffer_.rows(), buffer_.columns()); + }*/ + + template <typename T> + inline + data< tiled2d<T> >::~data() + { + deallocate_(); + } + + template <typename T> + inline + void + data< tiled2d<T> >::update_vb_() + { + vb_.pmin() = b_.pmin() - dpoint2d(all_to(bdr_)); + vb_.pmax() = b_.pmax() + dpoint2d(all_to(bdr_)); + } + + template <typename T> + inline + void + data< tiled2d<T> >::allocate_() + { + update_vb_(); +// unsigned +// nr = vb_.len(0), +// nc = vb_.len(1); +// buffer_ = new T[nr * nc]; +// array_ = new T*[nr]; +// T* buf = buffer_ - vb_.pmin().col(); +// for (unsigned i = 0; i < nr; ++i) +// { +// array_[i] = buf; +// buf += nc; +// } +// array_ -= vb_.pmin().row(); + mln_postcondition(vb_.len(0) == b_.len(0) + 2 * bdr_); + mln_postcondition(vb_.len(1) == b_.len(1) + 2 * bdr_); + } + + template <typename T> + inline + void + data< tiled2d<T> >::deallocate_() + { +// if (f_) +// delete(f_); + } + + template <typename T> + inline + void + data< tiled2d<T> >::swap_(data< tiled2d<T> >& other_) + { + data< tiled2d<T> > self_ = *this; + *this = other_; + other_ = self_; + } + + template <typename T> + inline + void + data< tiled2d<T> >::reallocate_(unsigned new_border) + { + data< tiled2d<T> >& tmp = *(new data< tiled2d<T> >(this->b_, new_border)); + this->swap_(tmp); + } + + + } // end of namespace mln::internal + + + // tiled2d<T> + + template <typename T> + inline + tiled2d<T>::tiled2d() + { + } + + template <typename T> + inline + tiled2d<T>::tiled2d(const box2d& b, unsigned bdr) + { + init_(b, bdr); + } + + template <typename T> + inline + void + tiled2d<T>::init_(const box2d& b, unsigned bdr) + { + mln_precondition(! this->is_valid()); + this->data_ = new internal::data< tiled2d<T> >(b, bdr); + } + + /*template <typename T> + inline + tiled2d<T>::tiled2d(const std::string& filename) + { + init_(filename); + } + + template <typename T> + inline + void + tiled2d<T>::init_(const std::string& filename) + { + mln_precondition(! this->is_valid()); + this->data_ = new internal::data< tiled2d<T> >(filename); + }*/ + + template <typename T> + inline + const box2d& + tiled2d<T>::domain() const + { + mln_precondition(this->is_valid()); + return this->data_->b_; + } + + template <typename T> + inline + const box2d& + tiled2d<T>::bbox() const + { + mln_precondition(this->is_valid()); + return this->data_->b_; + } + + template <typename T> + inline + bool + tiled2d<T>::has(const point2d& p) const + { + mln_precondition(this->is_valid()); + return this->data_->vb_.has(p); + } + + template <typename T> + inline + const T& + tiled2d<T>::operator()(const point2d& p) const + { + return read_(p); + } + + template <typename T> + inline + mln::value::proxy< tiled2d<T> > + tiled2d<T>::operator()(const point2d& p) + { + mln::value::proxy<tiled2d> prx(*this, p); + return prx; + } + + template <typename T> + inline + const T& + tiled2d<T>::read_(const point2d& p) const + { + std::cout << "setting at point " << p << std::endl; // DELETEME + return this->data_->value_; + } + + template <typename T> + inline + void + tiled2d<T>::write_(const point2d& p, const T& value) + { + std::cout << "setting value " << value << " at point " << p << std::endl; // DELETEME + /*this->data_->pixel_cache = this->data_->buffer_.getPixels(p.col(), p.row(), p.col(), p.row()); + *(this->data_->pixel_cache) = Magick::ColorRGB(256 - value.red(), + 256 - value.green(), + 256 - value.blue());*/ + } + + + // Specific methods: + + template <typename T> + inline + const T& + tiled2d<T>::at_(unsigned row, unsigned col) const + { + mln_precondition(this->has(point2d(row, col))); + //FIXME: use the cache Luke. + this->data_->pixel_cache = this->data_->buffer_.getPixels(col, row, col, row); + this->data_->value_.red() = this->data_->pixel_cache->red % 256; + this->data_->value_.green() = this->data_->pixel_cache->green % 256; + this->data_->value_.blue() = this->data_->pixel_cache->blue % 256; + return this->data_->value_; + } + + template <typename T> + inline + T& + tiled2d<T>::at_(unsigned row, unsigned col) + { + mln_precondition(this->has(point2d(row, col))); + //FIXME: use the cache Luke. + this->data_->pixel_cache = this->data_->buffer_.getPixels(col, row, col, row); + this->data_->value_.red() = this->data_->pixel_cache->red % 256; + this->data_->value_.green() = this->data_->pixel_cache->green % 256; + this->data_->value_.blue() = this->data_->pixel_cache->blue % 256; + return this->data_->value_; + } + + template <typename T> + inline + unsigned + tiled2d<T>::nrows() const + { + mln_precondition(this->is_valid()); + return this->data_->b_.len(0); + } + + template <typename T> + inline + unsigned + tiled2d<T>::ncols() const + { + mln_precondition(this->is_valid()); + return this->data_->b_.len(1); + } + + + // Hooks. + + template <typename T> + inline + const std::fstream* + tiled2d<T>::buffer() const + { + mln_precondition(this->is_valid()); + return this->data_->f_; + } + + template <typename T> + inline + std::fstream* + tiled2d<T>::buffer() + { + mln_precondition(this->is_valid()); + return this->data_->f_; + } + + template <typename T> + inline + const std::streampos + tiled2d<T>::pos_() const + { + mln_precondition(this->is_valid()); + return this->data_->pos_; + } + + template <typename T> + inline + std::streampos + tiled2d<T>::pos_() + { + mln_precondition(this->is_valid()); + return this->data_->pos_; + } + + +# endif // ! MLN_INCLUDE_ONLY + +} // end of namespace mln + + + +# include <mln/core/trait/pixter.hh> +# include <mln/core/dpoints_pixter.hh> +# include <mln/core/pixter2d.hh> +// # include <mln/core/w_window.hh> + + +namespace mln +{ + + namespace trait + { + + // pixter + + template <typename T> + struct fwd_pixter< tiled2d<T> > + { + typedef fwd_pixter2d< tiled2d<T> > ret; + }; + + template <typename T> + struct fwd_pixter< const tiled2d<T> > + { + typedef fwd_pixter2d< const tiled2d<T> > ret; + }; + + template <typename T> + struct bkd_pixter< tiled2d<T> > + { + typedef bkd_pixter2d< tiled2d<T> > ret; + }; + + template <typename T> + struct bkd_pixter< const tiled2d<T> > + { + typedef bkd_pixter2d< const tiled2d<T> > ret; + }; + + // qixter + + template <typename T, typename W> + struct fwd_qixter< tiled2d<T>, W > + { + typedef dpoints_fwd_pixter< tiled2d<T> > ret; + }; + + template <typename T, typename W> + struct fwd_qixter< const tiled2d<T>, W > + { + typedef dpoints_fwd_pixter< const tiled2d<T> > ret; + }; + + template <typename T, typename W> + struct bkd_qixter< tiled2d<T>, W > + { + typedef dpoints_bkd_pixter< tiled2d<T> > ret; + }; + + template <typename T, typename W> + struct bkd_qixter< const tiled2d<T>, W > + { + typedef dpoints_bkd_pixter< const tiled2d<T> > ret; + }; + + // nixter + + template <typename T, typename N> + struct fwd_nixter< tiled2d<T>, N > + { + typedef dpoints_fwd_pixter< tiled2d<T> > ret; + }; + + template <typename T, typename N> + struct fwd_nixter< const tiled2d<T>, N > + { + typedef dpoints_fwd_pixter< const tiled2d<T> > ret; + }; + + template <typename T, typename N> + struct bkd_nixter< tiled2d<T>, N > + { + typedef dpoints_bkd_pixter< tiled2d<T> > ret; + }; + + template <typename T, typename N> + struct bkd_nixter< const tiled2d<T>, N > + { + typedef dpoints_bkd_pixter< const tiled2d<T> > ret; + }; + + } // end of namespace mln::trait + +} // end of namespace mln + + +# include <mln/make/image.hh> + + +#endif // ! MLN_CORE_IMAGE_TILED2D_HH Index: trunk/milena/sandbox/fabien/mln/data/fast_median.hh =================================================================== --- trunk/milena/sandbox/fabien/mln/data/fast_median.hh (revision 0) +++ trunk/milena/sandbox/fabien/mln/data/fast_median.hh (revision 4335) @@ -0,0 +1,180 @@ +// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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_DATA_FAST_MEDIAN_HH +# define MLN_DATA_FAST_MEDIAN_HH + +/*! \file + * + * \brief Fast Median filtering of an image. + * + * \todo There are implicit assumptions about input being 2D!!! + */ + +# include <mln/core/concept/image.hh> +# include <mln/core/alias/window2d.hh> +# include <mln/accu/stat/median_h.hh> + +# include <mln/win/shift.hh> +# include <mln/win/diff.hh> + +# include <mln/geom/min_col.hh> +# include <mln/geom/min_row.hh> +# include <mln/geom/max_col.hh> +# include <mln/geom/max_row.hh> + + +namespace mln +{ + + namespace data + { + + /*! Compute in \p output the median filter of image \p input by + * the window \p win. + * + * \param[in] input The image to be filtered. + * \param[in] win The window. + * \param[in,out] output The output image. + * + * \pre \p input and \p output have to be initialized. + */ + template <typename I, typename W, typename O> + void fast_median(const Image<I>& input, const Window<W>& win, + Image<O>& output); + + +# ifndef MLN_INCLUDE_ONLY + + + namespace impl + { + + template <typename I, typename W, typename O> + inline + void fast_median(const I& input, + const W& win, + O& output) + { + mln_precondition(input.is_valid()); + mln_precondition(output.is_valid()); + + def::coord + min_row = geom::min_row(input), max_row = geom::max_row(input), + min_col = geom::min_col(input), max_col = geom::max_col(input); + + window2d + win_fwd_plus = win - win::shift(win, left), + win_fwd_minus = win::shift(win, left) - win, + win_bkd_plus = win - win::shift(win, right), + win_bkd_minus = win::shift(win, right) - win, + win_bot = win - win::shift(win, up), + win_top = win::shift(win, up) - win; + + accu::stat::median_h<mln_value(I)> med; + + // initialization + + point2d p = input.domain().pmin() + up; + + mln_qixter(const I, window2d) + q_fp(input, win_fwd_plus, p), q_fm(input, win_fwd_minus, p), + q_bp(input, win_bkd_plus, p), q_bm(input, win_bkd_minus, p), + q_top(input, win_top, p), q_bot(input, win_bot, p); + + med.init(); + { + mln_qixter(const I, W) q(input, win, p); + for_all(q) + med.take(q.val()); + } + + def::coord& row = p.row(); + def::coord& col = p.col(); + bool fwd = true; + + mln_assertion(p.col() == min_col); + mln_assertion(p.row() == min_row - 1); + + for (row = min_row; row <= max_row; ++row) + { + + // "go down" + for_all(q_top) + med.untake(q_top.val()); + + for_all(q_bot) + med.take(q_bot.val()); + + output(p) = med; + + if (fwd) + // browse line fwd + while (col < max_col) + { + ++col; + for_all(q_fm) + med.untake(q_fm.val()); + for_all(q_fp) + med.take(q_fp.val()); + output(p) = med; + } + else + // browse line bkd + while (col > min_col) + { + --col; + for_all(q_bm) + med.untake(q_bm.val()); + for_all(q_bp) + med.take(q_bp.val()); + output(p) = med; + } + // change browsing + fwd = ! fwd; + } + } + + } // end of namespace mln::data::impl + + + // facade + + template <typename I, typename W, typename O> + inline + void fast_median(const Image<I>& input, const Window<W>& win, + Image<O>& output) + { + impl::fast_median(exact(input), exact(win), exact(output)); + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::data + +} // end of namespace mln + + +#endif // ! MLN_DATA_FAST_MEDIAN_HH Index: trunk/milena/sandbox/fabien/mln/canvas/browsing/snake.hh =================================================================== --- trunk/milena/sandbox/fabien/mln/canvas/browsing/snake.hh (revision 0) +++ trunk/milena/sandbox/fabien/mln/canvas/browsing/snake.hh (revision 4335) @@ -0,0 +1,128 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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_CANVAS_BROWSING_SNAKE_HH +# define MLN_CANVAS_BROWSING_SNAKE_HH + +/// \file +/// +/// Browsing in a snake-way, forward. + +# include <vector> +# include <mln/core/concept/browsing.hh> + + +namespace mln +{ + + namespace canvas + { + + namespace browsing + { + + template <typename I, typename W, typename F> + inline + mln_ch_value(I, mln_result(F)) + snake(const Image<I>& input, const Neighborhood<N>& nbh, F& functor); + + +# ifndef MLN_INCLUDE_ONLY + + template <typename I, typename W, typename F> + inline + mln_ch_value(I, mln_result(F)) + snake(const Image<I>& input_, const Neighborhood<N>& nbh, F& functor) + { + trace::entering("canvas::browsing::snake"); + + I input = exact(input_); + mln_precondition(input.is_valid()); + + // p init + f.p = f.input.bbox().pmin();// - f.dps[0]; + + std::vector< int > directions(f.moves.size(), 0); + unsigned deph = 0; + unsigned total_deph = f.moves.size() / 2 + 1; + + // initialization + f.init(); + + bool first = true; + directions[deph] = 1; + deph = total_deph - 1; + + // Call the move function (for the first point) + (f.*(f.moves[(deph - 1) * 2 - 1 + directions[deph - 1]])) (); + while (deph > 0) // If direction is empty, break + { + mln_assertion(deph <= total_deph); + mln_assertion(deph > 0); + // If f.p is near the border (we ended a direction) -> next child + if (!f.input.domain().has(f.p + + f.dps[(deph - 1) * 2 - 1 + directions[deph - 1]])) + { + // Go up the tree + deph--; + if (deph >= 1) + // Change directions + directions[deph] = directions[deph] == 1 ? 0 : 1; + continue; + } + + if (!first) + { + // Move f.p + f.p += f.dps[(deph - 1) * 2 - 1 + directions[deph - 1]]; + // Call the move function + (f.*(f.moves[(deph - 1) * 2 - 1 + directions[deph - 1]])) (); + } + else + first = false; + + if (deph != total_deph) + { + // Go down the tree + deph++; + first = true; + } + } + + trace::exiting("canvas::browsing::snake"); + } + + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::canvas::browsing + + } // end of namespace mln::canvas + +} // end of namespace mln + + +#endif // ! MLN_CANVAS_BROWSING_SNAKE_HH + Index: trunk/milena/sandbox/fabien/mln/canvas/browsing/directional.hh =================================================================== --- trunk/milena/sandbox/fabien/mln/canvas/browsing/directional.hh (revision 0) +++ trunk/milena/sandbox/fabien/mln/canvas/browsing/directional.hh (revision 4335) @@ -0,0 +1,157 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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_CANVAS_BROWSING_DIRECTIONAL_HH +# define MLN_CANVAS_BROWSING_DIRECTIONAL_HH + +/// \file +/// +/// Directional browsing of an image. + +# include <mln/core/concept/browsing.hh> +# include <mln/core/concept/image.hh> + +namespace mln +{ + + namespace canvas + { + + namespace browsing + { + + /// Browsing in a certain direction. + /// + /// This canvas browse all the point of an image 'input' of type + /// 'I' and of dimension 'dim' in the direction 'dir'. + /// + /// The functor should provide (In addition to 'input', 'I', + /// 'dim' and 'dir') three methods : + /// + /// - init() : Will be called at the beginning. + /// - next() : Will be called at each point 'p' (also provided by + /// the fonctor). + /// - final(): Will be called at the end. + /// + /// F shall features : \n + /// { \n + /// --- as types: \n + /// I; \n + /// --- as attributes: \n + /// dim; \n + /// dir; // and test dir < dim \n + /// input; \n + /// p; \n + /// --- as methods: \n + /// void init(); \n + /// void next(); \n + /// void final(); \n + /// } \n + /// + /// Example : \n + /// + /// 1 0 0 + /// 2 0 0 + /// 3 0 0 + /// + /// 4 0 0 + /// 5 0 0 + /// 6 0 0 + /// + /// 7 0 0 + /// 8 0 0 + /// 9 0 0 + /// + /// + /// + template<typename I, typename W, typename F> + inline + void + directional(const Image<I>& input, F& functor); + + +# ifndef MLN_INCLUDE_ONLY + + template <typename I, typename W, typename F> + inline + void + directional(const Image<I>& input_, F& functor) + { + trace::entering("canvas::browsing::directional"); + + const I& input = exact(input_); + + mln_precondition(f.dir < f.dim); + + mln_psite(I) + pmin = f.input.domain().pmin(), + pmax = f.input.domain().pmax(); + + f.p = pmin; + + f.init(); + + do + { + + // Browse the run + f.init_run(); + while (f.p[f.dir] <= pmax[f.dir]) + { + f.next(); + ++f.p[f.dir]; + } + f.p[f.dir] = pmin[f.dir]; + + + // Select the next run start + for (int c = F::dim - 1; c >= 0; --c) + { + if (c == int(f.dir)) + continue; + if (f.p[c] != pmax[c]) + { + ++f.p[c]; + break; + } + f.p[c] = pmin[c]; + } + + } while (f.p != pmin); + + f.final(); + + trace::exiting("canvas::browsing::directional"); + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::canvas::browsing + + } // end of namespace mln::canvas + +} // end of namespace mln + +#endif // ! MLN_CANVAS_BROWSING_DIRECTIONAL_HH Index: trunk/milena/sandbox/fabien/magick/Makefile =================================================================== --- trunk/milena/sandbox/fabien/magick/Makefile (revision 4334) +++ trunk/milena/sandbox/fabien/magick/Makefile (revision 4335) @@ -1,12 +1,14 @@ -CXX = llvm-g++ -CXXFLAGS = -DNDEBUG -O4 +CXX = g++ +CXXFLAGS = -DNDEBUG -O1 LIBS = `Magick++-config --cppflags --cxxflags --ldflags --libs` INC = -I../../../ -all: magick magick: magick.cc ${CXX} ${INC} ${LIBS} $^ -o mln_magick save: save.cc ${CXX} ${INC} ${LIBS} $^ -o magick_save + +tiled: tiled_image.cc + ${CXX} ${INC} ${LIBS} $^ -o tiled
participants (1)
-
Fabien Freling