proto-1.0 54: Add gzip i/o

Index: ChangeLog from Damien Thivolle <damien@lrde.epita.fr> * tests/io: New. * tests/io/tests: New. * tests/io/tests/2d: New. * tests/io/Makefile.am: New. * tests/io/loadsave.hh: New. * oln/makefile.src: Add new files. * oln/io/write_image_2d_pnm.hh: Modify function prototypes. * oln/io/gz_stream.hh: New. Gz stream classes. * oln/io/read_image_2d_pnm.hh: Modify function prototypes. * oln/io/write_image.hh: Add gz stream support. * oln/io/read_image.hh: Likewise. * oln/io/utils.hh: Modify function prototypes. * oln/core/value_box.hh: Add new operator== for value_box. * oln/core/2d/image2d.hh: Remove debug output. * img/lena.pgm.gz: New. * img/lena.pgm: New. * img/chien.pbm.gz: New. * img/chien.pbm: New. * img/lena.ppm.gz: New. * img/lena.ppm: New. * img/lena.pbm.gz: New. * img/lena.pbm: New. img/lena.pbm | 0 img/lena.pgm | 4 img/lena.ppm | 541 +++++++++++++++++++++++++++++++++++++++++++ oln/core/2d/image2d.hh | 1 oln/core/value_box.hh | 64 ++++- oln/io/gz_stream.hh | 482 ++++++++++++++++++++++++++++++++++++++ oln/io/read_image.hh | 102 +++++++- oln/io/read_image_2d_pnm.hh | 134 ++-------- oln/io/utils.hh | 34 -- oln/io/write_image.hh | 65 ++++- oln/io/write_image_2d_pnm.hh | 39 +-- oln/makefile.src | 1 tests/io/Makefile.am | 9 tests/io/loadsave.hh | 49 +++ tests/io/tests/2d | 52 ++++ 15 files changed, 1399 insertions(+), 178 deletions(-) Index: tests/io/tests/2d --- tests/io/tests/2d (revision 0) +++ tests/io/tests/2d (revision 0) @@ -0,0 +1,52 @@ +// -*- c++ -*- +// Copyright (C) 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. + + +#include "loadsave.hh" + +bool +check(void) +{ + bool fail = false; + + typedef oln::image2d<ntg::int_u8> ima_int_u8; + typedef oln::image2d<ntg::rgb_8> ima_rgb_8; + typedef oln::image2d<ntg::bin> ima_bin; + + fail |= loadsave< ima_int_u8 >(rdata("lena.pgm"), "lena.pgm"); + fail |= loadsave< ima_bin >(rdata("lena.pbm"), "lena.pbm"); + fail |= loadsave< ima_rgb_8 >(rdata("lena.ppm"), "lena.ppm"); + +#if HAVE_ZLIB + fail |= loadsave< ima_bin >(rdata("lena.pbm.gz"), "lena.pbm.gz"); + fail |= loadsave< ima_int_u8 >(rdata("lena.pgm.gz"), "lena.pgm.gz"); + fail |= loadsave< ima_rgb_8 >(rdata("lena.ppm.gz"), "lena.ppm.gz"); +#endif + + return fail; +} Index: tests/io/Makefile.am --- tests/io/Makefile.am (revision 0) +++ tests/io/Makefile.am (revision 0) @@ -0,0 +1,9 @@ +## Process this file through Automake to create Makefile.in -*- Makefile -*- + +include ../check/Makefile.runtests + +noinst_HEADERS = loadsave.hh + +CLEANFILES += \ + lena.ppm lena.pgm lena.pbm \ + lena.ppm.gz lena.pgm.gz lena.pbm.gz Index: tests/io/loadsave.hh --- tests/io/loadsave.hh (revision 0) +++ tests/io/loadsave.hh (revision 0) @@ -0,0 +1,49 @@ +#include <oln/basics1d.hh> +#include <oln/basics2d.hh> +#include <oln/basics3d.hh> +#include <oln/all.hh> + +#include <ntg/all.hh> + +#include "check.hh" +#include "data.hh" + +template<typename E> +bool compare(const oln::abstract::image<E>& a, + const oln::abstract::image<E>& b) +{ + + oln_type_of(E, fwd_piter) it(a.size()); + + if (a.size().nrows() != b.size().nrows() || + a.size().ncols() != b.size().ncols()) + return false; + + for (it.start(); !it.is_valid(); it.next()) + if (a[it] != b[it]) + return false; + + return true; +} + +template< typename T > +bool +loadsave(const std::string& name, const std::string& savename) +{ + bool fail = false; + + T im1, im2; + im1 = oln::io::read(name); + oln::io::write(im1, savename); + + im2 = oln::io::read(savename); + + if (compare(im1, im2)) + std::cout << "OK" << std::endl; + else + { + std::cout << "FAILED" << std::endl; + fail = true; + } + return fail; +} Index: oln/makefile.src --- oln/makefile.src (revision 53) +++ oln/makefile.src (working copy) @@ -40,6 +40,7 @@ core/value_box.hh \ fancy/iota.hh \ fancy/print.hh \ + io/gz_stream.hh \ io/read_image.hh \ io/read_image_2d_pnm.hh \ io/utils.hh \ Index: oln/io/write_image_2d_pnm.hh --- oln/io/write_image_2d_pnm.hh (revision 53) +++ oln/io/write_image_2d_pnm.hh (working copy) @@ -59,9 +59,9 @@ typedef ntg_io_type(value_type) io_type; const I& to_write_; - std::ofstream& ostr_; + std::ostream& ostr_; - write_image_2d_raw(const I& to_write, std::ofstream& ostr): + write_image_2d_raw(const I& to_write, std::ostream& ostr): to_write_(to_write), ostr_(ostr) {} @@ -70,7 +70,7 @@ { point2d p; value_type c; - bool b; + bool b = false; for (p.row() = 0; p.row() < to_write_.size().nrows(); ++p.row()) for (p.col() = 0; p.col() < to_write_.size().ncols(); ++p.col()) @@ -80,21 +80,25 @@ } 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()); + io_type v = c.exact(); + ostr_.write((char *)&v, sizeof(io_type)); return true; } bool write_value_type(const ntg::color<value_type> &c) { - assert ((ntg_nb_comp(value_type) == 3)); + assert ((ntg_depth(value_type) == 3)); + io_type v; for (unsigned i = 0; i < 3; i++) - ostr_ << (io_type)(c[i]); + { + v = c[i]; + ostr_.write((char *)(&v), sizeof(io_type)); + } return true; } @@ -107,7 +111,7 @@ if (offset == -1) { - ostr_ << v; + ostr_.write((char *)&v, 1); offset = 7; v = 0; ret = true; @@ -123,15 +127,15 @@ template <typename I, typename T> void write(const abstract::image2d<I>& to_write, const ntg::integer<T>&, - const std::string& name, + std::ostream& ostr, const std::string& ext) { - std::ofstream ostr; + point2d p; size2d s = to_write.size(); if (ext == "pgm") - if (internal::write_pnm_header(ostr, name, "P5", + if (internal::write_pnm_header(ostr, "P5", s.ncols(), s.nrows(), ntg_max_val(T))) { @@ -139,7 +143,7 @@ tmp.run(); } else - std::cerr << "error: unable to write header" << std::endl; + std::cerr << "error: unable to write file header" << std::endl; else std::cerr << "error: image data type (`integer') does not match" << " file extension (`" << ext << "')" << std::endl; @@ -148,15 +152,15 @@ template <typename I, typename T> void write(const abstract::image2d<I>& to_write, const ntg::color<T>&, - const std::string& name, + std::ostream& ostr, 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", + if (internal::write_pnm_header(ostr, "P6", s.ncols(), s.nrows(), ntg_max_val(T))) { @@ -173,15 +177,14 @@ template <typename I, typename T> void write(const abstract::image2d<I>& to_write, const ntg::enum_value<T>&, - const std::string& name, + std::ostream& ostr, 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", + if (internal::write_pnm_header(ostr, "P4", s.ncols(), s.nrows(), ntg_max_val(T))) { Index: oln/io/gz_stream.hh --- oln/io/gz_stream.hh (revision 0) +++ oln/io/gz_stream.hh (revision 0) @@ -0,0 +1,482 @@ +// 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 OLN_IO_GZ_STREAM_HH +# define OLN_IO_GZ_STREAM_HH + +# include <oln/config/system.hh> + +#if defined HAVE_ZLIB && HAVE_ZLIB == 1 +# include <cassert> +# include <fstream> +# include <string> +# include <zlib.h> + +namespace oln { + + namespace io { + + /// Functions for gz files + namespace gz { + + + ///Performs operation on compressed files. + class zfilebuf : public std::streambuf + { + public: + + + zfilebuf() : file(0), mode(0), own_file_descriptor(0) + { + inbuf = new char[lenbuf]; + outbuf = new char[lenbuf]; + setg(0, 0, 0); + setp(outbuf, outbuf + lenbuf); + } + + virtual ~zfilebuf() + { + sync(); + delete[] inbuf; + delete[] outbuf; + if (own_file_descriptor) + close(); + } + + + /*! \brief Return a stream on the file \a name regarding + ** the opening mode: \a io_mode. + */ + zfilebuf* + open(const char *name, int io_mode) + { + if (is_open()) + return 0; + + char char_mode[10]; + char *p; + memset(char_mode,'\0',10); + p = char_mode; + + if (io_mode & std::ios::in) + { + mode = std::ios::in; + *p++ = 'r'; + } + else + if (io_mode & std::ios::app) + { + mode = std::ios::app; + *p++ = 'a'; + } + else + { + mode = std::ios::out; + *p++ = 'w'; + } + if (io_mode & std::ios::binary) + { + mode |= std::ios::binary; + *p++ = 'b'; + } + + // Hard code the compression level + if (io_mode & (std::ios::out|std::ios::app)) + *p++ = '9'; + + if ((file = gzopen(name, char_mode)) == 0) + return 0; + + name_ = name; + own_file_descriptor = 1; + return this; + } + + /*! \brief Attach a stream on \a file_descriptor regarding + ** the opening mode: \a io_mode. + */ + zfilebuf* + attach(int file_descriptor, int io_mode) + { + if (is_open()) + return 0; + + char char_mode[10]; + char *p; + memset(char_mode,'\0',10); + p = char_mode; + + if (io_mode & std::ios::in) + { + mode = std::ios::in; + *p++ = 'r'; + } + else + if (io_mode & std::ios::app) + { + mode = std::ios::app; + *p++ = 'a'; + } + else + { + mode = std::ios::out; + *p++ = 'w'; + } + + if (io_mode & std::ios::binary) + { + mode |= std::ios::binary; + *p++ = 'b'; + } + + // Hard code the compression level + if (io_mode & (std::ios::out|std::ios::app)) + *p++ = '9'; + + if ((file = gzdopen(file_descriptor, char_mode)) == 0) + return 0; + + own_file_descriptor = 0; + return this; + } + + /// Close the stream. + zfilebuf* + close() + { + if (is_open()) + { + sync(); + gzclose(file); + file = 0; + } + return this; + } + + + int + setcompressionlevel(short comp_level) + { + return gzsetparams(file, comp_level, -2); + } + + int + setcompressionstrategy(short comp_strategy) + { + return gzsetparams(file, -2, comp_strategy); + } + + /// Return true if the stream is open, false otherwise. + inline int + is_open() const + { return (file != 0); } + + virtual std::streampos + seekoff(std::streamoff off, std::ios::seekdir dir, int) // which) + { + return std::streampos(gzseek(file, off, dir)); + } + + /// Flush the buffer associated to the stream. + virtual int + sync() + { + if (!is_open()) + return EOF; + return flushbuf(); + } + + protected: + + /*! \brief Return the next character in the stream. + ** On failure, \a EOF is returned. + */ + virtual int + underflow() + { + // If the file hasn't been opened for reading, error. + if (!is_open() || !(mode & std::ios::in)) + return EOF; + + if (in_avail()) + return (unsigned char) *gptr(); + + if (flushbuf() == EOF) + return EOF; + + // Attempt to fill the buffer. + if (fillbuf() == EOF) + return EOF; + + assert (eback()); + + return (unsigned char) *gptr(); + } + + /*! \brief Flush the output buffer associated to the stream + ** then write \a c. On failure, \a EOF is returned. + */ + + virtual int + overflow(int c = EOF) + { + if (!is_open() || !(mode & std::ios::out)) + return EOF; + + assert (pbase()); + + if (flushbuf() == EOF) + return EOF; + + if (c != EOF) + { + *pptr() = c; + pbump(1); + } + return 0; + } + + private: + + gzFile file; + short mode; + short own_file_descriptor; + std::string name_; + char *inbuf; + char *outbuf; + static const int lenbuf = 16 * 1024; + + /// Flush the output buffer + int + flushbuf() + { + int n = pptr() - outbuf; + + if (n == 0) + return 0; + + if (gzwrite(file, outbuf, n) < n) + return EOF; + + setp(outbuf, outbuf + lenbuf); + return 0; + } + /// Fill the input buffer. + int + fillbuf() + { + int t = gzread(file, inbuf, lenbuf); + if (t <= 0) return EOF; + setg(inbuf, inbuf, inbuf + t); + return t; + } + + }; + + ///Define an interface for compressed file stream manipulation. + class zfilestream_common : virtual public std::ios + { + friend class zifstream; + friend class zofstream; + friend zofstream &setcompressionlevel(zofstream &, int); + friend zofstream &setcompressionstrategy(zofstream &, int); + + public: + virtual ~zfilestream_common() {} + + /*! \brief Open the stream on the file descriptor: + ** \a fd regarding the opening mode. + */ + void + attach(int fd, int io_mode) + { + if (!buffer.attach(fd, io_mode)) + clear(std::ios::failbit | std::ios::badbit); + else + clear(); + } + + /*! \brief Open the stream on the file named \a name + ** regarding the opening mode. + */ + void + open(const char *name, int io_mode) + { + if (!buffer.open(name, io_mode)) + clear(std::ios::failbit | std::ios::badbit); + else + clear(); + } + + /// Close the current stream. + void + close() + { + if (!buffer.close()) + clear(std::ios::failbit | std::ios::badbit); + } + + bool + is_open() + { + return buffer.is_open(); + } + + + protected: + /// Prevent instantiation. + zfilestream_common() : std::ios(zfilestream_common::rdbuf()) + { } + + + private: + zfilebuf* + rdbuf() + { + return &buffer; + } + + zfilebuf buffer; + }; + + + /// Read only zstream. + class zifstream : public zfilestream_common, public std::istream + { + public: + + zifstream() : std::istream(zfilestream_common::rdbuf()) + { + clear(std::ios::badbit); + } + + /// Open a read only stream on the file named \a name. + zifstream(const char *name, int io_mode = std::ios::in) : + std::istream(zfilestream_common::rdbuf()) + { + zfilestream_common::open(name, io_mode); + } + + /// Open a read only stream on the file descriptor \a fd. + zifstream(int fd, int io_mode = std::ios::in) : + std::istream(zfilestream_common::rdbuf()) + { + zfilestream_common::attach(fd, io_mode); + } + + virtual ~zifstream() {} + }; + + class zofstream : public zfilestream_common, public std::ostream { + + public: + + zofstream() : std::ostream(zfilestream_common::rdbuf()) + { + clear(std::ios::badbit); + } + + /// Open a write only stream on the file named \a name. + zofstream(const char *name, int io_mode = std::ios::out) : + std::ostream(zfilestream_common::rdbuf()) + { + zfilestream_common::open(name, io_mode); + } + + /// Open a write only stream on the file descriptor \a fd. + zofstream(int fd, int io_mode = std::ios::out) : + std::ostream(zfilestream_common::rdbuf()) + { + zfilestream_common::attach(fd, io_mode); + } + + virtual ~zofstream() {} + + }; + + // Forward declaration. + template <class T> + class zomanip; + + /// Apply a function on \a s via the operator <<. + template <class T> + zofstream& + operator<<(zofstream &s, const zomanip<T> &m) { + return (*m.func)(s, m.val); + } + + + /// Define a pair func / val to perform manipulation on zofstream. + template<class T> class zomanip + { + friend zofstream &operator<< <T>(zofstream &, const zomanip<T> &); + public: + zomanip(zofstream &(*f)(zofstream &, T), T v) : func(f), val(v) { } + private: + zofstream &(*func)(zofstream &, T); + T val; + }; + + + /// Set the compression level of \a s to \a l. + inline zofstream& + setcompressionlevel(zofstream &s, int l) { + (s.rdbuf())->setcompressionlevel(l); + return s; + } + + /// Set the compression strategy of \a s to \a l. + inline zofstream& + setcompressionstrategy(zofstream &s, int l) + { + (s.rdbuf())->setcompressionstrategy(l); + return s; + } + + /// Specialized version for zomanip<int> + inline zomanip<int> + setcompressionlevel(int l) + { + return zomanip<int>(&setcompressionlevel,l); + } + + /// Specialized version for zomanip<int> + inline zomanip<int> + setcompressionstrategy(int l) + { + return zomanip<int>(&setcompressionstrategy,l); + } + + } // end of namespace gz + + } // end of namespace io + +} // end of namespace oln + +# endif // ! HAVE_ZLIB + +#endif // ! OLN_IO_GZ_STREAM_HH Index: oln/io/read_image_2d_pnm.hh --- oln/io/read_image_2d_pnm.hh (revision 53) +++ oln/io/read_image_2d_pnm.hh (working copy) @@ -1,3 +1,30 @@ +// Copyright (C) 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 OLN_IO_READ_IMAGE_2D_PNM_HH # define OLN_IO_READ_IMAGE_2D_PNM_HH @@ -59,11 +86,11 @@ typedef ntg_io_type(value_type) io_type; mlc::box<I> image_; - std::ifstream& istr_; + std::istream& istr_; internal::pnm_info& info_; read_image_2d_raw(I& image, - std::ifstream &istr, + std::istream &istr, internal::pnm_info &info) : super_type(image), image_(image), @@ -97,7 +124,6 @@ read_value_type(c); tmp[p] = c; } - istr_.close(); *image_ = tmp; } @@ -110,10 +136,9 @@ 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++) + for (unsigned i = 0; i < ntg_depth(value_type); i++) { istr_.read(&v, sizeof (v)); c[i] = v; @@ -135,107 +160,20 @@ else c = 1; } - - }; - template <typename I, typename T> + template <typename I> void read(abstract::image2d<I>& ima, - const ntg::integer<T>&, - const std::string& filename, - const std::string& ext) + std::istream& istr, + internal::pnm_info info) { - std::ifstream istr; - internal::pnm_info info; - - if (internal::read_pnm_header(istr, info, filename)) - if (ext == "pgm") - if (info.type == "P5") - { - 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 - 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; + read_image_2d_raw<I> tmp(ima.exact(), istr, info); + tmp.run(); + tmp.output(ima.exact()); } - - - template <typename I, typename T> - void read(abstract::image2d<I>& ima, - const ntg::color<T>&, - const std::string& filename, - const std::string& ext) - { - 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> - void read(abstract::image2d<I>& ima, - const ntg::enum_value<T>&, - const std::string& filename, - const std::string& ext) - { - 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/write_image.hh --- oln/io/write_image.hh (revision 53) +++ oln/io/write_image.hh (working copy) @@ -30,6 +30,7 @@ # include <string> +# include <oln/io/gz_stream.hh> # include <oln/io/utils.hh> # include <oln/io/write_image_2d_pnm.hh> @@ -38,22 +39,68 @@ namespace io { template <typename I> - void write(const abstract::image<I>& im, const std::string& name) + void do_write(const abstract::image<I>& ima, + std::ostream& ostr, + const std::string& ext) { + typedef oln_type_of(I, value) value_type; + value_type t; + + impl::write(ima.exact(), t, ostr, ext); + } + +#if defined HAVE_ZLIB && HAVE_ZLIB == 1 + template <typename I> + void write_gz(const abstract::image<I>& ima, const std::string& name) + { + gz::zofstream zostr(name.c_str(), std::ios::out); + + if (zostr.is_open() == false) + std::cerr << "error: couldn't open " << name << std::endl; + else + { + std::string ext; + + ext = internal::utils::extension(name.substr(0, name.size() - 3)); + do_write(ima, zostr, ext); + } + zostr.close(); + } + +#endif // ! HAVE_ZLIB + + template <typename I> + void write_non_gz(const abstract::image<I>& ima, + const std::string& name, + const std::string& ext) + { + std::ofstream ostr; + + ostr.open(name.c_str(), std::ifstream::out); + + if (ostr.is_open() == false) + std::cerr << "error: couldn't open " << name << std::endl; + else + do_write(ima, ostr, ext); + ostr.close(); + } + + template <typename I> + void write(const abstract::image<I>& ima, const std::string& name) + { std::string ext; oln_type_of(I, value) t; ext = internal::utils::extension(name); - if (ext == "pgm" || - ext == "ppm" || - ext == "pbm") - impl::write(im.exact(), t, name, ext); +#if defined HAVE_ZLIB && HAVE_ZLIB == 1 + if (ext == "gz") + write_gz(ima, name); else - std::cerr << "error: output method for '" - << name.c_str() - << "' not implemented" - << std::endl; + write_non_gz(ima, name, ext); +# else + write_non_gz(ima, name, ext); +#endif // ! HAVE_ZLIB } } Index: oln/io/read_image.hh --- oln/io/read_image.hh (revision 53) +++ oln/io/read_image.hh (working copy) @@ -33,8 +33,12 @@ # include <mlc/box.hh> +# include <ntg/core/macros.hh> + +# include <oln/core/properties.hh> # include <oln/io/read_image_2d_pnm.hh> # include <oln/io/utils.hh> +# include <oln/io/gz_stream.hh> namespace oln { @@ -59,28 +63,102 @@ return tmp; } + template <typename I> - void do_read(abstract::image<I>& ima, const filename& name) + void read_dispatch_ext(abstract::image<I>& ima, + std::istream& istr, + const std::string& ext) + { - std::string ext; - const oln_type_of(I, value) t; + if (ext == "pgm" || ext == "pbm" || ext == "ppm" || + ext == "pnm") + { + internal::pnm_info info; - ext = internal::utils::extension(name.get()); + if (internal::read_pnm_header(istr, info)) + if ((ext == "ppm" || ext == "pnm") && info.type == "P6") + impl::read(ima.exact(), istr, info); + else if ((ext == "ppm" || ext == "pnm") && info.type == "P3") + std::cerr << "error: read_image_2d_ppm_ascii not implemented" + << std::endl; + else if ((ext == "pbm" || ext == "pnm") && info.type == "P4") + impl::read(ima.exact(), istr, info); + else if ((ext == "pbm" || ext == "pnm") && info.type == "P1") + std::cerr << "error: read_image_2d_ppm_ascii not implemented" + << std::endl; + else if ((ext == "pgm" || ext == "pnm") && info.type == "P5") + impl::read(ima.exact(), istr, info); + else if ((ext == "pgm" || ext == "pnm") && info.type == "P2") + 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: unable to get a valid header" << std::endl; + } + else + std::cout << "no input method for '" + << ext << "' file extension" + << std::endl; + } - if (ext == "pgm" || - ext == "pbm" || - ext == "ppm") - impl::read(ima.exact(), t, name.get(), ext); +#if defined HAVE_ZLIB && HAVE_ZLIB == 1 + template <typename I> + void do_read_gz(abstract::image<I>& ima, const std::string& name) + { + gz::zifstream zistr(name.c_str(), std::ios::in); + + if (zistr.is_open() == false) + std::cerr << "error: couldn't open " << name << std::endl; else { - std::cout << "input method for '" - << name.get() - << "' not implemented" - << std::endl; + std::string ext; + + ext = internal::utils::extension(name.substr(0, name.size() - 3)); + read_dispatch_ext(ima, zistr, ext); } + zistr.close(); + } +#endif // ! HAVE_ZLIB + + template <typename I> + void do_read_non_gz(abstract::image<I>& ima, + const std::string& name, + const std::string& ext) + { + std::ifstream istr; + + istr.open(name.c_str(), std::ifstream::in); + + if (istr.is_open() == false) + std::cerr << "error: couldn't open " << name << std::endl; + else + read_dispatch_ext(ima, istr, ext); + istr.close(); } + template <typename I> + void do_read(abstract::image<I>& ima, const filename& name) + { + std::string ext; + + ext = internal::utils::extension(name.get()); + +#if defined HAVE_ZLIB && HAVE_ZLIB == 1 + + if (ext == "gz") + do_read_gz(ima, name.get()); + else + do_read_non_gz(ima, name.get(), ext); +#else + do_read_non_gz(ima, name.get(), ext); +#endif // ! HAVE_ZLIB + } + + } } Index: oln/io/utils.hh --- oln/io/utils.hh (revision 53) +++ oln/io/utils.hh (working copy) @@ -76,17 +76,13 @@ std::string type; }; - bool read_pnm_header(std::ifstream& istr, - internal::pnm_info& info, - const std::string& name) + bool read_pnm_header(std::istream& istr, + internal::pnm_info& info) { - istr.open(name.c_str(), std::ifstream::in); - - if (!istr.is_open()) - return false; - std::getline(istr, info.type); + info.max_val = 1; + // skip comments while (istr.peek() == '#') { @@ -121,11 +117,9 @@ std::getline(istr, line); } - // FIXME: it can be either '\n', 'whitespace', ..., not only '\n'! - - // extract or skip maxvalue if (istr.get() != '\n') return false; + // extract or skip maxvalue if (info.type != "P1" && info.type != "P4") { istr >> info.max_val; @@ -137,29 +131,15 @@ return true; } - bool write_pnm_header(std::ofstream& ostr, - const std::string& name, + bool write_pnm_header(std::ostream& ostr, const std::string& type, int ncols, int nrows, int max_val) { if (max_val > 65535) - { - std::cerr << "error: can't save " << name - << ", data type too large" - << std::endl; - return false; - } + return false; - ostr.open(name.c_str(), std::ofstream::out); - - if (ostr.is_open() == false) - { - std::cerr << "error: couldn't open " << name << std::endl; - return false; - } - ostr << type << std::endl << "# Olena 1.0" << std::endl << ncols << " " << nrows << std::endl; Index: oln/core/value_box.hh --- oln/core/value_box.hh (revision 53) +++ oln/core/value_box.hh (working copy) @@ -79,6 +79,26 @@ typedef oln_type_of(I, point) point_type; + /// op== + + bool operator==(const value_box<I>& value) const + { + return this->value() == value.value(); + } + + template <typename V> + bool operator==(const V& value) const + { + return this->value() == value; + } + + template <typename V> + bool operator!=(const V& value) const + { + return ! this->operator==(value); + } + + /*! \brief op= ** FIXME:... ** \return (*this) @@ -87,7 +107,7 @@ template <typename V> value_box& operator=(const V& value) { - ima_.set(p_, value); + this->ima_->set(this->p_, value); return *this; } @@ -103,7 +123,7 @@ template <typename II> value_box& operator=(const value_box<II>& rhs) { - ima_.set(p_, rhs); // automatic conversion from rhs to value_type + ima_->set(p_, rhs); // automatic conversion from rhs to value_type return *this; } @@ -118,7 +138,7 @@ template <typename A, typename V> value_box& set(void (I::*method)(A), const V& value) { - ima_.set(p_, method, value); + ima_->set(p_, method, value); return *this; } @@ -133,13 +153,13 @@ template <typename V> operator const V() const { - const V value = ima_.get(p_); + const V value = ima_->get(p_); return value; } operator const value_type() const { - return ima_.get(p_); + return ima_->get(p_); } @@ -156,7 +176,7 @@ const value_type value() const { - return ima_.get(p_); + return ima_->get(p_); } @@ -180,7 +200,7 @@ /// Ctor (restricted access). value_box(abstract::image<I>& ima, const point_type& p) : - ima_(ima.exact()), + ima_(&ima.exact()), p_(p) { } @@ -189,7 +209,7 @@ ! attributes ! *------------*/ - I& ima_; + I* ima_; point_type p_; }; @@ -219,7 +239,25 @@ typedef oln_type_of(I, point) point_type; + /// op== + bool operator==(const value_box<const I>& value) const + { + return this->value() == value.value(); + } + template <typename V> + bool operator==(const V& value) const + { + return this->value() == value; + } + + template <typename V> + bool operator!=(const V& value) const + { + return ! this->operator==(value); + } + + /*! \brief Assignment (op=) is declared but undefined. */ @@ -235,13 +273,13 @@ template <typename V> operator const V() const { - const V value = ima_.get(p_); + const V value = ima_->get(p_); return value; } operator const value_type() const { - return ima_.get(p_); + return ima_->get(p_); } @@ -258,7 +296,7 @@ const value_type value() const { - return ima_.get(p_); + return ima_->get(p_); } // IDEA: provide op-> @@ -284,7 +322,7 @@ /// Ctor (restricted access). value_box(const abstract::image<I>& ima, const point_type& p) : - ima_(ima.exact()), + ima_(&ima.exact()), p_(p) { } @@ -293,7 +331,7 @@ ! attributes ! *------------*/ - const I& ima_; + const I* ima_; point_type p_; }; Index: oln/core/2d/image2d.hh --- oln/core/2d/image2d.hh (revision 53) +++ oln/core/2d/image2d.hh (working copy) @@ -140,7 +140,6 @@ { if (&rhs == this) return *this; - std::cout << "shallow copy" << std::endl; super_type::operator=(rhs); return *this; }; Index: img/lena.pgm.gz Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: img/lena.pgm.gz ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Index: img/lena.pgm Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: img/lena.pgm ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Index: img/chien.pbm.gz Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: img/chien.pbm.gz ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Index: img/chien.pbm Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: img/chien.pbm ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Index: img/lena.ppm.gz Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: img/lena.ppm.gz ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Index: img/lena.ppm Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: img/lena.ppm ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Index: img/lena.pbm.gz Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: img/lena.pbm.gz ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Index: img/lena.pbm Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: img/lena.pbm ___________________________________________________________________ Name: svn:mime-type + application/octet-stream
participants (1)
-
Damien Thivolle