URL:
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-09-21 Fabien Freling <fabien.freling(a)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