Index: ChangeLog
from Damien Thivolle <damien(a)lrde.epita.fr>
* tests/morpho/tests/dilation: New.
* tests/morpho/tests/erosion: New.
* tests/level/Makefile.am: Add missing inclusions.
* oln/core/abstract/image_with_data.hh: Use resize_border for const
images.
* oln/utils/key.hh: Add md5 key implementation.
* oln/utils/key.hxx: Likewise.
* oln/utils/buffer.hh: Add md5 buffer implementation.
* oln/utils/buffer.hxx: Likewise.
* oln/utils/md5.hh: Add md5 algorithm implementation.
* oln/utils/md5.hxx: Likewise.
* oln/utils/clone.hh: Make it respect algorithm coding style.
* oln/morpho/dilation.hh: New. Classical dilation implementation
* oln/morpho/stat.hh: Replace obsolete use of ::dim by size properties.
* oln/morpho/erosion.hh: New. Classical erosion implementation
* oln/io/write_image_2d_pnm.hh: Fix binary file handling.
* oln/io/read_image_2d_pnm.hh: Likewise.
oln/core/abstract/image_with_data.hh | 4
oln/io/read_image_2d_pnm.hh | 4
oln/io/write_image_2d_pnm.hh | 1
oln/morpho/dilation.hh | 178 +++++++++++++++++++
oln/morpho/erosion.hh | 209 ++++++++++++++++++++++
oln/morpho/stat.hh | 12 -
oln/utils/buffer.hh | 127 +++++++++++++
oln/utils/buffer.hxx | 163 +++++++++++++++++
oln/utils/clone.hh | 53 +++--
oln/utils/key.hh | 122 +++++++++++++
oln/utils/key.hxx | 80 ++++++++
oln/utils/md5.hh | 241 ++++++++++++++++++++++++++
oln/utils/md5.hxx | 324 +++++++++++++++++++++++++++++++++++
tests/level/Makefile.am | 5
tests/morpho/tests/dilation | 32 +++
tests/morpho/tests/erosion | 31 +++
16 files changed, 1554 insertions(+), 32 deletions(-)
Index: tests/morpho/tests/dilation
--- tests/morpho/tests/dilation (revision 0)
+++ tests/morpho/tests/dilation (revision 0)
@@ -0,0 +1,32 @@
+#include "data.hh"
+#include <oln/utils/md5.hh>
+
+#include <oln/io/read_image.hh>
+#include <oln/basics2d.hh>
+#include <oln/morpho/dilation.hh>
+#include <oln/level/compare.hh>
+#include <ntg/all.hh>
+
+bool check()
+{
+ oln::utils::key::value_type data_key[16] =
+ {0xbf, 0x67, 0x3, 0xa1, 0x2d, 0x6c, 0xac, 0xe9,
+ 0xf3, 0x7c, 0x19, 0x4c, 0x3a, 0x3b, 0x4d, 0xaa};
+
+ oln::utils::key key(data_key);
+
+ typedef oln::image2d<ntg::bin> im_type;
+ im_type ima;
+ ima = oln::io::read(rdata("object.pbm"));
+
+ if (oln::utils::md5(oln::morpho::dilation(ima, oln::win_c8p())) == key)
+ {
+ std::cout << "OK" << std::endl;
+ return false;
+ }
+ else
+ {
+ std::cout << "FAIL" << std::endl;
+ return true;
+ }
+}
Index: tests/morpho/tests/erosion
--- tests/morpho/tests/erosion (revision 0)
+++ tests/morpho/tests/erosion (revision 0)
@@ -0,0 +1,31 @@
+#include "data.hh"
+#include <oln/utils/md5.hh>
+
+#include <oln/io/read_image.hh>
+#include <oln/basics2d.hh>
+#include <oln/morpho/erosion.hh>
+#include <oln/level/compare.hh>
+#include <ntg/all.hh>
+
+bool check()
+{
+ oln::utils::key::value_type data_key[16] =
+ {0x7c, 0x4f, 0xf, 0xc7, 0x27, 0x1, 0x98, 0x81,
+ 0xfd, 0xb, 0x2e, 0xf6, 0x1c, 0x84, 0xc9, 0x1e};
+
+ oln::utils::key key(data_key);
+
+ typedef oln::image2d<ntg::bin> im_type;
+ im_type ima;
+ ima = oln::io::read(rdata("object.pbm"));
+ if (oln::utils::md5(oln::morpho::erosion(ima, oln::win_c8p())) == key)
+ {
+ std::cout << "OK" << std::endl;
+ return false;
+ }
+ else
+ {
+ std::cout << "FAIL" << std::endl;
+ return true;
+ }
+}
Index: tests/level/Makefile.am
--- tests/level/Makefile.am (revision 92)
+++ tests/level/Makefile.am (working copy)
@@ -1,4 +1,5 @@
include ../check/Makefile.runtests
+include ../check/Makefile.check
-CLEANFILES += cc 2nd_cc connected_out lena_inverted set_level \
- set_level2 threshold_128
+
+check-local: check-runtests
Index: oln/core/abstract/image_with_data.hh
--- oln/core/abstract/image_with_data.hh (revision 92)
+++ oln/core/abstract/image_with_data.hh (working copy)
@@ -178,9 +178,9 @@
return data_ != 0;
}
- void resize_border(size_t new_border, bool copy_border = false)
+ void resize_border(size_t new_border, bool copy_border = false) const
{
- this->data_->resize_border(new_border, copy_border);
+ (const_cast<storage_type&>(*this->data_)).resize_border(new_border,
copy_border);
}
Index: oln/utils/buffer.hxx
--- oln/utils/buffer.hxx (revision 0)
+++ oln/utils/buffer.hxx (revision 0)
@@ -0,0 +1,163 @@
+// Copyright (C) 2004 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, 59 Temple Place - Suite 330, 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 OLENA_OLN_UTILS_BUFFER_HXX
+# define OLENA_OLN_UTILS_BUFFER_HXX
+
+// Ctor implementation
+inline
+buffer::buffer(): current_bit_(0),
+ data_(),
+ len1_(ntg_zero_val(value_type)),
+ len2_(ntg_zero_val(value_type)),
+ padding_appended_(false),
+ length_appended_(false)
+{
+ data_.reserve(length_);
+ data_.push_back(ntg_zero_val(value_type));
+}
+
+// add implementation
+template <class E>
+inline
+void buffer::add(const E &e, bool count)
+{
+ ntg_storage_type(E) mask = 1 << (ntg_nbits(E) - 1);
+ ntg_storage_type(E) e_cast = e;
+
+ while (mask)
+ {
+ push_back(e_cast & mask, !count);
+ mask >>= 1;
+ }
+}
+
+// push_back implementation
+inline
+void buffer::push_back(bool bit, bool is_padding)
+{
+ precondition(current_bit_ < 32);
+
+ current_bit_ += 1;
+ data_.back() *= 2;
+ if (bit)
+ data_.back() += ntg_unit_val(value_type);
+ if (current_bit_ == 32)
+ {
+ if (data_.size() == data_.capacity())
+ data_.reserve(data_.capacity() + length_);
+ current_bit_ = 0;
+ data_.push_back(ntg_zero_val(value_type));
+ }
+ if (!is_padding)
+ {
+ if (len1_ == ntg_max_val(value_type))
+ {
+ if (len2_ == ntg_max_val(value_type))
+ len2_ = ntg_unit_val(value_type);
+ else
+ len2_ += ntg_unit_val(value_type);
+ }
+ len1_ += ntg_unit_val(value_type);
+ }
+}
+
+// reorder implementation
+inline
+buffer::value_type buffer::reorder(value_type x) const
+{
+ ntg_storage_type_(value_type) r = 0;
+ ntg_storage_type_(value_type) mask = 0xFF;
+
+ for (unsigned i = 0; i < (sizeof(ntg_storage_type_(value_type))); ++i)
+ {
+ r <<= 8;
+ r |= (mask & ntg_storage_type_(value_type)(x)) >> (i * 8);
+ mask <<= 8;
+ }
+ return r;
+}
+
+// [] operator implementation
+inline
+ntg::int_u32 buffer::operator[] (unsigned n) const
+{
+ precondition(n < data_.size());
+
+ return reorder(data_[n]);
+}
+
+// append padding implementation
+inline
+void buffer::append_padding()
+{
+ push_back(true, true);
+ while (((data_.size() * 32) % 512) != 448)
+ push_back(false, true);
+ padding_appended_ = true;
+}
+
+// append_length implementation
+inline
+void buffer::append_length()
+{
+ precondition(padding_appended_);
+
+ add(reorder(len2_), false);
+ add(reorder(len1_), false);
+ length_appended_ = true;
+}
+
+// size implementation.
+inline
+unsigned buffer::size() const
+{
+ return data_.size();
+}
+
+// bit len implementation.
+inline
+unsigned buffer::bit_len() const
+{
+ return data_.size() * 32;
+}
+
+// is_append_padding implementation.
+inline
+bool buffer::is_append_padding() const
+{
+ return padding_appended_;
+}
+
+// is append_length implementation.
+inline
+bool buffer::is_append_length() const
+{
+ return length_appended_;
+}
+
+#endif // !OLENA_OLN_UTILS_BUFFER_HXX
Index: oln/utils/md5.hh
--- oln/utils/md5.hh (revision 0)
+++ oln/utils/md5.hh (revision 0)
@@ -0,0 +1,241 @@
+// Copyright (C) 2004, 2005 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, 59 Temple Place - Suite 330, 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 OLENA_OLN_UTILS_MD5_HH
+# define OLENA_OLN_UTILS_MD5_HH
+
+# include <ntg/all.hh>
+# include <vector>
+
+# include <oln/core/abstract/image_vectorialness.hh>
+# include <oln/core/properties.hh>
+# include <oln/core/abstract/piter.hh>
+
+# include <oln/utils/key.hh>
+# include <oln/utils/buffer.hh>
+
+namespace oln {
+ namespace utils {
+ /*!
+ ** \brief Class used to compute a MD5 digest.
+ */
+ class MD5
+ {
+ public:
+ typedef ntg::int_u32 value_type; ///< Value to work on.
+ typedef ntg_storage_type_(value_type) storage_type; ///< Representation type of
value type.
+
+ /*!
+ ** \brief Constructor.
+ **
+ ** Initialization from a buffer.
+ **
+ ** \arg The buffer to use.
+ */
+ explicit MD5(buffer b);
+
+ /*!
+ ** \brief Compute the digest.
+ */
+ key execute();
+
+ /*!
+ ** \brief Generate the key.
+ **
+ ** \pre To avoid meaningless result, you should call execute before.
+ */
+ key gen_key();
+
+ protected:
+ /*!
+ ** \brief initialization of a MD5 algorithm step.
+ */
+ void sav();
+
+ /*!
+ ** \brief Round 1 of the algorithm.
+ */
+ void round1();
+
+ /*!
+ ** \brief Round 2 of the algorithm.
+ */
+ void round2();
+
+ /*!
+ ** \brief Round 3 of the algorithm.
+ */
+ void round3();
+
+ /*!
+ ** \brief Round 4 of the algorithm.
+ */
+ void round4();
+
+ /*!
+ ** \brief A step of the algorithm.
+ */
+ void step();
+
+ /*!
+ ** \brief Sub step to update a register value.
+ */
+ template <class Fun>
+ void sub_step(const Fun &fun,
+ storage_type &a,
+ const storage_type &b,
+ const storage_type &c,
+ const storage_type &d,
+ unsigned k,
+ unsigned s,
+ unsigned i);
+
+ /*!
+ ** \brief Generate a sub part of the key.
+ **
+ ** \arg v Vector of values (output).
+ ** \arg x Data to put in v.
+ ** \arg base Where to put x in v.
+ */
+ void gen_sub_key(std::vector<key::value_type> &v,
+ storage_type x,
+ unsigned base);
+
+
+ buffer buffer_; ///< The buffer to process.
+ std::vector<storage_type> X; ///< Vector of 16 words.
+ std::vector<storage_type> T; ///< Vector of 64 words.
+ unsigned current_; ///< Current position in the buffer.
+ storage_type aa; ///< Save of a.
+ storage_type bb; ///< Save of b.
+ storage_type cc; ///< Save of c.
+ storage_type dd; ///< Save of d.
+ storage_type a; ///< A register.
+ storage_type b; ///< B register.
+ storage_type c; ///< C register.
+ storage_type d; ///< D register.
+
+ /*!
+ ** \brief Functor for bit operations.
+ **
+ ** F(X,Y,Z) = XY v not(X) Z
+ */
+ struct F_
+ {
+ storage_type operator()(const storage_type &x,
+ const storage_type &y,
+ const storage_type &z) const
+ {
+ // return z ^ (x & (y ^ z));
+ return x & y | ~x & z;
+ }
+ };
+
+ F_ F;
+
+ /*!
+ ** \brief Functor for bit operations.
+ **
+ ** G(X,Y,Z) = XZ v Y not(Z)
+ */
+ struct G_
+ {
+ storage_type operator()(const storage_type &x,
+ const storage_type &y,
+ const storage_type &z) const
+ {
+ return x & z | y & ~z;
+ }
+ };
+
+ G_ G;
+
+ /*!
+ ** \brief Functor for bit operations.
+ **
+ ** H(X,Y,Z) = X xor Y xor Z
+ */
+ struct H_
+ {
+ storage_type operator()(const storage_type &x,
+ const storage_type &y,
+ const storage_type &z) const
+ {
+ return x ^ y ^ z;
+ }
+ };
+
+ H_ H;
+
+ /*!
+ ** \brief Functor for bit operations.
+ **
+ ** I(X,Y,Z) = Y xor (X v not(Z))
+ */
+ struct I_
+ {
+ storage_type operator()(const storage_type &x,
+ const storage_type &y,
+ const storage_type &z) const
+ {
+ return y ^ (x | ~z);
+ }
+ };
+
+ I_ I;
+
+ };
+
+#include <oln/utils/md5.hxx>
+
+ /*!
+ ** \brief Compute The Md5 value of an image.
+ **
+ ** \param I Exact type of the image.
+ **
+ ** \arg im Image to process.
+ **
+ ** Non vectorial image version.
+ */
+ template <class I>
+ key md5(const oln::abstract::non_vectorial_image<I> &im);
+
+ /*!
+ ** \brief Compute The Md5 value of an image.
+ **
+ ** \param I Exact type of the image.
+ **
+ ** \arg im Image to process.
+ **
+ ** Vectorial image version.
+ */
+ template <class I>
+ key md5(const oln::abstract::vectorial_image<I> &im);
+
+ } // !utils
+} // !oln
+#endif // !OLENA_OLN_UTILS_MD5_HH
Index: oln/utils/key.hh
--- oln/utils/key.hh (revision 0)
+++ oln/utils/key.hh (revision 0)
@@ -0,0 +1,122 @@
+// Copyright (C) 2004 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, 59 Temple Place - Suite 330, 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 OLENA_OLN_UTILS_KEY_HH
+# define OLENA_OLN_UTILS_KEY_HH
+# include <ntg/all.hh>
+# include <vector>
+# include <iostream>
+
+namespace oln {
+ namespace utils {
+ /*!
+ ** \brief 16 bytes key
+ **
+ ** Object to have a nice representation of a MD5 result.
+ */
+ class key
+ {
+ public:
+ typedef ntg::int_u8 value_type; ///< Used data type.
+
+ /*!
+ ** \brief Constructor used to initialize the key.
+ **
+ ** \pre There must at least 16 elements in data.
+ ** \arg data Inuput data.
+ */
+ explicit key(const std::vector<value_type> &data);
+
+ /*!
+ ** \brief Constructor used to initialize the key.
+ **
+ ** \pre There must at least 16 elements in data.
+ ** \arg data Inuput data.
+ */
+ explicit key(const value_type *data);
+
+ /*!
+ ** \brief [] operator.
+ **
+ ** \return the ith byte of the key.
+ **
+ ** \arg i Index of the byte wanted.
+ **
+ ** This is the non const version of the operator.
+ */
+ value_type &operator[](unsigned i);
+
+ /*!
+ ** \brief [] operator.
+ **
+ ** \return the ith byte of the key.
+ **
+ ** \arg i Index of the byte wanted.
+ **
+ ** This is the const version of the operator.
+ */
+ const value_type &operator[](unsigned i) const;
+
+ /*!
+ ** \brief Check equality between two keys.
+ **
+ ** \arg k Key to be compared with.
+ */
+ bool operator ==(const key &k);
+
+ /*!
+ ** \brief Check whether two key are different.
+ **
+ ** \arg k Key to be compared with.
+ */
+ bool operator !=(const key &k);
+
+ /*!
+ ** \brief Write of representation of the key on a stream.
+ **
+ ** stream Stream to put the key on.
+ ** k Key to represent.
+ */
+ friend std::ostream &operator<<(std::ostream &stream, const key
&k)
+ {
+ stream << "{";
+ for (unsigned i = 0; i < 15; ++i)
+ stream << "0x" << std::hex << k[i] << ",
";
+ stream << "0x" << std::hex << k[15] << "}";
+ return stream;
+ }
+
+
+ protected:
+ value_type data_[16]; ///< Internal data.
+ };
+
+# include <oln/utils/key.hxx>
+
+ } // !utils
+} // !oln
+#endif // !OLENA_OLN_UTILS_KEY_HH
Index: oln/utils/buffer.hh
--- oln/utils/buffer.hh (revision 0)
+++ oln/utils/buffer.hh (revision 0)
@@ -0,0 +1,127 @@
+// Copyright (C) 2004 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, 59 Temple Place - Suite 330, 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 OLENA_OLN_UTILS_BUFFER_HH
+# define OLENA_OLN_UTILS_BUFFER_HH
+
+# include <ntg/int.hh>
+# include <vector>
+
+namespace oln {
+ namespace utils {
+ /*!
+ ** \brief Buffer used for MD5 data type abstraction.
+ */
+ class buffer
+ {
+ public:
+ typedef ntg::int_u32 value_type; ///< Used data type.
+
+ /*!
+ ** \brief Initialization of data.
+ */
+ buffer();
+
+ /*!
+ ** \brief Add every bits of e in data.
+ **
+ ** \arg e Element to work on.
+ ** \arg count Tell if you want to count e size in the buffer size.
+ */
+ template <class E>
+ void add(const E &e, bool count = true);
+
+ /*!
+ ** \brief Push back a bit at the end of the buffer.
+ **
+ ** true -> push back a 1\n
+ ** false -> push back a 0\n
+ **
+ ** \arg bit Bit to push.
+ ** \arg is_padding Are you adding padding bytes ?
+ */
+ void push_back(bool bit, bool is_padding = false);
+
+ /*!
+ ** \brief Return the nth word.
+ */
+ ntg::int_u32 operator[] (unsigned n) const;
+
+ /*!
+ ** \brief Append padding bits.
+ */
+ void append_padding();
+
+ /*!
+ ** \brief Append length.
+ */
+ void append_length();
+
+ /*!
+ ** \brief Return the number of words.
+ */
+ unsigned size() const;
+
+ /*!
+ ** \brief Return the length in bits.
+ */
+ unsigned bit_len() const;
+
+ /*!
+ ** \brief Tell if the buffer has already been padded.
+ */
+ bool is_append_padding() const;
+
+ /*!
+ ** \brief Tell if the length has already been appended.
+ */
+ bool is_append_length() const;
+
+ protected:
+ /*!
+ ** \brief Change order of data in a word.
+ **
+ ** \arg x Data to reorder.
+ */
+ value_type reorder(value_type x) const;
+
+ static const unsigned length_ = 100; ///< Capacity chunk.
+ /// Number of the current bit in the current word.
+ unsigned char current_bit_;
+ std::vector<value_type> data_; ///< The buffer data.
+ value_type len1_; ///< first word length
+ value_type len2_; ///< second word length
+ bool padding_appended_; ///< Status of padding.
+ bool length_appended_; ///< Status of length appending.
+ };
+
+# include <oln/utils/buffer.hxx>
+
+ } // !utils
+} // !oln
+#endif // !OLENA_OLN_UTILS_BUFFER_HH
Index: oln/utils/md5.hxx
--- oln/utils/md5.hxx (revision 0)
+++ oln/utils/md5.hxx (revision 0)
@@ -0,0 +1,324 @@
+// Copyright (C) 2004, 2005 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, 59 Temple Place - Suite 330, 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 OLENA_OLN_UTILS_MD5_HXX
+# define OLENA_OLN_UTILS_MD5_HXX
+
+// Ctor.
+inline
+MD5::MD5(buffer b): buffer_(b),
+ X(16),
+ T(),
+ current_(0),
+ a(0x67452301),
+ b(0xefcdab89),
+ c(0x98badcfe),
+ d(0x10325476)
+ // a(0x01234567),
+ // b(0x89abcdef),
+ // c(0xfedcba98),
+ // d(0x76543210)
+{
+ precondition(buffer_.is_append_padding());
+ precondition(buffer_.is_append_length());
+ T.reserve(64);
+ T.push_back(0xd76aa478); /* 1 */
+ T.push_back(0xe8c7b756); /* 2 */
+ T.push_back(0x242070db); /* 3 */
+ T.push_back(0xc1bdceee); /* 4 */
+ T.push_back(0xf57c0faf); /* 5 */
+ T.push_back(0x4787c62a); /* 6 */
+ T.push_back(0xa8304613); /* 7 */
+ T.push_back(0xfd469501); /* 8 */
+ T.push_back(0x698098d8); /* 9 */
+ T.push_back(0x8b44f7af); /* 10 */
+ T.push_back(0xffff5bb1); /* 11 */
+ T.push_back(0x895cd7be); /* 12 */
+ T.push_back(0x6b901122); /* 13 */
+ T.push_back(0xfd987193); /* 14 */
+ T.push_back(0xa679438e); /* 15 */
+ T.push_back(0x49b40821); /* 16 */
+ T.push_back(0xf61e2562); /* 17 */
+ T.push_back(0xc040b340); /* 18 */
+ T.push_back(0x265e5a51); /* 19 */
+ T.push_back(0xe9b6c7aa); /* 20 */
+ T.push_back(0xd62f105d); /* 21 */
+ T.push_back(0x2441453); /* 22 */
+ T.push_back(0xd8a1e681); /* 23 */
+ T.push_back(0xe7d3fbc8); /* 24 */
+ T.push_back(0x21e1cde6); /* 25 */
+ T.push_back(0xc33707d6); /* 26 */
+ T.push_back(0xf4d50d87); /* 27 */
+ T.push_back(0x455a14ed); /* 28 */
+ T.push_back(0xa9e3e905); /* 29 */
+ T.push_back(0xfcefa3f8); /* 30 */
+ T.push_back(0x676f02d9); /* 31 */
+ T.push_back(0x8d2a4c8a); /* 32 */
+ T.push_back(0xfffa3942); /* 33 */
+ T.push_back(0x8771f681); /* 34 */
+ T.push_back(0x6d9d6122); /* 35 */
+ T.push_back(0xfde5380c); /* 36 */
+ T.push_back(0xa4beea44); /* 37 */
+ T.push_back(0x4bdecfa9); /* 38 */
+ T.push_back(0xf6bb4b60); /* 39 */
+ T.push_back(0xbebfbc70); /* 40 */
+ T.push_back(0x289b7ec6); /* 41 */
+ T.push_back(0xeaa127fa); /* 42 */
+ T.push_back(0xd4ef3085); /* 43 */
+ T.push_back(0x4881d05); /* 44 */
+ T.push_back(0xd9d4d039); /* 45 */
+ T.push_back(0xe6db99e5); /* 46 */
+ T.push_back(0x1fa27cf8); /* 47 */
+ T.push_back(0xc4ac5665); /* 48 */
+ T.push_back(0xf4292244); /* 49 */
+ T.push_back(0x432aff97); /* 50 */
+ T.push_back(0xab9423a7); /* 51 */
+ T.push_back(0xfc93a039); /* 52 */
+ T.push_back(0x655b59c3); /* 53 */
+ T.push_back(0x8f0ccc92); /* 54 */
+ T.push_back(0xffeff47d); /* 55 */
+ T.push_back(0x85845dd1); /* 56 */
+ T.push_back(0x6fa87e4f); /* 57 */
+ T.push_back(0xfe2ce6e0); /* 58 */
+ T.push_back(0xa3014314); /* 59 */
+ T.push_back(0x4e0811a1); /* 60 */
+ T.push_back(0xf7537e82); /* 61 */
+ T.push_back(0xbd3af235); /* 62 */
+ T.push_back(0x2ad7d2bb); /* 63 */
+ T.push_back(0xeb86d391); /* 64 */
+}
+
+// sav() implementation.
+inline
+void MD5::sav()
+{
+ for (unsigned i = 0; i < 16; ++i)
+ X[i] = buffer_[current_ + i];
+ current_ += 16;
+ aa = a;
+ bb = b;
+ cc = c;
+ dd = d;
+}
+
+// round1() implementation.
+inline
+void MD5::round1()
+{
+ sub_step(F, a, b, c, d, 0, 7, 1);
+ sub_step(F, d, a, b, c, 1, 12, 2);
+ sub_step(F, c, d, a, b, 2, 17, 3);
+ sub_step(F, b, c, d, a, 3, 22, 4);
+ sub_step(F, a, b, c, d, 4, 7, 5);
+ sub_step(F, d, a, b, c, 5, 12, 6);
+ sub_step(F, c, d, a, b, 6, 17, 7);
+ sub_step(F, b, c, d, a, 7, 22, 8);
+ sub_step(F, a, b, c, d, 8, 7, 9);
+ sub_step(F, d, a, b, c, 9, 12, 10);
+ sub_step(F, c, d, a, b, 10, 17, 11);
+ sub_step(F, b, c, d, a, 11, 22, 12);
+ sub_step(F, a, b, c, d, 12, 7, 13);
+ sub_step(F, d, a, b, c, 13, 12, 14);
+ sub_step(F, c, d, a, b, 14, 17, 15);
+ sub_step(F, b, c, d, a, 15, 22, 16);
+}
+
+// round2() implementation.
+inline
+void MD5::round2()
+{
+ sub_step(G, a, b, c, d, 1, 5, 17);
+ sub_step(G, d, a, b, c, 6, 9, 18);
+ sub_step(G, c, d, a, b, 11, 14, 19);
+ sub_step(G, b, c, d, a, 0, 20, 20);
+ sub_step(G, a, b, c, d, 5, 5, 21);
+ sub_step(G, d, a, b, c, 10, 9, 22);
+ sub_step(G, c, d, a, b, 15, 14, 23);
+ sub_step(G, b, c, d, a, 4, 20, 24);
+ sub_step(G, a, b, c, d, 9, 5, 25);
+ sub_step(G, d, a, b, c, 14, 9, 26);
+ sub_step(G, c, d, a, b, 3, 14, 27);
+ sub_step(G, b, c, d, a, 8, 20, 28);
+ sub_step(G, a, b, c, d, 13, 5, 29);
+ sub_step(G, d, a, b, c, 2, 9, 30);
+ sub_step(G, c, d, a, b, 7, 14, 31);
+ sub_step(G, b, c, d, a, 12, 20, 32);
+}
+
+// round3() implementation.
+inline
+void MD5::round3()
+{
+ sub_step(H, a, b, c, d, 5, 4, 33);
+ sub_step(H, d, a, b, c, 8, 11, 34);
+ sub_step(H, c, d, a, b, 11, 16, 35);
+ sub_step(H, b, c, d, a, 14, 23, 36);
+ sub_step(H, a, b, c, d, 1, 4, 37);
+ sub_step(H, d, a, b, c, 4, 11, 38);
+ sub_step(H, c, d, a, b, 7, 16, 39);
+ sub_step(H, b, c, d, a, 10, 23, 40);
+ sub_step(H, a, b, c, d, 13, 4, 41);
+ sub_step(H, d, a, b, c, 0, 11, 42);
+ sub_step(H, c, d, a, b, 3, 16, 43);
+ sub_step(H, b, c, d, a, 6, 23, 44);
+ sub_step(H, a, b, c, d, 9, 4, 45);
+ sub_step(H, d, a, b, c, 12, 11, 46);
+ sub_step(H, c, d, a, b, 15, 16, 47);
+ sub_step(H, b, c, d, a, 2, 23, 48);
+}
+
+// round 4() implementation.
+inline
+void MD5::round4()
+{
+ sub_step(I, a, b, c, d, 0, 6, 49);
+ sub_step(I, d, a, b, c, 7, 10, 50);
+ sub_step(I, c, d, a, b, 14, 15, 51);
+ sub_step(I, b, c, d, a, 5, 21, 52);
+ sub_step(I, a, b, c, d, 12, 6, 53);
+ sub_step(I, d, a, b, c, 3, 10, 54);
+ sub_step(I, c, d, a, b, 10, 15, 55);
+ sub_step(I, b, c, d, a, 1, 21, 56);
+ sub_step(I, a, b, c, d, 8, 6, 57);
+ sub_step(I, d, a, b, c, 15, 10, 58);
+ sub_step(I, c, d, a, b, 6, 15, 59);
+ sub_step(I, b, c, d, a, 13, 21, 60);
+ sub_step(I, a, b, c, d, 4, 6, 61);
+ sub_step(I, d, a, b, c, 11, 10, 62);
+ sub_step(I, c, d, a, b, 2, 15, 63);
+ sub_step(I, b, c, d, a, 9, 21, 64);
+}
+
+// step implementation.
+inline
+void MD5::step()
+{
+ sav();
+ round1();
+ round2();
+ round3();
+ round4();
+ a += aa;
+ b += bb;
+ c += cc;
+ d += dd;
+}
+
+// sub step implementation.
+template <class Fun>
+inline
+void MD5::sub_step(const Fun &fun,
+ storage_type &a,
+ const storage_type &b,
+ const storage_type &c,
+ const storage_type &d,
+ unsigned k,
+ unsigned s,
+ unsigned i)
+{
+ a += fun(b, c, d) + (X[k] + T[i - 1]);
+ a = a<<s | a>>(32-s);
+ a += b;
+ //a = b + ((a + fun(b, c, d) + X[k] + T[i - 1]) << s);
+}
+
+// gen_sub_key implementation.
+inline
+void MD5::gen_sub_key(std::vector<key::value_type> &v,
+ storage_type x,
+ unsigned base)
+{
+ base *= sizeof(value_type);
+
+ for (unsigned i = 0; i < sizeof(value_type); ++i)
+ v[base + i] = (x & (0xFF << (i * 8))) >> (i * 8);
+}
+
+// gen_key implementation.
+
+inline
+key MD5::gen_key()
+{
+ std::vector<key::value_type> k;
+
+ k.reserve(16);
+ gen_sub_key(k, a, 0);
+ gen_sub_key(k, b, 1);
+ gen_sub_key(k, c, 2);
+ gen_sub_key(k, d, 3);
+ return key(k);
+}
+
+// execute implementation.
+inline
+key MD5::execute()
+{
+ while (buffer_.size() > current_)
+ step();
+ return gen_key();
+}
+
+
+// md5 implementation.
+template <class I>
+inline
+key md5(const oln::abstract::non_vectorial_image<I> &im)
+{
+ buffer b;
+ oln_type_of(I, fwd_piter) p(im.size());
+
+ for_all(p)
+ b.add(im[p].value());
+ b.append_padding();
+ b.append_length();
+
+ oln::utils::MD5 md5(b);
+ return md5.execute();
+}
+
+// md5 implementation.
+template <class I>
+inline
+key md5(const oln::abstract::vectorial_image<I> &im)
+{
+ oln_type_of(I, fwd_piter) p(im.size());
+ buffer b;
+ // unsigned nb =
+
+ for_all(p)
+ {
+ for (unsigned i = 0; i < ntg_nb_comp(oln_type_of(I, value)); ++i)
+ b.add(im[p].value()[i]);
+ }
+ b.append_padding();
+ b.append_length();
+
+ oln::utils::MD5 md5(b);
+ return md5.execute();
+}
+
+#endif // !OLENA_OLN_UTILS_MD5_HXX
Index: oln/utils/clone.hh
--- oln/utils/clone.hh (revision 92)
+++ oln/utils/clone.hh (working copy)
@@ -35,56 +35,63 @@
// fwd decl
namespace utils {
+
+ namespace impl {
template <typename I> struct clone_type;
+ }
+
}
// category
template <typename I>
- struct set_category < utils::clone_type<I> >
+ struct set_category < utils::impl::clone_type<I> >
{
typedef category::image ret;
};
// super_type
template <typename I>
- struct set_super_type < utils::clone_type<I> >
+ struct set_super_type < utils::impl::clone_type<I> >
{
- typedef abstract::op<I, utils::clone_type<I> > ret;
+ typedef abstract::op<I, utils::impl::clone_type<I> > ret;
};
namespace utils {
- template <typename I>
- struct clone_type : abstract::op<I, clone_type<I> >
- {
- typedef abstract::op<I, clone_type<I> > super_type;
+ namespace impl {
- mlc::box<I> input_;
+ template <typename I>
+ struct clone_type : abstract::op<I, clone_type<I> >
+ {
+ typedef abstract::op<I, clone_type<I> > super_type;
- clone_type(I& input) : input_(input)
- {}
+ mlc::box<I> input_;
- void impl_run()
- {
- I ima(input_->size());
- oln_type_of(I, fwd_piter) it(input_->size());
+ clone_type(I& input) : input_(input)
+ {}
- for_all(it)
- {
- ima[it] = (*input_)[it];
- }
+ void impl_run()
+ {
+ I ima(input_->size());
+ oln_type_of(I, fwd_piter) it(input_->size());
- *this->image_ = ima;
- }
- };
+ for_all(it)
+ {
+ ima[it] = (*input_)[it];
+ }
+ *this->image_ = ima;
+ }
+ };
+ }
+
template <typename I>
- clone_type<I> clone(abstract::image<I>& ima)
+ impl::clone_type<I> clone(abstract::image<I>& ima)
{
- clone_type<I> tmp(ima.exact());
+ impl::clone_type<I> tmp(ima.exact());
tmp.run();
return tmp;
}
Index: oln/utils/key.hxx
--- oln/utils/key.hxx (revision 0)
+++ oln/utils/key.hxx (revision 0)
@@ -0,0 +1,80 @@
+// Copyright (C) 2004 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, 59 Temple Place - Suite 330, 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 OLENA_OLN_UTILS_KEY_HXX
+# define OLENA_OLN_UTILS_KEY_HXX
+
+// Ctor implementation.
+inline
+key::key(const std::vector<value_type> &data)
+{
+ for (unsigned i = 0; i < 16; ++i)
+ data_[i] = data[i];
+}
+
+// Ctor implementation.
+inline
+key::key(const value_type *data)
+{
+ for (unsigned i = 0; i < 16; ++i)
+ data_[i] = data[i];
+}
+
+// [] operator implementation
+inline
+key::value_type &key::operator[](unsigned i)
+{
+ precondition(i < 16);
+ return data_[i];
+}
+
+// [] operator
+inline
+const key::value_type &key::operator[](unsigned i) const
+{
+ precondition(i < 16);
+ return data_[i];
+}
+
+// == operator
+inline
+bool key::operator ==(const key &k)
+{
+ for (unsigned i = 0; i < 16; ++i)
+ if (data_[i] != k[i])
+ return false;
+ return true;
+}
+
+// != operator
+inline
+bool key::operator !=(const key &k)
+{
+ return !(*this == k);
+}
+
+#endif // !OLENA_OLN_UTILS_KEY_HXX
Index: oln/morpho/dilation.hh
--- oln/morpho/dilation.hh (revision 0)
+++ oln/morpho/dilation.hh (revision 0)
@@ -0,0 +1,178 @@
+// Copyright (C) 2001, 2002, 2004, 2005 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, 59 Temple Place - Suite 330, Boston,
+// MA 02111-1307, USA.
+//
+// As a special exception, you may use this filek 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 OLENA_MORPHO_DILATION_HH
+# define OLENA_MORPHO_DILATION_HH
+
+# include <oln/basics.hh>
+# include <oln/morpho/stat.hh>
+// # include <oln/morpho/fast_morpho.hh>
+# include <mlc/cmp.hh>
+
+namespace oln {
+
+ namespace morpho {
+
+ /*!
+ ** \brief Processing dilation.
+ **
+ ** Compute the morphological dilation of input using se
+ ** as structural element.\n
+ **
+ ** On grey-scale images, each point is replaced by the maximum value
+ ** of its neighbors, as indicated by se. On binary images,
+ ** a logical or is performed between neighbors.\n
+ **
+ ** The morpho::fast version of this function use a different
+ ** algorithm: This algorithm is described in
+ ** Implementation of morphological operations from:
+ ** M. Van Droogenbroeck and H. Talbot.
+ ** "Fast computation of morphological operations with arbitrary
+ ** structuring elements". Pattern Recognition Letters,
+ ** 17(14):1451-1460, 1996.\n
+ **
+ ** An histogram of the value of the neighborhood indicated by
+ ** se is updated while iterating over all point of the
+ ** image. Doing so is more efficient when the
+ ** structural element is large.\n
+ **
+ ** \param I Exact type of the input image.
+ ** \param E Exact type of the neighborhood.
+ **
+ ** \arg input The input image.
+ ** \arg se Structuring element to use.
+ **
+ ** \code
+ ** #include <oln/basics2d.hh>
+ ** #include <oln/morpho/dilation.hh>
+ ** #include <oln/level/compare.hh>
+ ** #include <ntg/all.hh>
+ ** int main()
+ ** {
+ ** typedef oln::image2d<ntg::bin> im_type;
+ **
+ ** im_type im1(oln::load(IMG_IN "object.pbm"));
+ ** save(oln::morpho::dilation(im1, oln::win_c8p()),
+ ** IMG_OUT "oln_morpho_dilation.pbm");
+ ** }
+ ** \endcode
+ **
+ ** \image html object_pbm.png
+ ** \image latex object_pbm.png
+ ** =>
+ ** \image html oln_morpho_dilation.png
+ ** \image latex oln_morpho_dilation.png
+ */
+
+ // fwd decl
+ namespace impl {
+ template <typename I, typename E> struct dilation_type;
+ }
+
+ }
+
+ // category
+ template <typename I, typename E>
+ struct set_category< morpho::impl::dilation_type<I,E> > { typedef
category::image ret; };
+
+ // super_type
+ template <typename I, typename E>
+ struct set_super_type< morpho::impl::dilation_type<I,E> >
+ {
+ typedef abstract::op<I, morpho::impl::dilation_type<I, E> > ret;
+ };
+
+ namespace morpho {
+
+ namespace impl {
+
+ template <class I, class E>
+ struct dilation_type : abstract::op<I, dilation_type<I, E> >
+ {
+ mlc::box<const I> input_;
+ mlc::box<const E> se_;
+
+ dilation_type(const abstract::non_vectorial_image<I>& input,
+ const abstract::struct_elt<E>& se) :
+ input_(input.exact()),
+ se_(se.exact())
+ {}
+
+ };
+
+ template <class I, class E>
+ struct dilation_type_classic : dilation_type<I, E>
+ {
+ typedef dilation_type<I, E> super_type;
+
+ dilation_type_classic(const abstract::non_vectorial_image<I>& input,
+ const abstract::struct_elt<E>& se) :
+ super_type(input, se)
+ {}
+
+ void impl_run()
+ {
+ mlc::is_true<mlc::type::eq<oln_type_of(I, size),
+ oln_type_of(E, size)>::ret>::ensure();
+ I output(this->input_->size());
+ this->input_->resize_border(this->se_->get_delta());
+ oln_type_of(I, fwd_piter) p(this->input_->size());
+
+ for_all (p)
+ output[p] = morpho::max(*this->input_, p, *this->se_);
+ *this->image_ = output;
+ }
+ };
+
+ }
+
+ template<class I, class E>
+ impl::dilation_type<I, E>
+ dilation(const abstract::non_vectorial_image<I>& input,
+ const abstract::struct_elt<E>& se)
+ {
+ impl::dilation_type_classic<I, E> tmp(input, se);
+ tmp.run();
+ return tmp;
+ }
+
+
+// namespace fast {
+// template<class I, class E>
+// oln_concrete_type(I)
+// dilation(const abstract::non_vectorial_image<I>& input,
+// const abstract::struct_elt<E>& se)
+// {
+// return fast_morpho<I, E, utils::histogram_max<oln_value_type(I)> >
+// (input, se);
+// }
+// }
+ } // end of morpho
+
+} // end of oln
+
+#endif // ! OLENA_MORPHO_DILATION_HH
Index: oln/morpho/stat.hh
--- oln/morpho/stat.hh (revision 92)
+++ oln/morpho/stat.hh (working copy)
@@ -63,7 +63,9 @@
static V
max(const I& input, const oln_type_of(I, point)& p, const E& se)
{
- // FIXME: test dim I == dim E
+ // FIXME: test dim I == dim
+ mlc::is_true<mlc::type::eq<oln_type_of(I, size),
+ oln_type_of(E, size)>::ret>::ensure();
oln_type_of(E, fwd_witer) dp(se);
dp.start();
@@ -88,6 +90,8 @@
min(const I& input, const oln_type_of(I, point)& p, const E& se)
{
// FIXME: test dim I == dim E
+ mlc::is_true<mlc::type::eq<oln_type_of(I, size),
+ oln_type_of(E, size)>::ret>::ensure();
oln_type_of(E, fwd_witer) dp(se);
dp.start();
@@ -108,7 +112,8 @@
static ntg::bin
max(const I& input, const oln_type_of(I, point)& p, const E& se)
{
- mlc::eq<I::dim, E::dim>::ensure();
+ mlc::is_true<mlc::type::eq<oln_type_of(I, size),
+ oln_type_of(E, size)>::ret>::ensure();
oln_type_of(E, fwd_witer) dp(se);
for_all (dp)
if (input[p + dp] == true)
@@ -119,7 +124,8 @@
static ntg::bin
min(const I& input, const oln_type_of(I, point)& p, const E& se)
{
- mlc::eq<I::dim, E::dim>::ensure();
+ mlc::is_true<mlc::type::eq<oln_type_of(I, size),
+ oln_type_of(E, size)>::ret>::ensure();
oln_type_of(E, fwd_witer) dp(se);
for_all (dp)
if (input[p + dp] == false)
Index: oln/morpho/erosion.hh
--- oln/morpho/erosion.hh (revision 0)
+++ oln/morpho/erosion.hh (revision 0)
@@ -0,0 +1,209 @@
+// Copyright (C) 2001, 2002, 2003, 2004, 2005 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, 59 Temple Place - Suite 330, 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 OLENA_MORPHO_EROSION_HH
+# define OLENA_MORPHO_EROSION_HH
+
+# include <oln/basics.hh>
+# include <oln/morpho/stat.hh>
+// # include <oln/morpho/fast_morpho.hh>
+# include <oln/core/abstract/op.hh>
+# include <mlc/cmp.hh>
+
+namespace oln {
+
+ namespace morpho {
+ /*!
+ ** \brief Perform a morphological erosion.
+ **
+ ** Compute the morphological erosion of input using se
+ ** as structuring element.
+ **
+ ** On grey-scale images, each point is replaced by the minimum
+ ** value of its neighbors, as indicated by se. On binary
+ ** images, a logical and is performed between neighbors. The
+ ** morpho::fast version of this function use a different
+ ** algorithm: an histogram of the value of the neighborhood
+ ** indicated by se is updated while iterating over all point of
+ ** the image. Doing so is more efficient when the structuring
+ ** element is large.
+ **
+ ** \param I Exact type of the input image.
+ ** \param E Exact type of the structuring element.
+ **
+ **
+ ** \arg input Input image.
+ ** \arg se Structuring element to use.
+ **
+ ** \code
+ ** #include <oln/basics2d.hh>
+ ** #include <oln/morpho/erosion.hh>
+ ** #include <oln/level/compare.hh>
+ ** #include <ntg/all.hh>
+ ** int main()
+ ** {
+ ** typedef oln::image2d<ntg::bin> im_type;
+ **
+ ** im_type im1(oln::load(IMG_IN "object.pbm"));
+ ** save(oln::morpho::erosion(im1, oln::win_c8p()),
+ ** IMG_OUT "oln_morpho_erosion.pbm");
+ ** }
+ ** \endcode
+ **
+ ** \image html object_pbm.png
+ ** \image latex object_pbm.png
+ ** =>
+ ** \image html oln_morpho_erosion.png
+ ** \image latex oln_morpho_erosion.png
+ **
+ ** \see oln::morpho::fast::erosion()
+ */
+
+ // fwd decl
+ namespace impl {
+ template <typename I, typename E> struct erosion_type;
+ }
+
+ }
+
+ // category
+ template <typename I, typename E>
+ struct set_category< morpho::impl::erosion_type<I,E> > { typedef
category::image ret; };
+
+ // super_type
+ template <typename I, typename E>
+ struct set_super_type< morpho::impl::erosion_type<I,E> >
+ {
+ typedef abstract::op<I, morpho::impl::erosion_type<I, E> > ret;
+ };
+
+ namespace morpho {
+
+ namespace impl {
+
+ template <class I, class E>
+ struct erosion_type : abstract::op<I, erosion_type<I, E> >
+ {
+ mlc::box<const I> input_;
+ mlc::box<const E> se_;
+
+ erosion_type(const abstract::non_vectorial_image<I>& input,
+ const abstract::struct_elt<E>& se) :
+ input_(input.exact()),
+ se_(se.exact())
+ {}
+
+ };
+
+ template <class I, class E>
+ struct erosion_type_classic : erosion_type<I, E>
+ {
+ typedef erosion_type<I, E> super_type;
+
+ erosion_type_classic(const abstract::non_vectorial_image<I>& input,
+ const abstract::struct_elt<E>& se) :
+ super_type(input, se)
+ {}
+
+ void impl_run()
+ {
+ mlc::is_true<mlc::type::eq<oln_type_of(I, size),
+ oln_type_of(E, size)>::ret>::ensure();
+ I output(this->input_->size());
+ this->input_->resize_border(this->se_->get_delta());
+ oln_type_of(I, fwd_piter) p(this->input_->size());
+
+ for_all (p)
+ output[p] = morpho::min(*this->input_, p, *this->se_);
+ *this->image_ = output;
+ }
+ };
+
+ }
+
+
+ template<class I, class E>
+ impl::erosion_type<I, E>
+ erosion(const abstract::non_vectorial_image<I>& input,
+ const abstract::struct_elt<E>& se)
+ {
+ impl::erosion_type_classic<I, E> tmp(input, se);
+ tmp.run();
+ return tmp;
+ }
+
+ namespace fast {
+ /*!
+ ** \brief Perform a morphological erosion.
+ **
+ ** Compute the morphological erosion of input using se
+ ** as structuring element.
+ **
+ ** \param I Exact type of the input image.
+ ** \param E Exact type of the structuring element.
+ **
+ **
+ ** \arg input Input image.
+ ** \arg se Structuring element to use.
+ **
+ ** \code
+ ** #include <oln/basics2d.hh>
+ ** #include <oln/morpho/erosion.hh>
+ ** #include <oln/level/compare.hh>
+ ** #include <ntg/all.hh>
+ ** int main()
+ ** {
+ ** typedef oln::image2d<ntg::bin> im_type;
+ **
+ ** im_type im1(oln::load(IMG_IN "object.pbm"));
+ ** save(oln::morpho::fast::erosion(im1, oln::win_c8p()),
+ ** IMG_OUT "oln_morpho_fast_erosion.pbm");
+ ** }
+ ** \endcode
+ **
+ ** \image html object_pbm.png
+ ** \image latex object_pbm.png
+ ** =>
+ ** \image html oln_morpho_fast_erosion.png
+ ** \image latex oln_morpho_fast_erosion.png
+ */
+// template<class I, class E>
+// oln_concrete_type(I)
+// erosion(const abstract::non_vectorial_image<I>& input,
+// const abstract::struct_elt<E>& se)
+// {
+// return fast_morpho<I, E, utils::histogram_min<oln_value_type(I)>
>
+// (input, se);
+// }
+ } // end of fast
+
+ } // end of morpho
+
+} // end of oln
+
+
+#endif // ! OLENA_MORPHO_EROSION_HH
Index: oln/io/write_image_2d_pnm.hh
--- oln/io/write_image_2d_pnm.hh (revision 92)
+++ oln/io/write_image_2d_pnm.hh (working copy)
@@ -116,6 +116,7 @@
if (bin_offset == -1)
{
+ bin_v = ~bin_v;
ostr_.write(&bin_v, 1);
bin_offset = 7;
bin_v = 0;
Index: oln/io/read_image_2d_pnm.hh
--- oln/io/read_image_2d_pnm.hh (revision 92)
+++ oln/io/read_image_2d_pnm.hh (working copy)
@@ -172,9 +172,9 @@
offset = 7;
}
if ((int)(v & (1<<offset--)) == 0)
+ c = 1;
+ else
c = 0;
- else
- c = 1;
}
};