olena-2.0-18-gf8e2ffe New ``lazy'' recorder morpher in apps/morpher.

* apps/morphers/lazy_recorder.hh: New. * apps/morphers/lazy_recorder.cc: New test. * apps/morphers/Makefile.am (noinst_HEADERS): Add lazy_recorder.hh. (noinst_PROGRAMS): Add lazy_recorder. (lazy_recorder_SOURCES): New. (MOSTLYCLEANFILES): Add lena-fill-lazy??????.ppm. --- milena/ChangeLog | 12 +++ milena/apps/morphers/Makefile.am | 9 ++- .../morphers/{recorder.cc => lazy_recorder.cc} | 11 ++-- .../morphers/{recorder.hh => lazy_recorder.hh} | 76 +++++++++++++------- 4 files changed, 74 insertions(+), 34 deletions(-) copy milena/apps/morphers/{recorder.cc => lazy_recorder.cc} (88%) copy milena/apps/morphers/{recorder.hh => lazy_recorder.hh} (66%) diff --git a/milena/ChangeLog b/milena/ChangeLog index 6f9f9f0..920aac7 100644 --- a/milena/ChangeLog +++ b/milena/ChangeLog @@ -1,5 +1,17 @@ 2012-06-21 Roland Levillain <roland@lrde.epita.fr> + New ``lazy'' recorder morpher in apps/morpher. + + * apps/morphers/lazy_recorder.hh: New. + * apps/morphers/lazy_recorder.cc: New test. + * apps/morphers/Makefile.am (noinst_HEADERS): + Add lazy_recorder.hh. + (noinst_PROGRAMS): Add lazy_recorder. + (lazy_recorder_SOURCES): New. + (MOSTLYCLEANFILES): Add lena-fill-lazy??????.ppm. + +2012-06-21 Roland Levillain <roland@lrde.epita.fr> + Render the recorder morpher more generic. * apps/morphers/recorder.hh (recorder<I>::sequence): Store a diff --git a/milena/apps/morphers/Makefile.am b/milena/apps/morphers/Makefile.am index 8633933..5dbcc7e 100644 --- a/milena/apps/morphers/Makefile.am +++ b/milena/apps/morphers/Makefile.am @@ -1,4 +1,4 @@ -# Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE). +# Copyright (C) 2011, 2012 EPITA Research and Development Laboratory (LRDE). # # This file is part of Olena. # @@ -27,19 +27,22 @@ noinst_PROGRAMS = \ recorder \ recorder-bft \ recorder-wst \ - mask+recorder + mask+recorder \ + lazy_recorder -noinst_HEADERS = recorder.hh +noinst_HEADERS = recorder.hh lazy_recorder.hh mask_channel_SOURCES = mask+channel.cc recorder_SOURCES = recorder.cc recorder_bft_SOURCES = recorder-bft.cc image2d-skel.hh recorder_wst_SOURCES = recorder-wst.cc mask_recorder_SOURCES = mask+recorder.cc +lazy_recorder_SOURCES = lazy_recorder.cc MOSTLYCLEANFILES = \ lena-mask-channel.ppm \ lena-fill??????.ppm \ + lena-fill-lazy??????.ppm \ lena-bft??????.pbm \ lena-wst??????.ppm \ lena-roi-fill??????.ppm diff --git a/milena/apps/morphers/recorder.cc b/milena/apps/morphers/lazy_recorder.cc similarity index 88% copy from milena/apps/morphers/recorder.cc copy to milena/apps/morphers/lazy_recorder.cc index 86af667..f3c770e 100644 --- a/milena/apps/morphers/recorder.cc +++ b/milena/apps/morphers/lazy_recorder.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE) +// Copyright (C) 2011, 2012 EPITA Research and Development Laboratory (LRDE) // // This file is part of Olena. // @@ -24,7 +24,8 @@ // executable file might be covered by the GNU General Public License. /// \file -/// \brief Exercise a morpher recording every change in the morphed image. +/// \brief Exercise a morpher recording every change in the morphed +/// image in a lazy fashion. /// /// To produce an AVI movie from the `lena-fill*.ppm' files, use: /// @@ -43,7 +44,7 @@ #include <mln/io/ppm/load.hh> -#include "apps/morphers/recorder.hh" +#include "apps/morphers/lazy_recorder.hh" #include "apps/data.hh" @@ -55,7 +56,7 @@ int main() typedef image2d<rgb8> I; I lena = io::ppm::load<rgb8>(MLN_IMG_DIR "/tiny.ppm"); - decorated_image< I, recorder<I> > lena_rec = record(lena); + decorated_image< I, lazy_recorder<I> > lena_rec = lazy_record(lena); data::fill(lena_rec, literal::green); - ppm::save(lena_rec, "lena-fill"); + ppm::save(lena_rec, "lena-fill-lazy"); } diff --git a/milena/apps/morphers/recorder.hh b/milena/apps/morphers/lazy_recorder.hh similarity index 66% copy from milena/apps/morphers/recorder.hh copy to milena/apps/morphers/lazy_recorder.hh index a2222a3..a9e0f08 100644 --- a/milena/apps/morphers/recorder.hh +++ b/milena/apps/morphers/lazy_recorder.hh @@ -23,12 +23,16 @@ // exception does not however invalidate any other reasons why the // executable file might be covered by the GNU General Public License. -#ifndef APPS_MORPHERS_RECORDER_HH -# define APPS_MORPHERS_RECORDER_HH +#ifndef APPS_MORPHERS_LAZY_RECORDER_HH +# define APPS_MORPHERS_LAZY_RECORDER_HH /// \file -/// \brief Morpher recording every change in the morphed image, -/// storing snapshots of the morphed image at each write operation. +/// \brief Morpher recording every change in the morphed image in a +/// lazy fashion, storing each write operation (i.e., the (site, +/// value) pairs). +/// +/// The data recorded by this morpher can thus be used to ``replay'' +/// the set of changes applied to an image. /// /// \todo Split and move this into the library? @@ -51,22 +55,22 @@ // Forward declaration. -template <typename I> struct recorder; +template <typename I> struct lazy_recorder; /* FIXME: mln::decorated_image lacks a proper definition of properties! (see mln/core/image/imorph/decorated_image.hh). We use the following (minimal) set of properties as a workaround for the - recorder decoration. */ + lazy_recorder decoration. */ namespace mln { namespace trait { template <typename I> - struct image_< decorated_image< I, recorder<I> > > + struct image_< decorated_image< I, lazy_recorder<I> > > : default_image_morpher< I, mln_value(I), - decorated_image< I, recorder<I> > > + decorated_image< I, lazy_recorder<I> > > { typedef trait::image::category::identity_morpher category; @@ -80,24 +84,37 @@ namespace mln } // end of namespace mln -// Recorder. +// ``Lazy'' recorder. template <typename I> -struct recorder +struct lazy_recorder { + lazy_recorder() + { + } + + lazy_recorder(mln::Image<I>& ima) + : initial(mln::duplicate(ima)) + { + } + void reading(const I&, const mln_psite(I)&) const { // N/A. } - void writing(I& ima, const mln_psite(I)&, const mln_value(I)&) + void writing(I&, const mln_psite(I)& p, const mln_value(I)& v) { - sequence.push_back(mln::duplicate(ima)); + sequence.push_back(std::make_pair(p, v)); } - std::vector<mln_concrete(I)> sequence; + /// The initial image. + mln_concrete(I) initial; + /// The sequence of changes (list of (psite, value) pairs). + // Make it a tracked_ptr to avoid costly copy operations? + std::vector< std::pair<mln_psite(I), mln_value(I)> > sequence; }; -/* Skeleton of an image decorated with a recorder. +/* Skeleton of an image decorated with a lazy_recorder. Initialy, I (Roland) wanted to add this to mln/trait/ch_value.hh: @@ -108,14 +125,14 @@ struct recorder typedef M< mln_ch_value(I, V), D > ret; }; - However, this would not work in the case of the recorder since the + However, this would not work in the case of the lazy_recorder since the type D of the data attached to the image (of type I) has to be changed as well. Indeed the initial decoration contains a sequence of images of type I, which should be changed into a sequence of images of type mln_ch_value(I, V). There are several option to improve this. One is to create a - ch_value trait for data/decorations such as `recorder<I>'. Another + ch_value trait for data/decorations such as `lazy_recorder<I>'. Another one is to refine the skeleton of decorated_image<I, D> to have it convey the type the data stored in the decoration, e.g, changing @@ -128,7 +145,7 @@ struct recorder but this seems overly complicated. The workaround chosen here is very local, and address the very - specific case of decorated_image< I, recorder<I> >. */ + specific case of decorated_image< I, lazy_recorder<I> >. */ namespace mln { @@ -138,11 +155,11 @@ namespace mln { template < typename I, typename V > struct ch_value_< decorated_image< tag::image_<I>, - tag::data_< recorder<I> > >, + tag::data_< lazy_recorder<I> > >, V > { typedef decorated_image< mln_ch_value(I, V), - recorder< mln_ch_value(I, V) > > ret; + lazy_recorder< mln_ch_value(I, V) > > ret; }; } // end namespace mln::trait::impl @@ -153,10 +170,10 @@ namespace mln // Helper. template <typename I> inline -mln::decorated_image< I, recorder<I> > -record(mln::Image<I>& ima) +mln::decorated_image< I, lazy_recorder<I> > +lazy_record(mln::Image<I>& ima) { - return mln::decorate(ima, recorder<I>()); + return mln::decorate(ima, lazy_recorder<I>(ima)); } @@ -166,17 +183,24 @@ namespace ppm template <typename I> inline void - save(const mln::decorated_image< I, recorder<I> >& rec, + save(const mln::decorated_image< I, lazy_recorder<I> >& rec, const std::string& prefix) { + mln_concrete(I) frame = mln::duplicate(rec.decoration().initial); for (size_t i = 0; i < rec.decoration().sequence.size(); ++i) { std::stringstream s; s << std::setfill ('0') << std::setw (6) << i; - mln::io::ppm::save(rec.decoration().sequence[i], - prefix + s.str() + ".ppm"); + mln::io::ppm::save(frame, prefix + s.str() + ".ppm"); + // Apply the I-th change to the next frame. + // + // Changes are applied after the I-th image has been written, + // to mimic the behavior of the original recorder morpher (see + // recorder.hh). + frame(rec.decoration().sequence[i].first) = + rec.decoration().sequence[i].second; } } } -#endif // ! APPS_MORPHERS_RECORDER_HH +#endif // ! APPS_MORPHERS_LAZY_RECORDER_HH -- 1.7.2.5
participants (1)
-
Roland Levillain