2006-10-10 Thierry GERAUD <theo(a)tegucigalpa.lrde.epita.fr>
Add i/o read for pbm and pgm formats.
* tests/io_pnm.cc: New.
* tests/Makefile.am (check_PROGRAMS): Update.
* oln/io: New directory.
* oln/io/pnm.hh: New.
* oln/core/image_entry.hh (coord_type): New single_vtype.
* oln/core/abstract/image.hh (decl): New comment.
* oln/core/2d/image2d.hh (adr_at): New.
* oln/basics2d.hh (include): Add fwd_piter.hh.
* oln/Makefile.am (nobase_oln_HEADERS): Update.
* img: New directory.
* img/chien.pbm: New.
* img/lena32.pgm: New.
Index: tests/io_pnm.cc
===================================================================
--- tests/io_pnm.cc (revision 0)
+++ tests/io_pnm.cc (revision 0)
@@ -0,0 +1,40 @@
+// Copyright (C) 2006 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, 51 Franklin Street, Fifth Floor,
+// 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.
+
+/// Test oln::io_pnm.cc.
+
+#include <cassert>
+#include <oln/basics2d.hh>
+#include <oln/io/pnm.hh>
+
+int
+main()
+{
+ // Fill a 2-d image using its iterator.
+ oln::image2d<bool> ima =
oln::io::load_pbm("../img/chien.pbm");
+ oln::image2d<unsigned char> ima2 =
oln::io::load_pgm("../img/lena32.pgm");
+}
Index: tests/Makefile.am
===================================================================
--- tests/Makefile.am (revision 614)
+++ tests/Makefile.am (working copy)
@@ -25,6 +25,7 @@
image1d \
image2d \
image3d \
+ io_pnm \
npoints \
\
identity_morpher \
Index: oln/io/pnm.hh
===================================================================
--- oln/io/pnm.hh (revision 0)
+++ oln/io/pnm.hh (revision 0)
@@ -0,0 +1,224 @@
+// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 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, 51 Franklin Street, Fifth Floor,
+// 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_PNM_HH
+# define OLN_IO_PNM_HH
+
+# include <iostream>
+# include <fstream>
+# include <string>
+
+# include <oln/core/2d/image2d.hh>
+
+
+namespace oln {
+
+ namespace io {
+
+ namespace internal {
+
+ void abort()
+ {
+ std::cerr << " aborting." << std::endl;
+ exit(0);
+ }
+
+ bool read_pnm_header(std::istream& istr,
+ char& type,
+ int& nrows, int& ncols,
+ bool test = false)
+ {
+ // check magic
+ if (istr.get() != 'P' )
+ goto err;
+ type = istr.get();
+ if (type < '1' or type > '6')
+ goto err;
+ if (istr.get() != '\n')
+ goto err;
+
+ // skip comments
+ while (istr.peek() == '#')
+ {
+ std::string line;
+ std::getline(istr, line);
+ }
+
+ // get size
+ istr >> ncols >> nrows;
+ if (nrows <= 0 or ncols <= 0)
+ goto err;
+
+ // skip maxvalue
+ if (istr.get() != '\n')
+ goto err;
+ if (type != '1' and type != '4')
+ {
+ std::string line;
+ std::getline(istr, line);
+ }
+ return true;
+
+ err:
+ if (not test)
+ {
+ std::cerr << "error: badly formed header!";
+ abort();
+ }
+ return false;
+ }
+
+ void read_pnm_header(char ascii, char raw,
+ std::istream& istr,
+ char& type,
+ int& nrows, int& ncols)
+ {
+ read_pnm_header(istr, type, nrows, ncols);
+ if (not (type == ascii or type == raw))
+ {
+ std::cerr << "error: bad pnm type; "
+ << "expected P" << ascii
+ << " or P" << raw
+ << ", get P" << type << "!";
+ abort();
+ }
+ }
+
+
+ /// load_pbm_raw.
+ template <typename I>
+ void load_pbm_raw(std::ifstream& file, I& ima)
+ {
+ oln_type_of(I, coord) cols = 0;
+ unsigned bits = 0;
+ unsigned char c = 0;
+ oln_type_of(I, fwd_piter) p(ima.topo());
+ for_all(p)
+ {
+ if (bits == 0)
+ {
+ c = file.get();
+ bits = 8;
+ }
+ ima(p) = (c & (1 << --bits)) ? false : true;
+ if (++cols >= int(ima.bbox().ncols()))
+ cols = bits = 0;
+ }
+ }
+
+
+ /// load_pbm_ascii.
+ template <typename I>
+ void load_pbm_ascii(std::ifstream& file, I& ima)
+ {
+ oln_type_of(I, fwd_piter) p(ima.topo());
+ for_all(p)
+ ima(p) = (file.get() == '0');
+ }
+
+
+ /// load_ascii.
+ template <typename I>
+ void load_pnm_ascii(std::ifstream& file, I& ima)
+ {
+ oln_type_of(I, fwd_piter) p(ima.topo());
+ for_all(p)
+ {
+ oln_type_of(I, value) value;
+ file >> value;
+ ima(p) = value;
+ // FIXME: Test alt code below.
+ // file >> ima(p);
+ }
+ }
+
+
+ /// load_raw_2d.
+ template <typename I>
+ void load_pnm_raw_2d(std::ifstream& file, I& ima)
+ {
+ int col = ima.pmin().col();
+ size_t len = ima.bbox().ncols();
+ for (int row = ima.pmin().row(); row <= ima.pmax().row(); ++row)
+ file.read((char*)(ima.adr_at(row, col)),
+ len * sizeof(oln_type_of(I, value)));
+ }
+
+
+ } // end of namespace oln::io::internal
+
+
+ image2d<bool> load_pbm(const std::string& filename)
+ {
+ std::ifstream file(filename.c_str());
+ if (not file)
+ {
+ std::cerr << "error: file '" << filename
+ << "' not found!";
+ abort();
+ }
+ char type;
+ int nrows, ncols;
+ internal::read_pnm_header('1', '4', file, type, nrows, ncols);
+ image2d<bool> ima(nrows, ncols);
+ if (type == '4')
+ internal::load_pbm_raw(file, ima);
+ else
+ // type == '1'
+ internal::load_pbm_ascii(file, ima);
+ return ima;
+ }
+
+
+ image2d<unsigned char> load_pgm(const std::string& filename)
+ {
+ std::ifstream file(filename.c_str());
+ if (not file)
+ {
+ std::cerr << "error: file '" << filename
+ << "' not found!";
+ abort();
+ }
+ char type;
+ int nrows, ncols;
+ internal::read_pnm_header('2', '5', file, type, nrows, ncols);
+ image2d<unsigned char> ima(nrows, ncols);
+ if (type == '4')
+ internal::load_pnm_raw_2d(file, ima);
+ else
+ // type == '1'
+ internal::load_pnm_ascii(file, ima);
+ return ima;
+ }
+
+ } // end of namespace oln::io
+
+} // end of namespace oln
+
+
+#endif // ! OLN_IO_PNM_HH
Index: oln/core/image_entry.hh
===================================================================
--- oln/core/image_entry.hh (revision 614)
+++ oln/core/image_entry.hh (working copy)
@@ -67,6 +67,8 @@
typedef mlc::undefined topo_type;
typedef mlc::undefined grid_type;
+ // coord_type: see below.
+
// psite_type: see below.
typedef mlc::undefined point_type;
@@ -82,13 +84,23 @@
};
+ // Coord.
template <typename E>
+ struct single_vtype< image_entry<E>, typedef_::coord_type >
+ {
+ typedef oln_deduce_type_of(E, point, coord) ret;
+ };
+
+
+ // Psite.
+ template <typename E>
struct single_vtype< image_entry<E>, typedef_::psite_type >
{
typedef oln_type_of(E, point) ret;
};
+ // Piter.
template <typename E>
struct single_vtype< image_entry<E>, typedef_::piter_type >
{
@@ -96,6 +108,7 @@
};
+ // Rvalue.
template <typename E>
struct single_vtype< image_entry<E>, typedef_::rvalue_type >
{
Index: oln/core/abstract/image.hh
===================================================================
--- oln/core/abstract/image.hh (revision 614)
+++ oln/core/abstract/image.hh (working copy)
@@ -66,6 +66,8 @@
// oln_virtual_typedef(topo);
// oln_virtual_typedef(grid);
+// oln_virtual_typedef(coord);
+
// oln_virtual_typedef(psite);
// oln_virtual_typedef(point);
Index: oln/core/2d/image2d.hh
===================================================================
--- oln/core/2d/image2d.hh (revision 614)
+++ oln/core/2d/image2d.hh (working copy)
@@ -89,6 +89,9 @@
T& impl_op_readwrite(const point2d& p);
+ T* adr_at(int row, int col);
+ const T* adr_at(int row, int col) const;
+
private:
topo2d topo_;
@@ -143,6 +146,22 @@
return data_->operator()(p.row(), p.col());
}
+ template <typename T>
+ T* image2d<T>::adr_at(int row, int col)
+ {
+ precondition(data_ != 0);
+ precondition(data_->has(row, col));
+ return &(data_->operator()(row, col));
+ }
+
+ template <typename T>
+ const T* image2d<T>::adr_at(int row, int col) const
+ {
+ precondition(data_ != 0);
+ precondition(data_->has(row, col));
+ return &(data_->operator()(row, col));
+ }
+
# endif
} // end of namespace oln
Index: oln/basics2d.hh
===================================================================
--- oln/basics2d.hh (revision 614)
+++ oln/basics2d.hh (working copy)
@@ -50,5 +50,7 @@
# include <oln/core/2d/image2d.hh>
+# include <oln/core/fwd_piter.hh>
+
#endif // ! OLN_BASICS2D_HH
Index: oln/Makefile.am
===================================================================
--- oln/Makefile.am (revision 614)
+++ oln/Makefile.am (working copy)
@@ -132,6 +132,8 @@
\
debug/print.hh \
\
+ io/pnm.hh \
+ \
level/fill.hh \
\
morpher/internal/image_extension.hh \
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/lena32.pgm
===================================================================
--- img/lena32.pgm (revision 0)
+++ img/lena32.pgm (revision 0)
@@ -0,0 +1,4 @@
+P5
+32 32
+255
+€chmzt¹Šsy{{`£bgly~~~~vv Áw{Y3 ¡ `fkx}~
~~}wt³³uV40¡]dlw|ªysrÆp02.r Xbhsy{w}
«ºÀ°io@02<hk Ybhsxrs{ŠºÇÏÁqhdB/1FyYkYbhtvov«ÀÇËзo>yZ129uZkV`g{ynz¢Ž»ÁÇÉÑ SŠÁK12aao Ycf
xlx§¯±·ŸŸÅÁ¥ ¶ÎÉO-F`p£Zac
l|§ª«±µ²µŸÆÊÀ©<4v_r€Zaav±œÃÉ¿r.Scu¥Ya`¢z~r[fU[¢¿ÀŸ¥|B4wfs€X_a|ª|zbF>H]Ž¶Ž|
F/H£fn£X`ep |vX@C;P°¬»¿mlF32e¡ dl£[cit
xT:6?Sª¥ÃÐRE6=
ck£[ci}naD:6C§y»²pJO4T_d£\`pUKI73j¯qVo«mEFU4n\]€blnZJOU/C®THX<
±NS¡brZSD>V;swv«±cFXM ÀÅHMfhV\D9UVuGu¡§V@^gºÉÍIX¡b]NYYAVrIIw£@>d ÇÎÐA^€f[DR_iQ5Jt d7@fªÏÑÓ7_ŠhSDdcp56Aa~?8Dj³ÕÓÒ1a£^HAdotB548Cbf2>Lmº×Ï·;Ra>A]jqM935>d ^AOo}~ÀÍOwY€Z8GKWse>59Go¡»ÁGqs}ÅTXsp€O1A:KkoI5<UqÃÎirªÇsac_t¢I1A4>foN:KewŠœÒ }Í®gc`Sz£M295@XY<7_hŽËÄ~
Ÿ\^Z[¢M075<^I,BakªÄÐWP«\W]Oi E39B>UA.Od~¡¹Ïa[iOU_FQ<9ANKJBFl|°È°esr`T_X?
\ No newline at end of file