
https://svn.lrde.epita.fr/svn/oln/trunk/olena Index: ChangeLog from Roland Levillain <roland@lrde.epita.fr> Extend morpher adding a look-up table (oln::morpher::with_lut). * oln/core/abstract/image/hierarchies.hh (image_hierarchy_wrt_value_wise_accessibility): New hierarchy. (image_hybrid_hierarchy_wrt_classical) (image_hierarchy_wrt_value, image_hierarchy_wrt_data_retrieval): Adjust numbers. * oln/core/abstract/image/all.hh (oln/core/abstract/image/value_wise_accessibility/hierarchy.hh): Include it. Adjust. * oln/core/abstract/image/value_wise_accessibility/hierarchy.hh: New. * oln/core/automatic/image/image_being_value_wise_random_accessible.hh: New. * oln/core/internal/fwd_viter_lut.hh, * oln/core/gen/fwd_viter_lut.hh: New. * oln/core/typedefs.hh (fwd_viter_type, mutable_fwd_viter_type) (lut_type, lut_iter_type): New virtual types declarations. * oln/core/lookup_table.hh (lookup_table): Rename the first two parameters to Orig_Value and New_Value. Add two parameters Orig_Value_Compare and New_Value_Compare, defaulting to std::less<Orig_Value> and std::less<New_Value> respectively. (lookup_table::key_type, lookup_table::data_type): Rename typedefs as... (lookup_table::orig_value_type, lookup_table::new_value_type): ...these. (lookup_table::map_type): Remove typedef. (lookup_table::orig_value_type, lookup_table::new_value_type) (lookup_table::const_iterator, lookup_table::iterator): New typedefs. Adjust signatures of methods. (lookup_table::map): Remove method. (lookup_table::begin, lookup_table::end, lookup_table::find) (lookup_table::orig_to_new_map, lookup_table::new_to_orig_map): New methods. (lookup_table::map_): Remove attributes. (lookup_table::orig_to_new_map_, lookup_table::new_to_orig_map_): New attributes. (lookup_table::add): Adjust method. * oln/morpher/with_lut.hh: Adjust. (single_vtype<morpher::with_lut<Image, Lut>, typedef_::fwd_viter_type>) (single_vtype<morpher::with_lut<Image ,Lut>, typedef_::mutable_fwd_viter_type>): New. (with_lut::lut_t, with_lut::value_t, with_lut::rvalue_t) (with_lut::psite_t): Rename typedefs as... (with_lut::lut_type, with_lut::value_type, with_lut::rvalue_type) (with_lut::psite_type): ...these. Adjust. (with_lut::fwd_viter_type, with_lut::mutable_fwd_viter_type): New typedefs. (with_lut::impl_value): New methods. (operator+ (const abstract::image<I>&, const lookup_table<K, D>&)): Turn into... (operator+ (const abstract::image<I>&, lookup_table<K, D>&)): ...this. Adjust. * tests/morphers/with_lut.cc: Augment this test. * oln/value/color/rgb.hh (rgb_<T>::operator==(const rgb_<U>&)): New operator. * TODO: New. TODO | 23 oln/core/abstract/image/all.hh | 6 oln/core/abstract/image/hierarchies.hh | 7 oln/core/abstract/image/value_wise_accessibility/hierarchy.hh | 154 +++++ oln/core/automatic/image/image_being_value_wise_random_accessible.hh | 104 +++ oln/core/gen/fwd_viter_lut.hh | 302 ++++++++++ oln/core/internal/fwd_viter_lut.hh | 171 +++++ oln/core/iterator_vtypes.hh | 2 oln/core/lookup_table.hh | 185 ++++-- oln/core/typedefs.hh | 15 oln/morpher/slice.hh | 5 oln/morpher/with_lut.hh | 101 ++- oln/value/color/rgb.hh | 14 tests/morphers/with_lut.cc | 106 ++- 14 files changed, 1093 insertions(+), 102 deletions(-) Index: tests/morphers/with_lut.cc --- tests/morphers/with_lut.cc (revision 684) +++ tests/morphers/with_lut.cc (working copy) @@ -34,17 +34,65 @@ #include <oln/debug/print.hh> -// FIXME: Remove. -using namespace oln; - +// A simple (fake) routine. template <typename I> void image_test(const oln::abstract::image<I>&) { // Do nothing. } + +/*--------------------------------------------------------------. +| Equipment of the new value type of the look-up table (rgb8). | +`--------------------------------------------------------------*/ + oln::value::color::rgb8 white(255, 255, 255); oln::value::color::rgb8 blue ( 0, 0, 255); +oln::value::color::rgb8 red (255, 0, 0); + +// We don't want to equip rgb8 with an operator<, nor to specialize +// std::less, so we pass the functor rgb8_less_t as fourth parameter +// of the look-up table. +xtd::lexi_less_t lexi_less; +struct rgb8_less_t +{ + bool operator()(const oln::value::color::rgb8& lhs, + const oln::value::color::rgb8& rhs) const + { + return lexi_less(lhs.to_vec(), rhs.to_vec()); + } +}; + +// FIXME: Move this elsewhere? +namespace oln +{ + std::ostream& + operator<< (std::ostream& ostr, value::color::rgb8 val) + { + // The static_cast are needed because components of rgb8 are + // unsigned chars, printed as a classic chars. + ostr << "(" + << static_cast<int>(val.red()) << ", " + << static_cast<int>(val.green()) << ", " + << static_cast<int>(val.blue()) + << ")"; + return ostr; + } + +} // end of namespace oln + + +/*---------------------. +| Look-up table type. | +`---------------------*/ + +typedef oln::lookup_table< unsigned, oln::value::color::rgb8, + std::less<unsigned>, rgb8_less_t > lut_t; + + +/*-------. +| Test. | +`-------*/ int main() { @@ -52,45 +100,53 @@ unsigned data[] = { 0, 1, 2, 0, 1, 2, 0, 1, 2}; - typedef image2d<unsigned> image_t; + typedef oln::image2d<unsigned> image_t; image_t ima(3, 3); - level::fill(ima, data); - debug::print(ima); + oln::level::fill(ima, data); + oln::debug::print(ima); - typedef lookup_table<unsigned, rgb8> lut_t; lut_t lut; rgb8 c(16, 6, 4); lut. add(0, blue). add(1, white). add(2, c); - std::cout << lut << std::endl; - typedef morpher::with_lut<image_t, lut_t> lutimage_t; - lutimage_t ima2 = ima + lut; + typedef oln::morpher::with_lut<image_t, lut_t> image_with_lut_t; + // FIXME: ``ima + lut'' doesn't work. Maybe a `using' statement is + // required. + image_with_lut_t ima_with_lut(ima, lut); + +#if 0 + // Disable the display to speed up the test. + std::cout << "lut = " << std::endl << ima_with_lut.lut() << std::endl; + oln::debug::print(ima_with_lut); + std::cout << std::endl; +#endif - // ima2 is an image, and can be as argument to to image routines. - image_test(ima2); + image_test(ima_with_lut); - // FIXME: To be enabled later. #if 0 - // it is value-wise accessible: - ima2.value(c) = red; + std::cout << ima_with_lut.value(c) << std::endl; #endif - // let's look at it - debug::print(ima2); + // Change a value in the LUT. + ima_with_lut.value(c) = red; + +#if 0 + // Disable the display to speed up the test. + std::cout << "lut = " << std::endl << ima_with_lut.lut() << std::endl; + oln::debug::print(ima_with_lut); std::cout << std::endl; +#endif - // it is a 2D image so we have: - point2d p(1, 1); - std::cout << "ima2(p) =" << ima2(p) << std::endl; - // or (likewise): - std::cout << "ima2.at(1, 1) =" << ima2.at(1, 1) << std::endl; + oln::point2d p(1, 2); + assert(ima_with_lut(p) == red); + assert(ima_with_lut.at(1, 2) == red); - // FIXME: To be enabled later. + // FIXME: To be enabled later, when oln::level::fill is specialized + // for abstract::mutable_image_being_value_wise_random_accessible. #if 0 - // FIXME... - level::apply(ima2, fun); // 3 ops only !!! + oln::level::apply(ima_with_lut, fun); // 3 ops only !!! #endif } Index: TODO --- TODO (revision 0) +++ TODO (revision 0) @@ -0,0 +1,23 @@ +* Renaming + +** point_accessibility + +Rename oln/core/abstract/image/accessibility +into oln/core/abstract/image/point_wise_accessibility; +rename structures as well, and adjust clients. + +** lvalue vs wvalue + +Rename lvalue (``left value'') as wvalue (``writable value'')? +(Recall that rvalue can stand for either ``right-value'' or ``readable +value'', even if the latter makes more sense). + +Or even, rename rvalue and lvalue as ro_value (read-only) and rw_value +(read-write). + + + +Local Variables: +mode: outline +ispell-local-dictionary: "american" +End: Index: oln/core/typedefs.hh --- oln/core/typedefs.hh (revision 684) +++ oln/core/typedefs.hh (working copy) @@ -90,6 +90,7 @@ // mlc_decl_typedef(iter_type); // mlc_decl_typedef(fwd_iter_type); // mlc_decl_typedef(bkd_iter_type); +// -------------------------------------------------------------------- mlc_decl_typedef(piter_type); mlc_decl_typedef(fwd_piter_type); @@ -102,7 +103,11 @@ mlc_decl_typedef(niter_type); mlc_decl_typedef(fwd_niter_type); mlc_decl_typedef(bkd_niter_type); -// -------------------------------------------------------------------- + + mlc_decl_typedef(fwd_viter_type); + mlc_decl_typedef(mutable_fwd_viter_type); + // FIXME: bkd_viter_type. + // FIXME: mutable_bkd_viter_type. /*----------------------. @@ -189,6 +194,14 @@ mlc_decl_typedef(vec_type); + /*-------------------------. + | category::lookup_table. | + `-------------------------*/ + + mlc_decl_typedef(lut_type); + mlc_decl_typedef(lut_iter_type); + + /*------------------------------------. | category::fun1 and category::fun2. | `------------------------------------*/ Index: oln/core/automatic/image/image_being_value_wise_random_accessible.hh --- oln/core/automatic/image/image_being_value_wise_random_accessible.hh (revision 0) +++ oln/core/automatic/image/image_being_value_wise_random_accessible.hh (revision 0) @@ -0,0 +1,104 @@ +// Copyright (C) 2006 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 OLN_CORE_AUTOMATIC_IMAGE_IMAGE_BEING_VALUE_WISE_RANDOM_ACCESSIBLE_HH +# define OLN_CORE_AUTOMATIC_IMAGE_IMAGE_BEING_VALUE_WISE_RANDOM_ACCESSIBLE_HH + +# include <oln/core/automatic/impl.hh> +# include <oln/morpher/tags.hh> + + +namespace oln +{ + + // Forward declaration. + namespace abstract + { + template <typename E> class image_being_value_wise_random_accessible; + template <typename E> class mutable_image_being_value_wise_random_accessible; + + } // end of namespace oln::abstract + + + namespace automatic + { + + /// Default implementation corresponding to the interface + /// oln::abstract::image_being_value_wise_random_accessible. + template <typename E, typename M> + class set_impl<abstract::image_being_value_wise_random_accessible, M, E> : + public virtual stc::any__simple<E> + { + public: + typedef oln_type_of(E, value) value_type; + typedef oln_type_of(E, fwd_viter) fwd_viter_type; + + public: + fwd_viter_type impl_value(const value_type& v) const; + }; + + + /// Default implementation corresponding to the interface + /// oln::abstract::mutable_image_being_value_wise_random_accessible. + template <typename E, typename M> + class set_impl<abstract::mutable_image_being_value_wise_random_accessible, + M, E> : + public virtual stc::any__simple<E> + { + public: + typedef oln_type_of(E, value) value_type; + typedef oln_type_of(E, fwd_viter) fwd_viter_type; + + public: + fwd_viter_type impl_value(const value_type& v); + }; + + + +# ifndef OLN_INCLUDE_ONLY + + template <typename E, typename M> + typename set_impl<abstract::image_being_value_wise_random_accessible, M, E>::fwd_viter_type + set_impl<abstract::image_being_value_wise_random_accessible, M, E>::impl_value(const typename set_impl<abstract::image_being_value_wise_random_accessible, M, E>::value_type& v) const + { + return this->exact().delegate().value(v); + } + + template <typename E, typename M> + typename set_impl<abstract::mutable_image_being_value_wise_random_accessible, M, E>::fwd_viter_type + set_impl<abstract::mutable_image_being_value_wise_random_accessible, M, E>::impl_value(const typename set_impl<abstract::mutable_image_being_value_wise_random_accessible, M, E>::value_type& v) + { + return this->exact().delegate().value(v); + } + +# endif + + } // end of namespace oln::automatic + +} // end of namespace oln + +#endif // ! OLN_CORE_AUTOMATIC_IMAGE_IMAGE_BEING_VALUE_WISE_RANDOM_ACCESSIBLE_HH Index: oln/core/iterator_vtypes.hh --- oln/core/iterator_vtypes.hh (revision 684) +++ oln/core/iterator_vtypes.hh (working copy) @@ -33,7 +33,6 @@ # include <oln/core/1d/aliases.hh> # include <oln/core/2d/aliases.hh> # include <oln/core/3d/aliases.hh> -// # include <oln/core/type_fun/slice.hh> namespace oln @@ -272,7 +271,6 @@ }; - } // end of namespace oln Index: oln/core/abstract/image/hierarchies.hh --- oln/core/abstract/image/hierarchies.hh (revision 684) +++ oln/core/abstract/image/hierarchies.hh (working copy) @@ -41,13 +41,14 @@ typedef hierarchy<abstract::image, 5> image_hierarchy_wrt_accessibility; typedef hierarchy<abstract::image, 6> image_hierarchy_wrt_mutability; typedef hierarchy<abstract::image, 7> image_hierarchy_wrt_computability; + typedef hierarchy<abstract::image, 8> image_hierarchy_wrt_value_wise_accessibility; - typedef hierarchy<abstract::image, 8> image_hybrid_hierarchy_wrt_classical; + typedef hierarchy<abstract::image, 9> image_hybrid_hierarchy_wrt_classical; // FIXME: To be continued. #if 0 - typedef hierarchy<abstract::image, 9> image_hierarchy_wrt_value; - typedef hierarchy<abstract::image, 10> image_hierarchy_wrt_data_retrieval; + typedef hierarchy<abstract::image, 10> image_hierarchy_wrt_value; + typedef hierarchy<abstract::image, 11> image_hierarchy_wrt_data_retrieval; // ... #endif Index: oln/core/abstract/image/all.hh --- oln/core/abstract/image/all.hh (revision 684) +++ oln/core/abstract/image/all.hh (working copy) @@ -40,14 +40,16 @@ # include <oln/core/abstract/image/neighborhood/hierarchy.hh> // Hierarchy 4: image w.r.t. bounding box. # include <oln/core/abstract/image/bbox/hierarchy.hh> -// Hierarchy 5: image w.r.t. accessibility. +// Hierarchy 5: image w.r.t. point accessibility. # include <oln/core/abstract/image/accessibility/hierarchy.hh> // Hierarchy 6: image w.r.t. data mutability. # include <oln/core/abstract/image/mutability/hierarchy.hh> // Hierarchy 7: image w.r.t. computability. # include <oln/core/abstract/image/computability/hierarchy.hh> +// Hierarchy 8: image w.r.t. value-wise accessibility. +# include <oln/core/abstract/image/value_wise_accessibility/hierarchy.hh> -// Hybrid hierarchy 8: image w.r.t. classical features. +// (Hybrid) hierarchy 9: image w.r.t. classical features. # include <oln/core/abstract/image/hybrid/classical.hh> #endif // ! OLN_CORE_ABSTRACT_IMAGE_ALL_HH Index: oln/core/abstract/image/value_wise_accessibility/hierarchy.hh --- oln/core/abstract/image/value_wise_accessibility/hierarchy.hh (revision 0) +++ oln/core/abstract/image/value_wise_accessibility/hierarchy.hh (revision 0) @@ -0,0 +1,154 @@ +// Copyright (C) 2006 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 OLN_CORE_ABSTRACT_IMAGE_VALUE_WISE_ACCESSIBILITY_HIERARCHY_HH +# define OLN_CORE_ABSTRACT_IMAGE_VALUE_WISE_ACCESSIBILITY_HIERARCHY_HH + +# include <mlc/logic.hh> +# include <mlc/cmp.hh> + +# include <oln/core/abstract/image.hh> +# include <oln/core/abstract/image/hierarchies.hh> +# include <oln/core/automatic/image/image_being_value_wise_random_accessible.hh> + + +namespace oln +{ + + /*----------------------------------------. + | Value-wise accessibility abstractions. | + `----------------------------------------*/ + + namespace abstract + { + + /// Image having a value-wise random accessibility. + template <typename E> + struct image_being_value_wise_random_accessible : + public virtual image<E>, + public automatic::get_impl< image_being_value_wise_random_accessible, E > + { + typedef oln_type_of(E, value) value_t; + typedef oln_type_of(E, fwd_viter) fwd_viter_t; + + + public: + // Value descriptor (read-only access). + fwd_viter_t value(const value_t& v) const; + + protected: + /// Constructor (protected, empty). + image_being_value_wise_random_accessible(); + }; + + /// Mutable image having a value-wise random accessibility. + template <typename E> + struct mutable_image_being_value_wise_random_accessible : + public virtual image_being_value_wise_random_accessible<E>, + public automatic::get_impl< mutable_image_being_value_wise_random_accessible, E > + { + typedef oln_type_of(E, value) value_t; + typedef oln_type_of(E, mutable_fwd_viter) mutable_fwd_viter_t; + + public: + using image_being_value_wise_random_accessible<E>::value; + // Value descriptor (read-write access). + mutable_fwd_viter_t value(const value_t& v); + + protected: + /// Constructor (protected, empty). + mutable_image_being_value_wise_random_accessible(); + }; + + + +# ifndef OLN_INCLUDE_ONLY + + // image_being_value_wise_random_accessible. + + template <typename E> + typename image_being_value_wise_random_accessible<E>::fwd_viter_t + image_being_value_wise_random_accessible<E>::value(const typename image_being_value_wise_random_accessible<E>::value_t& v) const + { + return this->exact().impl_value(v); + } + + template <typename E> + image_being_value_wise_random_accessible<E>::image_being_value_wise_random_accessible() + { + } + + + // mutable_image_being_value_wise_random_accessible. + + template <typename E> + typename mutable_image_being_value_wise_random_accessible<E>::mutable_fwd_viter_t + mutable_image_being_value_wise_random_accessible<E>::value(const typename mutable_image_being_value_wise_random_accessible<E>::value_t& v) + { + return this->exact().impl_value(v); + } + + template <typename E> + mutable_image_being_value_wise_random_accessible<E>::mutable_image_being_value_wise_random_accessible() + { + } + +# endif + + } // end of namespace oln::abstract + + + /*-------------------. + | Dimension switch. | + `-------------------*/ + + /* FIXME: Handle mutability. This is not easy, as, for instance an + image with LUT has no lvalue type, but can be perfectly const or + mutable. How can we deal with this? By adding a specific + vtype? */ + + /// With value-wise random accessibility ( + template <typename E> + struct case_< image_hierarchy_wrt_value_wise_accessibility, E, 1 > : + where_< mlc_is_ok(oln_type_of(E, fwd_viter)) > + { + typedef abstract::mutable_image_being_value_wise_random_accessible<E> ret; + }; + +// /// With accessibility. +// template <typename E> +// struct case_< image_hierarchy_wrt_value_wise_accessibility, E, 2 > : +// where_< mlc_and( mlc_is_ok(oln_type_of(E, fwd_viter)), +// mlc_is_ok(oln_type_of(E, lvalue)) ) > +// { +// typedef abstract::mutable_image_being_value_wise_random_accessible<E> ret; +// }; + +} // end of namespace oln + + +#endif // ! OLN_CORE_ABSTRACT_IMAGE_VALUE_WISE_ACCESSIBILITY_HIERARCHY_HH Index: oln/core/gen/fwd_viter_lut.hh --- oln/core/gen/fwd_viter_lut.hh (revision 0) +++ oln/core/gen/fwd_viter_lut.hh (revision 0) @@ -0,0 +1,302 @@ +// Copyright (C) 2006 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 OLN_CORE_GEN_FWD_VITER_LUT_HH +# define OLN_CORE_GEN_FWD_VITER_LUT_HH + +# include <oln/core/internal/fwd_viter_lut.hh> +# include <oln/core/lookup_table.hh> + +namespace oln +{ + + /*------------. + | fwd_viter. | + `------------*/ + + // Forward declaration. + template <typename Lut> class fwd_viter_lut; + + + /// Super type declaration. + template <typename Lut> + struct set_super_type< fwd_viter_lut<Lut> > + { + typedef fwd_viter_lut<Lut> self_t; + typedef internal::fwd_viter_lut<self_t> ret; + }; + + + /// Virtual types associated to oln::fwd_viter_lut<Lut>. + template <typename Lut> + struct vtypes< fwd_viter_lut<Lut> > + { + // The look-up table is immutable. + typedef const Lut lut_type; + typedef typename Lut::const_iterator lut_iter_type; + typedef typename Lut::new_value_type rvalue_type; + }; + + + /// Const forward value iterator on look-up table. + template <typename Lut> + class fwd_viter_lut : + public stc_get_supers(fwd_viter_lut<Lut>) + // Check that Lut is a look-up table. + // FIXME: an abstract::lookup_table would be useful. + { + typedef fwd_viter_lut<Lut> self_t; + typedef stc_get_super(self_t) super_t; + + public: + typedef oln_type_of(self_t, lut) lut_t; + typedef oln_type_of(self_t, rvalue) rvalue_type; + + public: + // Construct an uninitialized value iterator. + fwd_viter_lut(const Lut& lut); + // Construct an iterator pointing to value \a val. + fwd_viter_lut(const Lut& lut, const rvalue_type& val); + + // Get the value pointed by this iterator (const version). + operator rvalue_type() const; + + void print(std::ostream& ostr) const; + }; + + + template <typename Lut> + std::ostream& operator<<(std::ostream& ostr, + const fwd_viter_lut<Lut>& t); + + + +# ifndef OLN_INCLUDE_ONLY + + template <typename Lut> + fwd_viter_lut<Lut>::fwd_viter_lut(const Lut& lut) + : super_t(lut) + { + // Initialize underlying iterator (i.e., \a i_.) + this->invalidate(); + } + + template <typename Lut> + fwd_viter_lut<Lut>::fwd_viter_lut(const Lut& lut, + const typename fwd_viter_lut<Lut>::rvalue_type& val) + : super_t(lut, val) + { + // The underlying iterator is initialized by the super class. + } + + template <typename Lut> + fwd_viter_lut<Lut>::operator typename fwd_viter_lut<Lut>::rvalue_type() const + { + precondition(this->is_valid()); + return this->i_->second; + } + + template <typename Lut> + void fwd_viter_lut<Lut>::print(std::ostream& ostr) const + { + precondition(this->is_valid()); + ostr << "fwd_viter_lut<Lut> { value = " << this->i_->second << " }"; + } + + + template <typename Lut> + std::ostream& operator<<(std::ostream& ostr, + const fwd_viter_lut<Lut>& t) + { + t.print(ostr); + return ostr; + } + +# endif + + + + /*--------------------. + | mutable_fwd_viter. | + `--------------------*/ + + // Forward declaration. + template <typename Lut> class mutable_fwd_viter_lut; + + + /// Super type declaration. + template <typename Lut> + struct set_super_type< mutable_fwd_viter_lut<Lut> > + { + typedef mutable_fwd_viter_lut<Lut> self_t; + typedef internal::fwd_viter_lut<self_t> ret; + }; + + + /// Virtual types associated to oln::mutable_fwd_viter_lut<Lut>. + template <typename Lut> + struct vtypes< mutable_fwd_viter_lut<Lut> > + { + typedef Lut lut_type; + typedef typename Lut::iterator lut_iter_type; + typedef typename Lut::new_value_type rvalue_type; + typedef typename Lut::new_value_type& lvalue_type; + }; + + + /// Const forward value iterator on look-up table. + template <typename Lut> + class mutable_fwd_viter_lut : + public stc_get_supers(mutable_fwd_viter_lut<Lut>) + // Check that Lut is a look-up table. + // FIXME: an abstract::lookup_table would be useful. + { + typedef mutable_fwd_viter_lut<Lut> self_t; + typedef stc_get_super(self_t) super_t; + typedef typename Lut::orig_value_type orig_value_t; + typedef typename Lut::new_value_type new_value_t; + + public: + typedef Lut lut_t; + typedef oln_type_of(self_t, rvalue) rvalue_type; + typedef oln_type_of(self_t, lvalue) lvalue_type; + + self_t& operator=(const rvalue_type& rhs); + + public: + // Construct an uninitialized value iterator. + mutable_fwd_viter_lut(Lut& lut); + // Construct an iterator pointing to value \a val. + mutable_fwd_viter_lut(Lut& lut, const rvalue_type& val); + + // Get the value pointed by this iterator (const version). + operator rvalue_type() const; + // Get the value pointed by this iterator (mutable version). + operator lvalue_type(); + + void print(std::ostream& ostr) const; + }; + + + template <typename Lut> + std::ostream& operator<<(std::ostream& ostr, + const mutable_fwd_viter_lut<Lut>& t); + + + +# ifndef OLN_INCLUDE_ONLY + + template <typename Lut> + mutable_fwd_viter_lut<Lut>::mutable_fwd_viter_lut(Lut& lut) + : super_t(lut) + { + // Initialize underlying iterator (i.e., \a i_.) + this->invalidate(); + } + + template <typename Lut> + mutable_fwd_viter_lut<Lut>::mutable_fwd_viter_lut(Lut& lut, + const typename mutable_fwd_viter_lut<Lut>::rvalue_type& val) + : super_t(lut, val) + { + // The underlying iterator is initialized by the super class. + } + + template <typename Lut> + mutable_fwd_viter_lut<Lut>::operator typename mutable_fwd_viter_lut<Lut>::rvalue_type() const + { + precondition(this->is_valid()); + return this->i_->second; + } + + template <typename Lut> + mutable_fwd_viter_lut<Lut>::operator typename mutable_fwd_viter_lut<Lut>::lvalue_type() + { + precondition(this->is_valid()); + return this->i_->second; + } + + template <typename Lut> + mutable_fwd_viter_lut<Lut>& + mutable_fwd_viter_lut<Lut>::operator=(const typename mutable_fwd_viter_lut<Lut>::rvalue_type& rhs) + { + precondition(this->is_valid()); + + // Current ``new'' value. + new_value_t cur_new_val = this->i_->first; + + // Shortcuts. + typedef typename Lut::iterator new_iter_t; + typedef std::pair<new_iter_t, new_iter_t> new_iter_range_t; + + // Current ``original'' value(s) associated to the next ``new'' value RHS. + new_iter_range_t cur_orig_val_range = + this->lut_.new_to_orig_map().equal_range(cur_new_val); + // A temporary map where additional bindings will be stored. + typename Lut::new_to_orig_map_type additional_bindings; + + for (new_iter_t j = cur_orig_val_range.first; + j != cur_orig_val_range.second; ++j) + { + // Update the orig-to-new map (substitution). + orig_value_t orig_val = j->second; + this->lut_.orig_to_new_map()[orig_val] = rhs; + // Populate the temp map. + additional_bindings.insert(std::make_pair(rhs, orig_val)); + } + // Update the new-to-orig map (deletion). + this->lut_.new_to_orig_map().erase(cur_orig_val_range.first, + cur_orig_val_range.second); + // Update the new-to-orig map (insertion). + this->lut_.new_to_orig_map().insert(additional_bindings.begin(), + additional_bindings.end()); + return *this; + } + + template <typename Lut> + void mutable_fwd_viter_lut<Lut>::print(std::ostream& ostr) const + { + precondition(this->is_valid()); + ostr + << "mutable_fwd_viter_lut<Lut> { value = " << this->i_->second << " }"; + } + + + template <typename Lut> + std::ostream& operator<<(std::ostream& ostr, + const mutable_fwd_viter_lut<Lut>& t) + { + t.print(ostr); + return ostr; + } + +# endif + +} // end of namespace oln + + +#endif // ! OLN_CORE_GEN_FWD_VITER_LUT_HH Index: oln/core/internal/fwd_viter_lut.hh --- oln/core/internal/fwd_viter_lut.hh (revision 0) +++ oln/core/internal/fwd_viter_lut.hh (revision 0) @@ -0,0 +1,171 @@ +// Copyright (C) 2006 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 OLN_CORE_INTERNAL_FWD_VITER_LUT_HH +# define OLN_CORE_INTERNAL_FWD_VITER_LUT_HH + +# include <oln/core/abstract/iterator.hh> + + +namespace oln +{ + + namespace internal + { + // Forward declaration. + template <typename Exact> class fwd_viter_lut; + + } // end of namespace oln::internal + + + /// Super type declaration. + template <typename Exact> + struct set_super_type< internal::fwd_viter_lut<Exact> > + { + typedef internal::fwd_viter_lut<Exact> self_t; + typedef abstract::iterator<self_t> ret; + }; + + + namespace internal + { + /// Forward value iterator on look-up table (abstract + /// factorization class). + template <typename Exact> + class fwd_viter_lut : public stc_get_supers(fwd_viter_lut<Exact>) + // Check that oln_type_of(Exact, lut) is a look-up table. + // FIXME: an abstract::lookup_table would be useful. + { + typedef fwd_viter_lut<Exact> self_t; + typedef stc_get_super(self_t) super_t; + typedef oln_type_of(Exact, lut_iter) lut_iter_t; + + public: + typedef oln_type_of(Exact, lut) lut_type; + typedef oln_type_of(Exact, rvalue) rvalue_type; + + public: + /// Iterator manipulators. + /// \{ + void start(); + void next(); + void invalidate(); + bool is_valid() const; + /// \} + + protected: + // Construct an uninitialized value iterator. + fwd_viter_lut(lut_type& lut); + // Construct an iterator pointing to value \a val. + fwd_viter_lut(lut_type& lut, const rvalue_type& val); + + protected: + /// Look-up table. + lut_type& lut_; + /// Iterator on \a lut_. + lut_iter_t i_; + }; + + + template <typename Exact> + std::ostream& operator<<(std::ostream& ostr, const fwd_viter_lut<Exact>& t); + + + +# ifndef OLN_INCLUDE_ONLY + + template <typename Exact> + fwd_viter_lut<Exact>::fwd_viter_lut(typename fwd_viter_lut<Exact>::lut_type& lut) + : super_t(), + lut_(lut), + i_() + { + // Initialize underlying iterator (i.e., \a i_.) + this->invalidate(); + } + + template <typename Exact> + fwd_viter_lut<Exact>::fwd_viter_lut(typename fwd_viter_lut<Exact>::lut_type& lut, + const typename fwd_viter_lut<Exact>::rvalue_type& val) + : super_t(), + lut_(lut), + i_() + { + // Initialize underlying iterator (i.e., \a i_.) + i_ = lut_.find(val); + assert(i_ != lut_.end()); + } + + template <typename Exact> + void + fwd_viter_lut<Exact>::start() + { + i_ = lut_.begin(); + } + + template <typename Exact> + void + fwd_viter_lut<Exact>::next() + { + /* Iterate until a different key is reached. In fact, + std::multimap might not be the best choice to implement + new_to_orig_map_. Maybe a std::map binding orig_val to a + std::set of new_val's would is better?. */ + rvalue_type val = i_->first; + do + ++i_; + while (i_ != lut_.end() and i_->first == val); + } + + template <typename Exact> + void + fwd_viter_lut<Exact>::invalidate() + { + i_ = lut_.end(); + } + + template <typename Exact> + bool + fwd_viter_lut<Exact>::is_valid() const + { + return (i_ != lut_.end()); + } + + template <typename Exact> + std::ostream& operator<<(std::ostream& ostr, const fwd_viter_lut<Exact>& t) + { + t.print(ostr); + return ostr; + } + +# endif + + } // end of namespace oln::internal + +} // end of namespace oln + +#endif // ! OLN_CORE_INTERNAL_FWD_VITER_LUT_HH Index: oln/core/lookup_table.hh --- oln/core/lookup_table.hh (revision 684) +++ oln/core/lookup_table.hh (working copy) @@ -34,83 +34,196 @@ namespace oln { - template <typename Key, typename Data> + // FIXME: Document! + + template <typename Orig_Value, typename New_Value, + typename Orig_Value_Compare = std::less<Orig_Value>, + typename New_Value_Compare = std::less<New_Value> > class lookup_table { - typedef lookup_table<Key, Data> self_t; + typedef lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare> self_t; public: - typedef Key key_type; - typedef Data data_type; - typedef std::map<Key, Data> map_type; + typedef Orig_Value orig_value_type; + typedef New_Value new_value_type; + typedef std::map<Orig_Value, New_Value, Orig_Value_Compare> orig_to_new_map_type; + typedef std::multimap<New_Value, Orig_Value, New_Value_Compare> new_to_orig_map_type; + + typedef typename new_to_orig_map_type::const_iterator const_iterator; + typedef typename new_to_orig_map_type::iterator iterator; public: lookup_table(); - self_t& add (const key_type& k, const data_type& d); + self_t& add (const orig_value_type& orig_value, const new_value_type& new_value); - const data_type operator () (const key_type& key) const; + const new_value_type operator() (const orig_value_type& orig_value) const; - const map_type& map() const; + /// (Internal) iterators. + /// \{ + const_iterator begin() const; + iterator begin(); + + const_iterator end() const; + iterator end(); + /// \} + + const_iterator find(const new_value_type& val) const; + iterator find(const new_value_type& val); + + /// Accessors. + /// \{ + const orig_to_new_map_type& orig_to_new_map() const; + orig_to_new_map_type& orig_to_new_map(); + const new_to_orig_map_type& new_to_orig_map() const; + new_to_orig_map_type& new_to_orig_map(); + /// \} private: - std::map<Key, Data> map_; + orig_to_new_map_type orig_to_new_map_; + new_to_orig_map_type new_to_orig_map_; }; # ifndef OLN_INCLUDE_ONLY - template <typename Key, typename Data> - lookup_table<Key, Data>::lookup_table() : - map_() + template <typename Orig_Value, typename New_Value, + typename Orig_Value_Compare, typename New_Value_Compare> + lookup_table<Orig_Value, New_Value, + Orig_Value_Compare, New_Value_Compare>::lookup_table() : + orig_to_new_map_() { } - template <typename Key, typename Data> - lookup_table<Key, Data>& - lookup_table<Key, Data>::add (const Key& k, const Data& d) + template <typename Orig_Value, typename New_Value, + typename Orig_Value_Compare, typename New_Value_Compare> + lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>& + lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>::add (const Orig_Value& orig_value, + const New_Value& new_value) { - map_.insert(std::make_pair(k, d)); + orig_to_new_map_.insert(std::make_pair(orig_value, new_value)); + new_to_orig_map_.insert(std::make_pair(new_value, orig_value)); return *this; } - template <typename Key, typename Data> - const Data - lookup_table<Key, Data>::operator () (const Key& key) const - { - typedef typename lookup_table<Key, Data>::map_type map_t; - typename map_t::const_iterator i = map_.find(key); - // FIXME: Is this the expected behavior when the LUT has no data - // for \a key. - assert(i != map_.end()); + template <typename Orig_Value, typename New_Value, + typename Orig_Value_Compare, typename New_Value_Compare> + const New_Value + lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>::operator () (const Orig_Value& orig_value) const + { + typedef typename lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>::orig_to_new_map_type orig_to_new_map_t; + typename orig_to_new_map_t::const_iterator i = orig_to_new_map_.find(orig_value); + // FIXME: Is this the expected behavior when the LUT has no new_value + // for \a orig_value? + assert(i != orig_to_new_map_.end()); return i->second; } - template <typename Key, typename Data> - const typename lookup_table<Key, Data>::map_type& - lookup_table<Key, Data>::map() const + + template <typename Orig_Value, typename New_Value, + typename Orig_Value_Compare, typename New_Value_Compare> + typename lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>::const_iterator + lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>::begin() const + { + return new_to_orig_map_.begin(); + } + + template <typename Orig_Value, typename New_Value, + typename Orig_Value_Compare, typename New_Value_Compare> + typename lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>::iterator + lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>::begin() + { + return new_to_orig_map_.begin(); + } + + template <typename Orig_Value, typename New_Value, + typename Orig_Value_Compare, typename New_Value_Compare> + typename lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>::const_iterator + lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>::end() const + { + return new_to_orig_map_.end(); + } + + template <typename Orig_Value, typename New_Value, + typename Orig_Value_Compare, typename New_Value_Compare> + typename lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>::iterator + lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>::end() + { + return new_to_orig_map_.end(); + } + + + template <typename Orig_Value, typename New_Value, + typename Orig_Value_Compare, typename New_Value_Compare> + typename lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>::const_iterator + lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>::find(const New_Value& val) const + { + return new_to_orig_map_.find(val); + } + + template <typename Orig_Value, typename New_Value, + typename Orig_Value_Compare, typename New_Value_Compare> + typename lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>::iterator + lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>::find(const New_Value& val) + { + return new_to_orig_map_.find(val); + } + + + template <typename Orig_Value, typename New_Value, + typename Orig_Value_Compare, typename New_Value_Compare> + const typename lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>::orig_to_new_map_type& + lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>::orig_to_new_map() const + { + return orig_to_new_map_; + } + + template <typename Orig_Value, typename New_Value, + typename Orig_Value_Compare, typename New_Value_Compare> + typename lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>::orig_to_new_map_type& + lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>::orig_to_new_map() + { + return orig_to_new_map_; + } + + template <typename Orig_Value, typename New_Value, + typename Orig_Value_Compare, typename New_Value_Compare> + const typename lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>::new_to_orig_map_type& + lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>::new_to_orig_map() const + { + return new_to_orig_map_; + } + + template <typename Orig_Value, typename New_Value, + typename Orig_Value_Compare, typename New_Value_Compare> + typename lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>::new_to_orig_map_type& + lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>::new_to_orig_map() { - return map_; + return new_to_orig_map_; } # endif /// Print a look-up table. - template <typename Key, typename Data> + template <typename Orig_Value, typename New_Value, + typename Orig_Value_Compare, typename New_Value_Compare> std::ostream& - operator<< (std::ostream& ostr, const lookup_table<Key, Data>& lut); + operator<< (std::ostream& ostr, + const lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>& lut); # ifndef OLN_INCLUDE_ONLY - template <typename Key, typename Data> + template <typename Orig_Value, typename New_Value, + typename Orig_Value_Compare, typename New_Value_Compare> std::ostream& - operator<< (std::ostream& ostr, const lookup_table<Key, Data>& lut) + operator<< (std::ostream& ostr, + const lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare>& lut) { - typedef lookup_table<Key, Data> lut_t; - const typename lut_t::map_type& map = lut.map(); - for (typename lut_t::map_type::const_iterator i = map.begin (); + typedef lookup_table<Orig_Value, New_Value, Orig_Value_Compare, New_Value_Compare> lut_t; + const typename lut_t::orig_to_new_map_type& map = lut.orig_to_new_map(); + for (typename lut_t::orig_to_new_map_type::const_iterator i = map.begin (); i != map.end(); ++i) ostr << " " << i->first << " -> " << i->second << std::endl; return ostr; Index: oln/morpher/slice.hh --- oln/morpher/slice.hh (revision 684) +++ oln/morpher/slice.hh (working copy) @@ -86,6 +86,7 @@ typedef oln_type_of(Image, value) value_type; // rvalue_type: see below. + // lvalue_type: see below. // fwd_piter_type: see oln/core/iterator_vtypes.hh. // bkd_piter_type: see oln/core/iterator_vtypes.hh. @@ -140,9 +141,6 @@ /// \} - - - // piters. /// fwd_piter vtype of morpher::slice. @@ -189,6 +187,7 @@ }; + // FIXME: What about niters on morpher::slice? Index: oln/morpher/with_lut.hh --- oln/morpher/with_lut.hh (revision 684) +++ oln/morpher/with_lut.hh (working copy) @@ -30,6 +30,7 @@ # include <oln/morpher/internal/image_value_morpher.hh> # include <oln/core/lookup_table.hh> +# include <oln/core/gen/fwd_viter_lut.hh> namespace oln @@ -61,58 +62,84 @@ public: typedef mlc::true_ is_computed_type; // Value type. - typedef typename Lut::data_type value_type; + typedef typename Lut::new_value_type value_type; // Look-up table type. typedef Lut lut_type; + + // rvalue_type: see below. + // lvalue_type: undefined (see + // oln/morpher/internal/image_value_morpher.hh). + + // fwd_viter_type: see below. + // mutable_fwd_viter_type: see below. + + // FIXME: implement bkd_viter_type! + // FIXME: implement mutable_bkd_viter_type! }; // Rvalue. template <typename Image, typename Lut> struct single_vtype< morpher::with_lut<Image, Lut>, typedef_::rvalue_type > { + private: typedef morpher::with_lut<Image, Lut> self_t; + public: typedef oln_value(self_t) ret; }; - // FIXME: What about lvalue type? + /// Const forward viter vtype of morpher::with_lut. + template <typename Image, typename Lut> + struct single_vtype< morpher::with_lut<Image, Lut>, + typedef_::fwd_viter_type > + { + typedef fwd_viter_lut<Lut> ret; + }; -// // Lvalue. -// template <typename Image> -// struct single_vtype< morpher::slice<Image>, typedef_::lvalue_type > -// { -// typedef oln_type_of(Image, lvalue) ret; -// }; + /// Mutable forward viter vtype of morpher::with_lut. + template <typename Image, typename Lut> + struct single_vtype< morpher::with_lut<Image, Lut>, + typedef_::mutable_fwd_viter_type > + { + typedef mutable_fwd_viter_lut<Lut> ret; + }; /// \} + // FIXME: What about bkd_viter_type on morpher::with_lut? + + + namespace morpher { /// Look-up table addition morpher. template <typename Image, typename Lut> class with_lut : public stc_get_supers(mlc_comma_1(with_lut<Image, Lut>)) - // FIXME: Ensure oln_value(Image) == Lut::data_type? Or just let + // FIXME: Ensure oln_value(Image) == Lut::new_value_type? Or just let // the ctor check this property? { - private: typedef with_lut<Image, Lut> self_t; typedef stc_get_super(self_t) super_t; - typedef Lut lut_t; - typedef oln_type_of(self_t, value) value_t; - typedef oln_type_of(self_t, rvalue) rvalue_t; - typedef oln_type_of(self_t, psite) psite_t; - // FIXME: Useful typedef? -// typedef oln_type_of(Image, value) orig_value_t; + + public: + typedef Lut lut_type; + typedef oln_type_of(self_t, value) value_type; + typedef oln_type_of(self_t, rvalue) rvalue_type; + typedef oln_type_of(self_t, psite) psite_type; + typedef oln_type_of(self_t, fwd_viter) fwd_viter_type; + typedef oln_type_of(self_t, mutable_fwd_viter) mutable_fwd_viter_type; public: with_lut(const Image& image, const Lut& lut); - const lut_t& lut() const; + const lut_type& lut() const; - rvalue_t impl_op_read(const psite_t& p) const; + rvalue_type impl_op_read(const psite_type& p) const; - // FIXME: Implement impl_op_write() when there is value proxy? + // FIXME: Constness of this method? + fwd_viter_type impl_value(const value_type& v) const; + mutable_fwd_viter_type impl_value(const value_type& v); protected: - lut_t lut_; + lut_type lut_; }; @@ -123,13 +150,12 @@ super_t(image), lut_(lut) { - mlc::assert_equal_< oln_value(Image), typename Lut::key_type >::check(); + mlc::assert_equal_< oln_value(Image), typename Lut::orig_value_type >::check(); } template <typename Image, typename Lut> - typename with_lut<Image, Lut>::rvalue_t - with_lut<Image, Lut>:: - impl_op_read(const typename with_lut<Image, Lut>::psite_t& p) const + typename with_lut<Image, Lut>::rvalue_type + with_lut<Image, Lut>::impl_op_read(const typename with_lut<Image, Lut>::psite_type& p) const { // FIXME: What if lut_ has no value for `this->image_(p)'? At // least, document the behavior of this method (will it abort, @@ -138,7 +164,21 @@ } template <typename Image, typename Lut> - const typename with_lut<Image, Lut>::lut_t& + typename with_lut<Image, Lut>::fwd_viter_type + with_lut<Image, Lut>::impl_value(const value_type& v) const + { + return fwd_viter_type(lut_, v); + } + + template <typename Image, typename Lut> + typename with_lut<Image, Lut>::mutable_fwd_viter_type + with_lut<Image, Lut>::impl_value(const value_type& v) + { + return mutable_fwd_viter_type(lut_, v); + } + + template <typename Image, typename Lut> + const typename with_lut<Image, Lut>::lut_type& with_lut<Image, Lut>::lut() const { return lut_; @@ -149,11 +189,12 @@ } // end of namespace oln::morpher + // FIXME: Provide a version of op+ where the LUT is const? template <typename I, typename K, typename D> morpher::with_lut< I, lookup_table<K, D> > operator + (const abstract::image<I>& image, - const lookup_table<K, D>& lut); + lookup_table<K, D>& lut); # ifndef OLN_INCLUDE_ONLY @@ -161,11 +202,11 @@ template <typename I, typename K, typename D> morpher::with_lut< I, lookup_table<K, D> > operator + (const abstract::image<I>& image, - const lookup_table<K, D>& lut) + lookup_table<K, D>& lut) { - typedef lookup_table<K, D> lut_t; - mlc::assert_equal_< oln_value(I), typename lut_t::key_type >::check(); - morpher::with_lut<I, lut_t> tmp(image.exact(), lut); + typedef lookup_table<K, D> lut_type; + mlc::assert_equal_< oln_value(I), typename lut_type::orig_value_type >::check(); + morpher::with_lut<I, lut_type> tmp(image.exact(), lut); return tmp; } Index: oln/value/color/rgb.hh --- oln/value/color/rgb.hh (revision 684) +++ oln/value/color/rgb.hh (working copy) @@ -63,6 +63,10 @@ template <typename U> rgb_<T>& operator=(const rgb_<U>& rhs); + /// Op==. + template <typename U> + bool operator==(const rgb_<U>& rhs); + T red() const; T& red(); typedef T red_type; @@ -124,6 +128,16 @@ } template <typename T> + template <typename U> + bool rgb_<T>::operator==(const rgb_<U>& rhs) + { + return + val_[0] == rhs.red() and + val_[1] == rhs.green() and + val_[2] == rhs.blue(); + } + + template <typename T> T rgb_<T>::red() const { return val_[0];