
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena ChangeLog: 2007-09-17 Matthieu Garrigues <garrigues@lrde.epita.fr> Improve pnm support. * mln/io/fits/load.hh: start debug, only the first column of the image is filled * mln/io/internal/pnm/load.hh: add a second funtion to load a function load(ima, filename). Then we can check if ima is the right type to load the image in the file filename. * mln/io/internal/pnm/load_header.hh: update read_header to get the maxvalue of the pnm header. We need it to check if max(mln_value(I)) == maxval * mln/io/internal/pnm/save.hh: * mln/io/internal/pnm/save_header.hh: change save_header(type, maxval, ima, filename, file) to save_header(type, maxval, ima, filename, file) * mln/io/pbm/save.hh: * mln/io/pgm/load.hh: * mln/io/pgm/save.hh: * mln/io/ppm/load.hh: update to support save_header changes * sandbox/garrigues/io_fits.cc: start debuging io fits * tests/io_pgm.cc: * tests/io_pgm19.cc: * tests/io_pgm27.cc: * tests/io_ppm23.cc: * tests/new_io_pgm.cc: tests. save pgm and ppm N bits works. --- mln/io/fits/load.hh | 3 + mln/io/internal/pnm/load.hh | 49 ++++++++++++++++ mln/io/internal/pnm/load_header.hh | 27 ++++++--- mln/io/internal/pnm/save.hh | 7 +- mln/io/internal/pnm/save_header.hh | 26 ++++++-- mln/io/pbm/save.hh | 3 - mln/io/pgm/load.hh | 7 ++ mln/io/pgm/save.hh | 20 +----- mln/io/ppm/load.hh | 7 ++ sandbox/garrigues/io_fits.cc | 14 ++++ tests/io_pgm.cc | 7 -- tests/io_pgm19.cc | 95 +++++++++++++++++++++++++++++++ tests/io_pgm27.cc | 94 +++++++++++++++++++++++++++++++ tests/io_ppm23.cc | 110 +++++++++++++++++++++++++++++++++++++ tests/new_io_pgm.cc | 55 ++++++++++++++++++ 15 files changed, 478 insertions(+), 46 deletions(-) Index: trunk/milena/tests/io_pgm.cc =================================================================== --- trunk/milena/tests/io_pgm.cc (revision 1119) +++ trunk/milena/tests/io_pgm.cc (revision 1120) @@ -33,7 +33,6 @@ #include <mln/core/image2d_b.hh> #include <mln/value/int_u8.hh> -#include <mln/value/rgb8.hh> #include <mln/io/pgm/load.hh> #include <mln/io/pgm/save.hh> @@ -42,12 +41,6 @@ { using namespace mln; using value::int_u8; - using value::rgb8; - - // { - // // image2d_b<rgb8> - // // lena = io::pgm::load<rgb8>("../img/lena.pgm"); - // } { image2d_b<int_u8> Index: trunk/milena/tests/io_pgm19.cc =================================================================== --- trunk/milena/tests/io_pgm19.cc (revision 0) +++ trunk/milena/tests/io_pgm19.cc (revision 1120) @@ -0,0 +1,95 @@ +// Copyright (C) 2007 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. + +/*! \file tests/pbm_load.cc + * + * \brief Test on mln::io::pbm::load. + */ + +#include <mln/core/image2d_b.hh> + +#include <mln/value/int_u8.hh> + +#include <mln/io/pgm/load.hh> +#include <mln/io/pgm/save.hh> + +#include <mln/level/transform.hh> +#include <mln/level/compare.hh> + + + using namespace mln; + +struct to19bits : mln::Function_v2v<to19bits> +{ + + typedef value::int_u<19> result; + result operator()(value::int_u8 v) const + { + result ret(v * 524288); + return ret; + } +}; + +struct to8bits : mln::Function_v2v<to8bits> +{ + + typedef value::int_u8 result; + result operator()(value::int_u<19> v) const + { + result ret(v / 524288); + return ret; + } +}; + +int main() +{ + using namespace mln; + using value::int_u8; + using value::int_u; + typedef value::int_u<19> int_u19; + + border::thickness = 52; + + image2d_b<int_u8> + lena = io::pgm::load<int_u8>("../img/lena.pgm"); + image2d_b<int_u19> out(lena.domain()); + + level::transform(lena, to19bits(), out); + + io::pgm::save(out, "out19.pgm"); + + image2d_b<int_u19> + lena2 = io::pgm::load<int_u19>("out19.pgm"); + image2d_b<int_u8> out2(lena.domain()); + + level::transform(lena2, to8bits(), out2); + + io::pgm::save(out2, "out8.pgm"); + + assert(out2 == lena); + +} Index: trunk/milena/tests/io_ppm23.cc =================================================================== --- trunk/milena/tests/io_ppm23.cc (revision 0) +++ trunk/milena/tests/io_ppm23.cc (revision 1120) @@ -0,0 +1,110 @@ +// Copyright (C) 2007 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. + +/*! \file tests/pbm_load.cc + * + * \brief Test on mln::io::pbm::load for 23bits ppm + */ + +#include <mln/core/image2d_b.hh> +#include <mln/core/win/rectangle2d.hh> + +#include <mln/value/rgb8.hh> + +#include <mln/io/ppm/load.hh> +#include <mln/io/ppm/save.hh> + +#include <mln/level/compare.hh> + + +using namespace mln; + +typedef value::rgb<23> rgb23; + +struct to23bits : mln::Function_v2v<to23bits> +{ + + typedef rgb23 result; + result operator()(value::rgb8 v) const + { + result ret(v.red().to_enc() * 256, + v.green().to_enc() * 256, + v.blue().to_enc() * 256); + return ret; + } +}; + +struct to8bits : mln::Function_v2v<to8bits> +{ + + typedef value::rgb8 result; + result operator()(rgb23 v) const + { + result ret(v.red().to_enc() / 256, + v.green().to_enc() / 256, + v.blue().to_enc() / 256); + return ret; + } +}; + +int main() +{ + using namespace mln; + using value::rgb8; + + typedef image2d_b<rgb8> I; + + + // load a 8bits image A + image2d_b<rgb8> + a = io::ppm::load<rgb8>("../img/lena.ppm"); + image2d_b<rgb23> b(a.domain()); + + image2d_b<rgb8>::fwd_piter p(b.domain()); + + // save it as a 23bits ppm image B + to23bits f; + for_all(p) + b(p) = f(a(p)); + io::ppm::save(b, "out23.ppm"); + + // reload B into C + image2d_b<rgb23> + c = io::ppm::load<rgb23>("out23.ppm"); + image2d_b<rgb8> d(a.domain()); + + + // save C as a 8bits ppm image D + to8bits g; + for_all(p) + d(p) = g(c(p)); + io::ppm::save(d, "out8.ppm"); + + // D should equals A + mln_assertion(d == a); + +} Index: trunk/milena/tests/new_io_pgm.cc =================================================================== --- trunk/milena/tests/new_io_pgm.cc (revision 0) +++ trunk/milena/tests/new_io_pgm.cc (revision 1120) @@ -0,0 +1,55 @@ +// Copyright (C) 2007 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. + +/*! \file tests/ppm_load.cc + * + * \brief Test on mln::io::ppm::load. + */ + +#include <mln/core/image2d_b.hh> + +#include <mln/value/int_u8.hh> +#include <mln/value/int_u.hh> +#include <mln/value/rgb8.hh> + +#include <mln/io/pgm/load.hh> +#include <mln/io/pgm/save.hh> + +int main() +{ + using namespace mln; + using value::int_u8; + using value::rgb8; + + { + image2d_b< value::int_u<8> > + lena; + io::pgm::load(lena, "../img/lena.pgm"); + + io::pgm::save(lena, "out.pgm"); + } +} Index: trunk/milena/tests/io_pgm27.cc =================================================================== --- trunk/milena/tests/io_pgm27.cc (revision 0) +++ trunk/milena/tests/io_pgm27.cc (revision 1120) @@ -0,0 +1,94 @@ +// Copyright (C) 2007 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. + +/*! \file tests/pbm_load.cc + * + * \brief Test on mln::io::pbm::load. + */ + +#include <mln/core/image2d_b.hh> + +#include <mln/value/int_u8.hh> + +#include <mln/io/pgm/load.hh> +#include <mln/io/pgm/save.hh> + +#include <mln/level/transform.hh> +#include <mln/level/compare.hh> + + + using namespace mln; + +struct to27bits : mln::Function_v2v<to27bits> +{ + + typedef value::int_u<27> result; + result operator()(value::int_u8 v) const + { + result ret(v * 524288); + return ret; + } +}; + +struct to8bits : mln::Function_v2v<to8bits> +{ + + typedef value::int_u8 result; + result operator()(value::int_u<27> v) const + { + result ret(v / 524288); + return ret; + } +}; + +int main() +{ + using namespace mln; + using value::int_u8; + using value::int_u; + typedef value::int_u<27> int_u27; + + image2d_b<int_u8> + lena = io::pgm::load<int_u8>("../img/lena.pgm"); + image2d_b<int_u27> out(lena.domain()); + + level::transform(lena, to27bits(), out); + + io::pgm::save(out, "out27.pgm"); + + image2d_b<int_u27> lena2; + io::pgm::load(lena2, "out27.pgm"); + + image2d_b<int_u8> out2(lena.domain()); + + level::transform(lena2, to8bits(), out2); + + io::pgm::save(out2, "out8.pgm"); + + assert(out2 == lena); + +} Index: trunk/milena/mln/io/pgm/save.hh =================================================================== --- trunk/milena/mln/io/pgm/save.hh (revision 1119) +++ trunk/milena/mln/io/pgm/save.hh (revision 1120) @@ -35,7 +35,7 @@ # include <mln/io/internal/pnm/save.hh> # include <mln/geom/size2d.hh> -# include <mln/metal/equal.hh> +# include <mln/metal/templated_by.hh> # include <mln/metal/bexpr.hh> @@ -61,26 +61,12 @@ # ifndef MLN_INCLUDE_ONLY - namespace impl - { - - } // end of namespace mln::io::impl - - template <typename I> void save(const Image<I>& ima, const std::string& filename) { mln::metal::or_< - mln::metal::equal<mln_value(I), value::int_u<8> >, - - mln::metal::or_< - mln::metal::equal<mln_value(I), value::int_u_sat<8> >, - - mln::metal::or_< - mln::metal::equal<mln_value(I), value::int_u<16> >, - mln::metal::equal<mln_value(I), value::int_u_sat<16> > - > - > + mln::metal::templated_by<mln_value(I), value::int_u >, + mln::metal::templated_by<mln_value(I), value::int_u_sat > >::check(); io::internal::pnm::save(PGM, exact(ima), filename); } Index: trunk/milena/mln/io/pgm/load.hh =================================================================== --- trunk/milena/mln/io/pgm/load.hh (revision 1119) +++ trunk/milena/mln/io/pgm/load.hh (revision 1120) @@ -34,6 +34,7 @@ # include <string> # include <mln/core/image2d_b.hh> + # include <mln/value/int_u8.hh> # include <mln/io/internal/pnm/load.hh> @@ -59,6 +60,12 @@ return load<value::int_u8>(filename); } + template <typename I> + void load(Image<I>& ima, + const std::string& filename) + { + io::internal::pnm::load<I>(PGM, ima, filename); + } } // end of namespace mln::io::pgm } // end of namespace mln::io Index: trunk/milena/mln/io/fits/load.hh =================================================================== --- trunk/milena/mln/io/fits/load.hh (revision 1119) +++ trunk/milena/mln/io/fits/load.hh (revision 1120) @@ -75,6 +75,9 @@ const int ncols = naxes[0], nrows = naxes[1]; + std::cout << "ncols : " << ncols + << "nrows : " << nrows << std::endl; + image2d_b<float> output(nrows, ncols); nullval = 0; // don't check null values Index: trunk/milena/mln/io/ppm/load.hh =================================================================== --- trunk/milena/mln/io/ppm/load.hh (revision 1119) +++ trunk/milena/mln/io/ppm/load.hh (revision 1120) @@ -57,6 +57,13 @@ return load< value::rgb8 >(filename); } + template <typename I> + void load(Image<I>& ima, + const std::string& filename) + { + io::internal::pnm::load<I>(PPM, ima, filename); + } + } // end of namespace mln::io::ppm } // end of namespace mln::io Index: trunk/milena/mln/io/internal/pnm/save_header.hh =================================================================== --- trunk/milena/mln/io/internal/pnm/save_header.hh (revision 1119) +++ trunk/milena/mln/io/internal/pnm/save_header.hh (revision 1120) @@ -32,6 +32,8 @@ # include <iostream> # include <fstream> +# include <mln/value/rgb.hh> + namespace mln { @@ -46,6 +48,20 @@ namespace pnm { + template <typename V> + void save_max_val(V&, std::ofstream& file) + { + if (mln_max(V) > 1) + file << mln_max(V) << std::endl; + } + + template <unsigned int n> + void save_max_val(value::rgb<n>&, std::ofstream& file) + { + typedef typename value::rgb<n>::enc E; + file << mln_max(E) << std::endl; + } + template <typename I> void save_header(const char type, const I& ima, const std::string& filename, @@ -60,15 +76,9 @@ file << "P" << type << std::endl; file << "# milena" << std::endl; file << geom::ncols(ima) << ' ' << geom::nrows(ima) << std::endl; - } - template <typename I> - void save_header(const char type, const int maxval, - const I& ima, const std::string& filename, - std::ofstream& file) - { - save_header(type, ima, filename, file); - file << maxval << std::endl; + mln_value(I) i; + save_max_val(i, file); } } // end of namespace mln::io::internal::pnm Index: trunk/milena/mln/io/internal/pnm/load_header.hh =================================================================== --- trunk/milena/mln/io/internal/pnm/load_header.hh (revision 1119) +++ trunk/milena/mln/io/internal/pnm/load_header.hh (revision 1120) @@ -46,9 +46,10 @@ { - bool read_header(std::istream& istr, + bool read_header(std::ifstream& istr, char& type, int& nrows, int& ncols, + unsigned int& maxval, bool test = false) { // check magic @@ -73,13 +74,14 @@ if (nrows <= 0 || ncols <= 0) goto err; - // skip maxvalue + // get maxvalue if (istr.get() != '\n') goto err; if (type != '1' && type != '4') { - std::string line; - std::getline(istr, line); + istr >> maxval; + if (istr.get() != '\n') + goto err; } return true; @@ -93,11 +95,12 @@ } void read_header(char ascii, char raw, - std::istream& istr, + std::ifstream& istr, char& type, - int& nrows, int& ncols) + int& nrows, int& ncols, + unsigned int& maxval) { - read_header(istr, type, nrows, ncols); + read_header(istr, type, nrows, ncols, maxval); if (! (type == ascii || type == raw)) { std::cerr << "error: bad pnm type; " @@ -108,6 +111,16 @@ } } + void read_header(char ascii, char raw, + std::ifstream& istr, + char& type, + int& nrows, int& ncols) + { + unsigned int maxval; + read_header(ascii, raw, istr, type, + nrows, ncols, maxval); + } + } // end of namespace mln::io::internal::pnm } // end of namespace mln::io::internal Index: trunk/milena/mln/io/internal/pnm/save.hh =================================================================== --- trunk/milena/mln/io/internal/pnm/save.hh (revision 1119) +++ trunk/milena/mln/io/internal/pnm/save.hh (revision 1120) @@ -41,8 +41,11 @@ # include <mln/core/concept/image.hh> # include <mln/value/rgb.hh> +# include <mln/value/rgb8.hh> # include <mln/value/int_u8.hh> +# include <mln/metal/templated_by.hh> + # include <mln/io/internal/pnm/save_header.hh> # include <mln/io/internal/pnm/macros.hh> @@ -150,8 +153,8 @@ { const I& ima = exact(ima_); std::ofstream file(filename.c_str()); - io::internal::pnm::save_header(type, mln_max(mln_value(I)::enc), - ima, filename, file); + io::internal::pnm::save_header(type, ima, filename, file); + save_data(file, ima); } Index: trunk/milena/mln/io/internal/pnm/load.hh =================================================================== --- trunk/milena/mln/io/internal/pnm/load.hh (revision 1119) +++ trunk/milena/mln/io/internal/pnm/load.hh (revision 1120) @@ -158,7 +158,9 @@ } char type = 0; int nrows, ncols; - read_header(type_ - 3, type_, file, type, nrows, ncols); + unsigned int maxval; + read_header(type_ - 3, type_, file, type, + nrows, ncols, maxval); image2d_b<V> ima(nrows, ncols); if (type == type_) @@ -170,6 +172,51 @@ } + /// a new function to load pnm files : + /// the destination is an argument to check if + /// the type match the file to load. + template <typename I> + void load(char type_, + Image<I>& ima_, + const std::string& filename) + { + std::ifstream file(filename.c_str()); + if (! file) + { + std::cerr << "error: file '" << filename + << "' not found!"; + abort(); + } + + I& ima = exact(ima_); + + char type = 0; + int nrows, ncols; + unsigned int maxval; + read_header(type_ - 3, type_, file, type, + nrows, ncols, maxval); + + if (value::props< mln_value(I) >::max() != maxval) + { + std::cerr << "max ref : " << value::props< mln_value(I) >::max() + << "max image : " << maxval + << std::endl; + + std::cerr << "error: file '" << filename + << "' cannot be loaded into this type of image" + << std::endl; + abort(); + } + + ima.init_with(nrows, ncols); + if (type == type_) + load_raw_2d(file, ima); + else + if (type == (type_ - 3)) + pnm::load_ascii(file, ima); + + } + # endif // ! MLN_INCLUDE_ONLY } // end of namespace mln::io::internal::pnm Index: trunk/milena/mln/io/pbm/save.hh =================================================================== --- trunk/milena/mln/io/pbm/save.hh (revision 1119) +++ trunk/milena/mln/io/pbm/save.hh (revision 1120) @@ -70,8 +70,7 @@ const I& ima = exact(ima_); std::ofstream file(filename.c_str()); - //FIXME : why do we need a max val??? - io::internal::pnm::save_header(PBM, 255, ima, filename, file); + io::internal::pnm::save_header(PBM, ima, filename, file); const int min_row = geom::min_row(ima), Index: trunk/milena/sandbox/garrigues/io_fits.cc =================================================================== --- trunk/milena/sandbox/garrigues/io_fits.cc (revision 1119) +++ trunk/milena/sandbox/garrigues/io_fits.cc (revision 1120) @@ -33,6 +33,7 @@ #include <mln/core/image2d_b.hh> #include <mln/level/compare.hh> +#include <mln/debug/println.hh> #include <mln/io/fits/load.hh> #include <mln/io/pfm/save.hh> @@ -43,7 +44,9 @@ using namespace mln; { image2d_b<float> - fits_in = io::fits::load("../img/test.fits"); + fits_in = io::fits::load("../../img/test.fits"); + + debug::println(fits_in); io::pfm::save(fits_in, "out.pfm"); @@ -55,7 +58,14 @@ image2d_b<float> pfm2 = io::pfm::load("out2.pfm"); - mln_assertion(pfm == pfm2); + image2d_b<float>::fwd_piter p(fits_in.domain()); + for_all(p) + if (fits_in(p) != pfm(p)) + std::cout << "at " << p + << " ref :" << fits_in(p) + << " pfm2 : " << pfm(p) << std::endl; + + mln_assertion(fits_in == pfm2); // } // {