r4515: Add disk_ima test, improve HSL operations

URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox ChangeLog: 2009-09-21 Fabien Freling <fabien.freling@lrde.epita.fr> Add disk_ima test, improve HSL operations. * fabien/igr/color/find_color.cc: Add operations on HSL values. * fabien/mln/core/image/disk_ima.hh: Implement an image directly mapped on disk. * fabien/tests/core/image/Makefile: Add `disk_ima' target. * fabien/tests/core/image/disk_ima.cc: New test file for the disk_ima class. --- igr/color/find_color.cc | 54 ++++++++++++++++++++++++++++++++++++++++++ mln/core/image/disk_ima.hh | 54 ++++++++++++++++++++++++++++++++++++++++++ tests/core/image/Makefile | 5 +++ tests/core/image/disk_ima.cc | 55 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 167 insertions(+), 1 deletion(-) Index: trunk/milena/sandbox/fabien/igr/color/find_color.cc =================================================================== --- trunk/milena/sandbox/fabien/igr/color/find_color.cc (revision 0) +++ trunk/milena/sandbox/fabien/igr/color/find_color.cc (revision 4515) @@ -0,0 +1,54 @@ +#include <mln/core/image/image2d.hh> + +#include <mln/io/ppm/all.hh> + +#include <mln/value/rgb8.hh> +#include <mln/value/hsl.hh> + +#include <mln/convert/from_to.hh> +#include <mln/data/convert.hh> + +using namespace mln; +using value::rgb8; +using value::hsl_; + + +bool +is_green(hsl_<float, float, float> value) +{ + if (value.hue() > 75 && value.hue() < 170 && + value.sat() > 0.5 && + value.lum() > 0.3 && value.lum() < 0.7) + return true; + + return false; +} + +int main(int argc, char* argv[]) +{ + if (argc != 3) + { + std::cout << "Usage: " << argv[0] << " input output" << std::endl; + return 1; + } + + image2d<rgb8> input; + io::ppm::load(input, argv[1]); + + typedef image2d<hsl_<float, float, float> > H; + H ima_hsl = data::convert(hsl_<float, float, float>(), input); + mln_piter_(H) p(ima_hsl.domain()); + for_all(p) + { + if (!is_green(ima_hsl(p))) + { + ima_hsl(p).sat() = 0.3; + ima_hsl(p).lum() = 0.3; + } + } + + image2d<rgb8> output = data::convert(rgb8(), ima_hsl); + io::ppm::save(output, argv[2]); + + return 0; +} Index: trunk/milena/sandbox/fabien/tests/core/image/disk_ima.cc =================================================================== --- trunk/milena/sandbox/fabien/tests/core/image/disk_ima.cc (revision 0) +++ trunk/milena/sandbox/fabien/tests/core/image/disk_ima.cc (revision 4515) @@ -0,0 +1,55 @@ +#include <mln/core/image/image2d.hh> +#include <mln/core/image/disk_ima.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" << std::endl; + return 1; + } + + //image2d<rgb8> ima; + disk_ima<rgb8> tiled_ima; + + //io::ppm::load(ima, argv[1]); + io::ppm::load(tiled_ima, argv[1]); + + //std::cout << "bbox: " << tiled_ima.bbox() << std::endl; + //std::cout << "file: " << tiled_ima.file_() << std::endl; + + /*point2d pt0(0, 0); + mln_assertion(tiled_ima(pt0) == ima(pt0)); + + point2d pt(0, 1); + mln_assertion(tiled_ima(pt) == ima(pt)); + + point2d pt2(1, 0); + mln_assertion(tiled_ima(pt2) == ima(pt2)); + + point2d pt3(1, 1); + mln_assertion(tiled_ima(pt3) == ima(pt3));*/ + + mln_piter_(disk_ima<rgb8>) p(tiled_ima.domain()); + for_all(p) + if (p.row() % 16 == 0) + { + //std::cout << tiled_ima(p); + tiled_ima(p) = literal::green; + //std::cout << " -> " << tiled_ima(p) << std::endl; + //mln_assertion(tiled_ima(p) == ima(p)); + } + + return 0; +} Index: trunk/milena/sandbox/fabien/tests/core/image/Makefile =================================================================== --- trunk/milena/sandbox/fabien/tests/core/image/Makefile (revision 4514) +++ trunk/milena/sandbox/fabien/tests/core/image/Makefile (revision 4515) @@ -3,7 +3,10 @@ LIBS = `Magick++-config --cppflags --cxxflags --ldflags --libs` INC = -I../../../ -I../../../../../ -all: tiled2d +all: tiled2d disk_ima tiled2d: tiled2d.cc ${CXX} ${CXXFLAGS} ${INC} $^ -o tiled2d + +disk_ima: disk_ima.cc + ${CXX} ${CXXFLAGS} ${INC} $^ -o disk_ima Index: trunk/milena/sandbox/fabien/mln/core/image/disk_ima.hh =================================================================== --- trunk/milena/sandbox/fabien/mln/core/image/disk_ima.hh (revision 0) +++ trunk/milena/sandbox/fabien/mln/core/image/disk_ima.hh (revision 4515) @@ -0,0 +1,643 @@ +// 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_DISK_IMA_HH +# define MLN_CORE_IMAGE_DISK_IMA_HH + +/// \file +/// Definition of the basic mln::disk_ima 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 disk_ima; + + + namespace internal + { + + /// Data structure for \c mln::disk_ima<T>. + template <typename T> + struct data< disk_ima<T> > + { + data(const box2d& b, unsigned bdr); + ~data(); + + std::fstream* f_; + std::streampos pos_; + std::string file_; + bool loaded_; + 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< disk_ima<T> >& other_); + void reallocate_(unsigned new_border); + }; + + } // end of namespace mln::internal + + + namespace trait + { + + template <typename T> + struct image_< disk_ima<T> > : default_image_< T, disk_ima<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 disk_ima : public internal::image_primary< T, mln::box2d, disk_ima<T> > + { + typedef internal::image_primary< T, mln::box2d, disk_ima<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< disk_ima<T> > lvalue; + + + /// Skeleton. + typedef disk_ima< tag::value_<T> > skeleton; + + + /// Constructor without argument. + disk_ima(); + + /// Constructor with a box and the border thickness (default is + /// 3). + disk_ima(const box2d& b, unsigned bdr = border::thickness); + + + /// 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< disk_ima<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 offset for accessing data. + const std::streampos& pos_() const; + + /// Give a hook to the offset for accessing data. + std::streampos& pos_(); + + /// Give a hook to the filename. + const std::string& file_() const; + + /// Give a hook to the filename. + std::string& file_(); + + + /// Resize image border with new_border. + void resize_(unsigned new_border); + }; + + + + // Forward declaration + + template <typename T> + void init_(tag::border_t, unsigned& bdr, const disk_ima<T>& model); + + template <typename T, typename J> + void init_(tag::image_t, mln::disk_ima<T>& target, const J& model); + + + +# ifndef MLN_INCLUDE_ONLY + + // init_ + + template <typename T> + inline + void init_(tag::border_t, unsigned& bdr, const disk_ima<T>& model) + { + bdr = model.border(); + } + + template <typename T, typename J> + inline + void init_(tag::image_t, disk_ima<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< disk_ima<T> > + + namespace internal + { + template <typename T> + inline + data< disk_ima<T> >::data(const box2d& b, unsigned bdr) + : b_ (b), + bdr_ (bdr) + { + allocate_(); + } + + template <typename T> + inline + data< disk_ima<T> >::~data() + { + deallocate_(); + } + + template <typename T> + inline + void + data< disk_ima<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< disk_ima<T> >::allocate_() + { + update_vb_(); + 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< disk_ima<T> >::deallocate_() + { + if (this->loaded_) + { + this->f_->close(); + } + } + + template <typename T> + inline + void + data< disk_ima<T> >::swap_(data< disk_ima<T> >& other_) + { + data< disk_ima<T> > self_ = *this; + *this = other_; + other_ = self_; + } + + template <typename T> + inline + void + data< disk_ima<T> >::reallocate_(unsigned new_border) + { + data< disk_ima<T> >& tmp = *(new data< disk_ima<T> >(this->b_, new_border)); + this->swap_(tmp); + } + + + } // end of namespace mln::internal + + + // disk_ima<T> + + template <typename T> + inline + disk_ima<T>::disk_ima() + { + } + + template <typename T> + inline + disk_ima<T>::disk_ima(const box2d& b, unsigned bdr) + { + init_(b, bdr); + } + + template <typename T> + inline + void + disk_ima<T>::init_(const box2d& b, unsigned bdr) + { + mln_precondition(! this->is_valid()); + this->data_ = new internal::data< disk_ima<T> >(b, bdr); + this->data_->loaded_ = false; + } + + template <typename T> + inline + const box2d& + disk_ima<T>::domain() const + { + mln_precondition(this->is_valid()); + return this->data_->b_; + } + + template <typename T> + inline + const box2d& + disk_ima<T>::bbox() const + { + mln_precondition(this->is_valid()); + return this->data_->b_; + } + + template <typename T> + inline + bool + disk_ima<T>::has(const point2d& p) const + { + mln_precondition(this->is_valid()); + return this->data_->vb_.has(p); + } + + template <typename T> + inline + const T& + disk_ima<T>::operator()(const point2d& p) const + { + return read_(p); + } + + template <typename T> + inline + mln::value::proxy< disk_ima<T> > + disk_ima<T>::operator()(const point2d& p) + { + mln::value::proxy<disk_ima> prx(*this, p); + return prx; + } + + template <typename T> + inline + const T& + disk_ima<T>::read_(const point2d& p) const + { + mln::disk_ima<T>* this_ = const_cast<mln::disk_ima<T>* >(this); // Trust me, I have to do this(_). + if (!this_->data_->loaded_) + { + this_->data_->f_ = new std::fstream(this->data_->file_.c_str()); + this_->data_->loaded_ = true; + } + std::streampos offset = this_->data_->pos_; + offset += (this_->ncols() * p.row() + p.col()) * sizeof(T); + this_->data_->f_->seekg(offset); + this_->data_->f_->get((char*)(&this_->data_->value_), sizeof(T) + 1); // FIXME: I don't know why + // I have to add +1. + return this_->data_->value_; + } + + template <typename T> + inline + void + disk_ima<T>::write_(const point2d& p, const T& value) + { + mln::disk_ima<T>* this_ = const_cast<mln::disk_ima<T>* >(this); // Trust me, I have to do this(_). + if (!this_->data_->loaded_) + { + this_->data_->f_ = new std::fstream(this->data_->file_.c_str()); + this_->data_->loaded_ = true; + } + std::streampos offset = this_->data_->pos_; + offset += (this_->ncols() * p.row() + p.col()) * sizeof(T); + this_->data_->f_->seekg(offset); + this_->data_->f_->write((char*)(&value), sizeof(T) + 1); // FIXME: I don't know why + // I have to add +1. + } + + + // Specific methods: + + template <typename T> + inline + const T& + disk_ima<T>::at_(unsigned row, unsigned col) const + { + mln_precondition(this->has(point2d(row, col))); + return this->data_->cache_(point2d(row, col)); + } + + template <typename T> + inline + T& + disk_ima<T>::at_(unsigned row, unsigned col) + { + mln_precondition(this->has(point2d(row, col))); + return this->data_->cache_(point2d(row, col)); + } + + template <typename T> + inline + unsigned + disk_ima<T>::nrows() const + { + mln_precondition(this->is_valid()); + return this->data_->b_.len(0); + } + + template <typename T> + inline + unsigned + disk_ima<T>::ncols() const + { + mln_precondition(this->is_valid()); + return this->data_->b_.len(1); + } + + + // Hooks. + + template <typename T> + inline + const std::streampos& + disk_ima<T>::pos_() const + { + mln_precondition(this->is_valid()); + return this->data_->pos_; + } + + template <typename T> + inline + std::streampos& + disk_ima<T>::pos_() + { + mln_precondition(this->is_valid()); + return this->data_->pos_; + } + + template <typename T> + inline + const std::string& + disk_ima<T>::file_() const + { + mln_precondition(this->is_valid()); + return this->data_->file_; + } + + template <typename T> + inline + std::string& + disk_ima<T>::file_() + { + mln_precondition(this->is_valid()); + return this->data_->file_; + } + + +# 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< disk_ima<T> > + { + typedef fwd_pixter2d< disk_ima<T> > ret; + }; + + template <typename T> + struct fwd_pixter< const disk_ima<T> > + { + typedef fwd_pixter2d< const disk_ima<T> > ret; + }; + + template <typename T> + struct bkd_pixter< disk_ima<T> > + { + typedef bkd_pixter2d< disk_ima<T> > ret; + }; + + template <typename T> + struct bkd_pixter< const disk_ima<T> > + { + typedef bkd_pixter2d< const disk_ima<T> > ret; + }; + + // qixter + + template <typename T, typename W> + struct fwd_qixter< disk_ima<T>, W > + { + typedef dpoints_fwd_pixter< disk_ima<T> > ret; + }; + + template <typename T, typename W> + struct fwd_qixter< const disk_ima<T>, W > + { + typedef dpoints_fwd_pixter< const disk_ima<T> > ret; + }; + + template <typename T, typename W> + struct bkd_qixter< disk_ima<T>, W > + { + typedef dpoints_bkd_pixter< disk_ima<T> > ret; + }; + + template <typename T, typename W> + struct bkd_qixter< const disk_ima<T>, W > + { + typedef dpoints_bkd_pixter< const disk_ima<T> > ret; + }; + + // nixter + + template <typename T, typename N> + struct fwd_nixter< disk_ima<T>, N > + { + typedef dpoints_fwd_pixter< disk_ima<T> > ret; + }; + + template <typename T, typename N> + struct fwd_nixter< const disk_ima<T>, N > + { + typedef dpoints_fwd_pixter< const disk_ima<T> > ret; + }; + + template <typename T, typename N> + struct bkd_nixter< disk_ima<T>, N > + { + typedef dpoints_bkd_pixter< disk_ima<T> > ret; + }; + + template <typename T, typename N> + struct bkd_nixter< const disk_ima<T>, N > + { + typedef dpoints_bkd_pixter< const disk_ima<T> > ret; + }; + + } // end of namespace mln::trait + +} // end of namespace mln + + +# include <mln/make/image.hh> + + +#endif // ! MLN_CORE_IMAGE_DISK_IMA_HH
participants (1)
-
Fabien Freling