Index: ChangeLog
from Damien Thivolle <damien(a)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