* 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(a)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(a)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