
Index: ChangeLog from Damien Thivolle <damien@lrde.epita.fr> * oln/io/write_image_2d_pnm.hh: Add ppm and pbm output methods. * oln/io/read_image_2d_pnm.hh: Add ppm and pbm input methods. * oln/io/utils.hh: Fix an error occuring when writing pbm headers. * oln/core/abstract/image_with_data.hh: Remove an unexpected `return'. * oln/core/2d/image2d.hh: Fix circular inclusion problem. core/2d/image2d.hh | 8 + core/abstract/image_with_data.hh | 4 io/read_image_2d_pnm.hh | 163 +++++++++++++++++++++++++++++++-------- io/utils.hh | 8 - io/write_image_2d_pnm.hh | 102 ++++++++++++++++++++++-- 6 files changed, 242 insertions(+), 45 deletions(-) Index: oln/io/write_image_2d_pnm.hh --- oln/io/write_image_2d_pnm.hh (revision 44) +++ oln/io/write_image_2d_pnm.hh (working copy) @@ -53,16 +53,16 @@ namespace impl { template <typename I> - struct write_image_2d_pgm_raw - : public oln::abstract::void_op<write_image_2d_pgm_raw<I> > + struct write_image_2d_raw + : public oln::abstract::void_op<write_image_2d_raw<I> > { typedef oln_value_type(I) value_type; - typedef typename mlc::traits<value_type>::encoding_type out_type; + typedef ntg_io_type(value_type) io_type; const I& to_write_; std::ofstream& ostr_; - write_image_2d_pgm_raw(const I& to_write, std::ofstream& ostr): + write_image_2d_raw(const I& to_write, std::ofstream& ostr): to_write_(to_write), ostr_(ostr) {} @@ -70,19 +70,57 @@ void impl_run() { point2d p; - out_type c; + value_type c; + bool b; for (p.row() = 0; p.row() < to_write_.size().nrows(); ++p.row()) for (p.col() = 0; p.col() < to_write_.size().ncols(); ++p.col()) { c = to_write_[p]; - ostr_ << c; + b = write_value_type(c); } + while (b == false) + b = write_value_type(c); ostr_.close(); } + bool write_value_type(const ntg::integer<value_type> &c) + { + ostr_ << (io_type)(c.exact()); + return true; + } + + bool write_value_type(const ntg::color<value_type> &c) + { + assert ((ntg_nb_comp(value_type) == 3)); + + for (unsigned i = 0; i < 3; i++) + ostr_ << (io_type)(c[i]); + return true; + } + + bool write_value_type(const ntg::enum_value<value_type> &c) + { + assert ((ntg_max_val(value_type) == 1)); + static int offset = 7; + static unsigned char v = 0; + bool ret = false; + + if (offset == -1) + { + ostr_ << v; + offset = 7; + v = 0; + ret = true; + } + if (c == 1) + v |= 1 << offset; + offset--; + return ret; + } }; + template <typename I, typename T> void write(const abstract::image2d<I>& to_write, const ntg::integer<T>&, @@ -98,7 +136,7 @@ s.ncols(), s.nrows(), ntg_max_val(T))) { - write_image_2d_pgm_raw<I> tmp(to_write.exact(), ostr); + write_image_2d_raw<I> tmp(to_write.exact(), ostr); tmp.run(); } else @@ -108,6 +146,56 @@ << " file extension (`" << ext << "')" << std::endl; } + template <typename I, typename T> + void write(const abstract::image2d<I>& to_write, + const ntg::color<T>&, + const std::string& name, + const std::string& ext) + { + std::ofstream ostr; + point2d p; + size2d s = to_write.size(); + + if (ext == "ppm") + if (internal::write_pnm_header(ostr, name, "P6", + s.ncols(), s.nrows(), + ntg_max_val(T))) + { + write_image_2d_raw<I> tmp(to_write.exact(), ostr); + tmp.run(); + } + else + std::cerr << "error: unable to write header" << std::endl; + else + std::cerr << "error: image data type (`color') does not match" + << " file extension (`" << ext << "')" << std::endl; + } + + template <typename I, typename T> + void write(const abstract::image2d<I>& to_write, + const ntg::enum_value<T>&, + const std::string& name, + const std::string& ext) + { + std::ofstream ostr; + point2d p; + size2d s = to_write.size(); + + if (ext == "pbm") + if (internal::write_pnm_header(ostr, name, "P4", + s.ncols(), s.nrows(), + ntg_max_val(T))) + { + write_image_2d_raw<I> tmp(to_write.exact(), ostr); + tmp.run(); + } + else + std::cerr << "error: unable to write header" << std::endl; + else + std::cerr << "error: image data type (`enum_value') does not match" + << " file extension (`" << ext << "')" << std::endl; + } + } } Index: oln/io/read_image_2d_pnm.hh --- oln/io/read_image_2d_pnm.hh (revision 44) +++ oln/io/read_image_2d_pnm.hh (working copy) @@ -28,27 +28,56 @@ namespace impl { + template <typename I> + struct read_image_2d_raw; + } + + } + + template <typename I> + struct category_type< io::impl::read_image_2d_raw<I> > + { + typedef cat::image ret; + }; + + template <typename I> + struct props <cat::image, io::impl::read_image_2d_raw<I> > + : public props<cat::image, I> + { + typedef I delegated_type; + }; + + + + namespace io { + + namespace impl { + template <typename I> - struct read_image_2d_pgm_raw: - oln::abstract::void_op<read_image_2d_pgm_raw<I> > + struct read_image_2d_raw: + oln::abstract::op<I, read_image_2d_raw<I> > { + + typedef oln::abstract::op<I, read_image_2d_raw<I> > super_type; + typedef oln_value_type(I) value_type; + typedef ntg_io_type(value_type) io_type; + mlc::box<I> image_; std::ifstream& istr_; internal::pnm_info& info_; - read_image_2d_pgm_raw(I& image, - std::ifstream &istr, - internal::pnm_info &info) : + read_image_2d_raw(I& image, + std::ifstream &istr, + internal::pnm_info &info) : + super_type(image), image_(image), istr_(istr), info_(info) {} - typedef oln_value_type(I) value_type; - typedef typename mlc::traits<value_type>::encoding_type encoding_type; - read_image_2d_pgm_raw<I>& output(I& output) + read_image_2d_raw<I>& output(I& output) { output = *image_; return *this; @@ -56,7 +85,9 @@ void impl_run() { - encoding_type c; + value_type c; + point2d p; + oln::image2d<value_type> tmp(info_.rows, info_.cols); if (info_.max_val > ntg_max_val(value_type)) { @@ -64,26 +95,57 @@ << std::endl; return; } - point2d p; - oln::image2d<value_type> tmp(info_.rows, info_.cols); - std::cout << info_.cols << "," << info_.rows << "," - << info_.max_val << std::endl; - - for (p.row() = 0; p.row() < info_.rows && !istr_.eof(); ++p.row()) for (p.col() = 0; p.col() < info_.cols && !istr_.eof(); ++p.col()) { - istr_.read(&c, sizeof (encoding_type)); + read_value_type(c); tmp[p] = c; } istr_.close(); *image_ = tmp; - std::cout << "debug : size = " << image_->size() << std::endl; } + + void read_value_type(ntg::integer<value_type> &c) + { + io_type v; + istr_.read(&v, sizeof (io_type)); + c = v; + } + + void read_value_type(ntg::color<value_type> &c) + { + assert((ntg_nb_comp(value_type) == 3)); + io_type v; + + for (unsigned i = 0; i < 3; i++) + { + istr_.read(&v, sizeof (v)); + c[i] = v; + } + } + + void read_value_type(ntg::enum_value<value_type> &c) + { + static io_type v; + static int offset = -1; + + if (offset == -1) + { + istr_.read((char *)(&v), sizeof (v)); + offset = 7; + } + if ((int)(v & (1<<offset--)) == 0) + c = 0; + else + c = 1; + } + + }; + template <typename I, typename T> void read(abstract::image2d<I>& ima, const ntg::integer<T>&, @@ -97,27 +159,25 @@ if (ext == "pgm") if (info.type == "P5") { - read_image_2d_pgm_raw<I> tmp(ima.exact(), istr, info); + read_image_2d_raw<I> tmp(ima.exact(), istr, info); tmp.run(); tmp.output(ima.exact()); } + else if (info.type == "P2") + std::cerr << "error: read_image_2d_pgm_ascii not implemented" + << std::endl; else - if (info.type == "P2") - std::cerr << "error: read_image_2d_pgm_ascii not implemented" - << std::endl; - else - std::cerr << "error: file header (`" << info.type - << "') does not match file extension (`" - << ext << "')" << std::endl; + std::cerr << "error: file header (`" << info.type + << "') does not match file extension (`" + << ext << "')" << std::endl; else std::cerr << "error: image data type (`integer') does not match" << " file extension (`" << ext << "')" << std::endl; else std::cerr << "error: unable to get a valid header" << std::endl; - std::cout << "debug : size = " << ima.size() << std::endl; + } - } template <typename I, typename T> void read(abstract::image2d<I>& ima, @@ -125,7 +185,29 @@ const std::string& filename, const std::string& ext) { - std::cout << "read for image2d<color>" << std::endl; + std::ifstream istr; + internal::pnm_info info; + + if (internal::read_pnm_header(istr, info, filename)) + if (ext == "ppm") + if (info.type == "P6") + { + read_image_2d_raw<I> tmp(ima.exact(), istr, info); + tmp.run(); + tmp.output(ima.exact()); + } + else if (info.type == "P3") + std::cerr << "error: read_image_2d_ppm_ascii not implemented" + << std::endl; + else + std::cerr << "error: file header (`" << info.type + << "') does not match file extension (`" + << ext << "')" << std::endl; + else + std::cerr << "error: image data type (`color') does not match" + << " file extension (`" << ext << "')" << std::endl; + else + std::cerr << "error: unable to get a valid header" << std::endl; } template <typename I, typename T> @@ -134,10 +216,31 @@ const std::string& filename, const std::string& ext) { - std::cout << "read for image2d<enum>" << std::endl; + std::ifstream istr; + internal::pnm_info info; + + if (internal::read_pnm_header(istr, info, filename)) + if (ext == "pbm") + if (info.type == "P4") + { + read_image_2d_raw<I> tmp(ima.exact(), istr, info); + tmp.run(); + tmp.output(ima.exact()); + } + else if (info.type == "P1") + std::cerr << "error: read_image_2d_ppm_ascii not implemented" + << std::endl; + else + std::cerr << "error: file header (`" << info.type + << "') does not match file extension (`" + << ext << "')" << std::endl; + else + std::cerr << "error: image data type (`enum_value') does not match" + << " file extension (`" << ext << "')" << std::endl; + else + std::cerr << "error: unable to get a valid header" << std::endl; } - } } Index: oln/io/utils.hh --- oln/io/utils.hh (revision 44) +++ oln/io/utils.hh (working copy) @@ -160,11 +160,11 @@ return false; } - - ostr << "P5" << std::endl + ostr << type << std::endl << "# Olena 1.0" << std::endl - << ncols << " " << nrows << std::endl - << max_val << std::endl; + << ncols << " " << nrows << std::endl; + if (type != "P1" && type != "P4") + ostr << max_val << std::endl; return true; } Index: oln/core/abstract/image_with_data.hh --- oln/core/abstract/image_with_data.hh (revision 44) +++ oln/core/abstract/image_with_data.hh (working copy) @@ -121,7 +121,7 @@ template <typename V> void impl_set(const oln_point_type(E)& p, const V& v) { - return this->data_->set(p, v); + this->data_->set(p, v); } /*! \brief True if the image contains data. @@ -130,8 +130,8 @@ { return data_ != 0; } - + protected: /*! \brief Constructor (protected) with no memory allocation for Index: oln/core/2d/image2d.hh --- oln/core/2d/image2d.hh (revision 44) +++ oln/core/2d/image2d.hh (working copy) @@ -34,14 +34,20 @@ # include <oln/core/abstract/image_with_data.hh> # include <oln/core/2d/array2d.hh> # include <oln/core/2d/fwd_piter2d.hh> -# include <oln/io/read_image.hh> /*! \namespace oln ** \brief oln namespace. */ namespace oln { + namespace io { + struct filename; + + template <typename I> + void do_read(abstract::image<I>&, const filename&); + } + // fwd decl template <typename T> class image2d;