milena r1343: Add fi_adaptor class to interact with Free Image

URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena ChangeLog: 2007-10-16 Matthieu Garrigues <garrigues@lrde.epita.fr> Add fi_adaptor class to interact with Free Image. * mln/core/fi_adaptor.hh: The fi_adaptor class. * tests/fi_adaptor.cc: An example of use. * mln/display/color_pretty.hh: Fix to color more values. * mln/display/save.hh: Nothing * mln/value/rgb.hh: Disable dangerous constructor. --- mln/core/fi_adaptor.hh | 456 ++++++++++++++++++++++++++++++++++++++++++++ mln/display/color_pretty.hh | 24 ++ mln/display/save.hh | 1 mln/value/rgb.hh | 16 - tests/fi_adaptor.cc | 79 +++++++ 5 files changed, 567 insertions(+), 9 deletions(-) Index: trunk/milena/tests/fi_adaptor.cc =================================================================== --- trunk/milena/tests/fi_adaptor.cc (revision 0) +++ trunk/milena/tests/fi_adaptor.cc (revision 1343) @@ -0,0 +1,79 @@ +// Copyright (C) 2007 EPITA Research and Development Laboratory +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to +// produce an executable, this file does not by itself cause the +// resulting executable to be covered by the GNU General Public +// License. This exception does not however invalidate any other +// reasons why the executable file might be covered by the GNU General +// Public License. + +/*! \file tests/fi_adaptor.cc + * + * \brief Test on mln::fi_adaptor. + */ + +#include <mln/core/fi_adaptor.hh> +#include <mln/core/image2d.hh> +#include <mln/win/rectangle2d.hh> + +#include <mln/value/int_u8.hh> + +#include <mln/level/paste.hh> +#include <mln/level/median.hh> + +#include <mln/display/show.hh> +#include <mln/display/save.hh> + +#include <FreeImagePlus.h> + + +using namespace mln; + +int main() +{ + using typename value::int_u8; + +#ifdef FREEIMAGE_LIB + //FIXME : is it necessary?? + FreeImage_Initialise(); +#endif // FREEIMAGE_LIB + + win::rectangle2d rect(51, 51); + + fi_adaptor< image2d<int_u8> > adaptor; + + adaptor.load("../img/lena.pgm"); + + image2d<int_u8> ima(adaptor.domain()); + + level::median(adaptor, rect, ima); + + level::paste(ima, adaptor); + + display::save (adaptor); + display::show (adaptor, "xv"); + + // call this ONLY when linking with FreeImage as a static library +#ifdef FREEIMAGE_LIB + FreeImage_DeInitialise(); +#endif // FREEIMAGE_LIB + +} Index: trunk/milena/mln/core/fi_adaptor.hh =================================================================== --- trunk/milena/mln/core/fi_adaptor.hh (revision 0) +++ trunk/milena/mln/core/fi_adaptor.hh (revision 1343) @@ -0,0 +1,456 @@ +// Copyright (C) 2007 EPITA Research and Development Laboratory +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to +// produce an executable, this file does not by itself cause the +// resulting executable to be covered by the GNU General Public +// License. This exception does not however invalidate any other +// reasons why the executable file might be covered by the GNU General +// Public License. + +#ifndef MLN_CORE_FI_ADAPTOR_HH +# define MLN_CORE_FI_ADAPTOR_HH + + +/*! \file mln/core/image2d.hh + * + * \brief Definition of the fi_adaptor image class. This class aim + * to use the fipImage class (Main FreeImagePlus class) thought one of + * our class. Then we can pass image data as our algorithms and + * FreeImagePlus's ones. + * + * For compatibility reasons, images from FreeImage library which + * doesn't take more than 7 are converted to 8 bits. + * + * + * COMPILATION: + * If you need this class you will need to install FreeImagePlus then + * compile you software with the flag -lfreeimageplus. + * + */ + + +# include <mln/core/internal/image_primary.hh> +# include <mln/core/box2d.hh> +# include <mln/core/line_piter.hh> +# include <mln/value/set.hh> + +# include <FreeImagePlus.h> + +namespace mln +{ + // Fwd decl. + template <typename I> struct fi_adaptor; + + namespace internal + { + template <typename I> + struct data_< fi_adaptor<I> > + { + data_(); + ~data_(); + + fipImage fi_ima_; + bool fi_ima_loaded; + + mln_value(I)* buffer_; + mln_value(I)** array_; + + box2d b_; // theoretical box + + void sync_with_adaptee_(); + void deallocate_(); + void swap_(data_< fi_adaptor<I> >& other_); + }; + + } // end of namespace mln::internal + + + + namespace trait + { + + template <typename I> + struct image_< fi_adaptor<I> > : default_image_< mln_value(I), fi_adaptor<I> > + { + typedef trait::image::category::primary category; + + typedef trait::image::access::random access; + typedef trait::image::space::two_d space; + typedef trait::image::size::regular size; + typedef trait::image::support::aligned support; + + typedef trait::image::border::none border; + typedef trait::image::data::raw data; + typedef trait::image::io::read_write io; + typedef trait::image::speed::fast speed; + }; + + } // end of namespace mln::trait + + + template <typename I> + struct fi_adaptor : public internal::image_primary_< box2d, fi_adaptor<I> > + { + // Warning: just to make effective types appear in Doxygen: + typedef box2d pset; + typedef point2d psite; + typedef point2d point; + typedef dpoint2d dpoint; + typedef mln_fwd_piter(box2d) fwd_piter; + typedef mln_bkd_piter(box2d) bkd_piter; + typedef line_piter_<point> line_piter; + // End of warning. + + /// Typedef T. + typedef mln_value(I) T; + + /// Value associated type. + typedef T value; + + /// Return type of read-only access. + typedef const T& rvalue; + + /// Return type of read-write access. + typedef T& lvalue; + + /// Skeleton. + typedef fi_adaptor< tag::value_<T> > skeleton; + + /// Value_Set associated type. + typedef mln::value::set<T> vset; + + + /// Constructor without argument. + fi_adaptor(); + + /// Constructor with a fipImage + fi_adaptor(fipImage& ima); + + /// Initialize an empty image. + void init_(); + + /// Give the set of values of the image. + const vset& values() const; + + /// Give the definition domain. + const box2d& domain() const; + + /// Give the number of cells. + std::size_t ncells() 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. + T& operator()(const point2d& p); + + /// Read-only access to the image value located at offset \p o. + const T& operator[](unsigned o) const; + + /// Read-write access to the image value located at offset \p o. + T& operator[](unsigned o); + + /// Read-only access to the image value located at (\p row, \p col). + const T& at(int row, int col) const; + + /// Read-write access to the image value located at (\p row, \p col). + T& at(int row, int col); + + + /// Fast Image method + + /// Give the offset corresponding to the delta-point \p dp. + int offset(const dpoint2d& dp) const; + + /// Give the point corresponding to the offset \p o. + point2d point_at_offset(unsigned o) const; + + /// Give a hook to the value buffer. + const T* buffer() const; + + /// Give a hook to the value buffer. + T* buffer(); + + /// \{ Access to adaptee. + fipImage& adaptee(); + const fipImage& adaptee() const; + /// \} + + /// \{ Delegatee functions to construct the image. Should be use it + /// before calling adaptee() method. + BOOL load(const char* lpszPathName, int flag = 0); + BOOL loadU(const wchar_t* lpszPathName, int flag = 0); + BOOL loadFromHandle(FreeImageIO *io, fi_handle handle, int flag = 0); + BOOL loadFromMemory(fipMemoryIO& memIO, int flag = 0); + /// \} + }; + + + // internal::data_< fi_adaptor<I> > + + namespace internal + { + template <typename I> + data_< fi_adaptor<I> >::data_() + { + } + + template <typename I> + data_< fi_adaptor<I> >::~data_() + { + deallocate_(); + } + + template <typename I> + void + data_< fi_adaptor<I> >::sync_with_adaptee_() + { + mln_precondition(fi_ima_.isValid()); + deallocate_(); + b_ = make::box2d(fi_ima_.getHeight(), + fi_ima_.getWidth()); + + unsigned + nr = fi_ima_.getHeight(), + nc = fi_ima_.getWidth(); + buffer_ = (mln_value(I)*) fi_ima_.accessPixels(); + array_ = new mln_value(I)*[nr]; + mln_value(I)* buf = buffer_; + for (unsigned i = 0; i < nr; ++i) + { + array_[i] = buf; + buf += nc; + } + } + + template <typename I> + void + data_< fi_adaptor<I> >::deallocate_() + { + if (array_) + { + delete[] array_; + array_ = 0; + } + } + + template <typename I> + void + data_< fi_adaptor<I> >::swap_(data_< fi_adaptor<I> >& other_) + { + data_< fi_adaptor<I> > self_ = *this; + *this = other_; + other_ = self_; + } + + } // end of namespace mln::internal + + + // fi_adaptor<I> + + template <typename I> + fi_adaptor<I>::fi_adaptor() + { + } + + template <typename I> + void + fi_adaptor<I>::init_() + { + this->data_ = new internal::data_< fi_adaptor<I> >(); + } + + template <typename I> + const typename fi_adaptor<I>::vset& + fi_adaptor<I>::values() const + { + return vset::the(); + } + + template <typename I> + const box2d& + fi_adaptor<I>::domain() const + { + mln_precondition(this->has_data()); + return this->data_->b_; + } + + template <typename I> + std::size_t + fi_adaptor<I>::ncells() const + { + mln_precondition(this->has_data()); + return this->data_->b_.npoints(); + } + + template <typename I> + const mln_value(I)& + fi_adaptor<I>::operator()(const point2d& p) const + { + mln_precondition(this->owns_(p)); + return this->data_->array_[this->domain().len(0) - 1 - p.row()][p.col()]; + } + + template <typename I> + mln_value(I)& + fi_adaptor<I>::operator()(const point2d& p) + { + mln_precondition(this->owns_(p)); + return this->data_->array_[this->domain().len(0) - 1 - p.row()][p.col()]; + } + + template <typename I> + const mln_value(I)& + fi_adaptor<I>::operator[](unsigned o) const + { + mln_precondition(o < ncells()); + return *(this->data_->buffer_ + o); + } + + template <typename I> + mln_value(I)& + fi_adaptor<I>::operator[](unsigned o) + { + mln_precondition(o < ncells()); + return *(this->data_->buffer_ + o); + } + + template <typename I> + const mln_value(I)& + fi_adaptor<I>::at(int row, int col) const + { + mln_precondition(this->owns_(make::point2d(row, col))); + return this->data_->array_[this->domain().len(0) - 1 - row][col]; + } + + template <typename I> + mln_value(I)& + fi_adaptor<I>::at(int row, int col) + { + mln_precondition(this->owns_(make::point2d(row, col))); + return this->data_->array_[this->domain().len(0) - 1 - row][col]; + } + + template <typename I> + const mln_value(I)* + fi_adaptor<I>::buffer() const + { + mln_precondition(this->has_data()); + return this->data_->buffer_; + } + + template <typename I> + mln_value(I)* + fi_adaptor<I>::buffer() + { + mln_precondition(this->has_data()); + return this->data_->buffer_; + } + + template <typename I> + int + fi_adaptor<I>::offset(const dpoint2d& dp) const + { + mln_precondition(this->has_data()); + int o = dp[0] * this->data_->b_.len(1) + dp[1]; + return o; + } + + template <typename I> + point2d + fi_adaptor<I>::point_at_offset(unsigned o) const + { + mln_precondition(o < ncells()); + point2d p = make::point2d(this->data_->b_.max_row() - o / this->data_->b_.len(1) - this->data_->b_.min_row(), + o % this->data_->b_.len(1) + this->data_->b_.min_col()); + mln_postcondition(& this->operator()(p) == this->data_->buffer_ + o); + + return p; + } + + template <typename I> + fipImage& + fi_adaptor<I>::adaptee() + { + mln_precondition(this->has_data()); + return this->data_->fi_ima_; + } + + template <typename I> + const fipImage& + fi_adaptor<I>::adaptee() const + { + mln_precondition(this->has_data()); + return this->data_->fi_ima_; + } + + template <typename I> + BOOL + fi_adaptor<I>::load(const char* lpszPathName, int flag) + { + init_(); + BOOL r = this->data_->fi_ima_.load(lpszPathName, flag); + if (this->data_->fi_ima_.getBitsPerPixel() < 8) + this->data_->fi_ima_.convertTo8Bits(); + this->data_->sync_with_adaptee_(); + return r; + } + + template <typename I> + BOOL + fi_adaptor<I>::loadU(const wchar_t* lpszPathName, int flag) + { + init_(); + BOOL r = this->data_->fi_ima_.loadU(lpszPathName, flag); + if (this->data_->fi_ima_.getBitsPerPixel() < 8) + this->data_->fi_ima_.convertTo8Bits(); + this->data_->sync_with_adaptee_(); + return r; + } + + template <typename I> + BOOL + fi_adaptor<I>::loadFromHandle(FreeImageIO *io, fi_handle handle, int flag) + { + init_(); + BOOL r = this->data_->fi_ima_.loadFromHandle(io, handle, flag); + if (this->data_->fi_ima_.getBitsPerPixel() < 8) + this->data_->fi_ima_.convertTo8Bits(); + this->data_->sync_with_adaptee_(); + return r; + } + + template <typename I> + BOOL + fi_adaptor<I>::loadFromMemory(fipMemoryIO& memIO, int flag) + { + init_(); + BOOL r = this->data_->fi_ima_.loadFromMemory(memIO, flag); + if (this->data_->fi_ima_.getBitsPerPixel() < 8) + this->data_->fi_ima_.convertTo8Bits(); + this->data_->sync_with_adaptee_(); + return r; + } + +} // end of namespace mln + + +#endif // ! MLN_CORE_FI_ADAPTOR_HH Index: trunk/milena/mln/value/rgb.hh =================================================================== --- trunk/milena/mln/value/rgb.hh (revision 1342) +++ trunk/milena/mln/value/rgb.hh (revision 1343) @@ -91,7 +91,7 @@ rgb<n>(); rgb<n>(equiv a); rgb<n>(enc r, enc g, enc b); - rgb<n>(enc l); + //rgb<n>(enc l); rgb<n>(const literal::white_t&); rgb<n>(const literal::black_t&); rgb<n>(const literal::blue_t&); @@ -190,13 +190,13 @@ this->c_[2] = b; } - template <unsigned n> - rgb<n>::rgb(enc l) - { - this->c_[0] = l; - this->c_[1] = l; - this->c_[2] = l; - } +// template <unsigned n> +// rgb<n>::rgb(enc l) +// { +// this->c_[0] = l; +// this->c_[1] = l; +// this->c_[2] = l; +// } template <unsigned n> rgb<n>::rgb(const literal::white_t&) Index: trunk/milena/mln/display/color_pretty.hh =================================================================== --- trunk/milena/mln/display/color_pretty.hh (revision 1342) +++ trunk/milena/mln/display/color_pretty.hh (revision 1343) @@ -56,6 +56,28 @@ namespace impl { + template <typename V> + value::rgb8 + color_value(V v) + { + //r = v * (mln_max(V) / mln_max(value::int_u8) ); + return value::rgb8(v, v, v); + } + + template <unsigned int n> + value::rgb8 + color_value(value::rgb<n> v) + { + return v; + } + + value::rgb8 + color_value(bool b) + { + value::int_u8 r = b ? 255 : 0; + return value::rgb8(r, r, r); + } + template <typename I> typename trait::image_from_mesh < mln_mesh(I), value::rgb8 >::ret @@ -72,7 +94,7 @@ mln_piter(I) p(input.domain()); for_all(p) - output(p) = value::rgb8(input(p)); + output(p) = value::rgb8(color_value(input(p))); } return output; } Index: trunk/milena/mln/display/save.hh =================================================================== --- trunk/milena/mln/display/save.hh (revision 1342) +++ trunk/milena/mln/display/save.hh (revision 1343) @@ -74,6 +74,7 @@ std::string path_tmp = tmp; io::ppm::save(out, path_tmp); + std::cout << input.id_ () << " = " << path_tmp << std::endl; map_saved_image_tmp_[(void*)input.id_ ()] = path_tmp; }
participants (1)
-
Matthieu Garrigues