Index: ChangeLog from Damien Thivolle damien@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::image2dntg::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::image2dntg::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::vectorkey::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::vectorkey::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::vectorkey::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::image2dntg::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::image2dntg::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::image2dntg::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; } };