save.hh 5.24 KB
Newer Older
1
2
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
// 2010 EPITA Research and Development Laboratory (LRDE)
3
//
4
// This file is part of Olena.
5
//
6
7
8
9
10
// Olena is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, version 2 of the License.
//
// Olena is distributed in the hope that it will be useful,
11
12
13
14
15
// 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
16
// along with Olena.  If not, see <http://www.gnu.org/licenses/>.
17
18
//
// As a special exception, you may use this file as part of a free
19
// software project without restriction.  Specifically, if other files
20
// instantiate templates or use macros or inline functions from this
21
22
23
24
25
// 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.
26
27
28
29

#ifndef MLN_IO_PNM_SAVE_HH
# define MLN_IO_PNM_SAVE_HH

30
/// \file
31
32
33
///
/// Define a function which saves an image of kind PNM into
/// given path.
34
35
36
37
38

# include <iostream>
# include <fstream>

# include <mln/core/concept/image.hh>
39
# include <mln/core/alias/point2d.hh>
Guillaume Lazzara's avatar
Guillaume Lazzara committed
40
# include <mln/value/concept/scalar.hh>
41
42
43
44
45
46

# include <mln/value/rgb.hh>
# include <mln/value/rgb8.hh>
# include <mln/value/int_u8.hh>

# include <mln/metal/templated_by.hh>
Guillaume Lazzara's avatar
Guillaume Lazzara committed
47
# include <mln/metal/not_equal.hh>
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

# include <mln/io/pnm/save_header.hh>
# include <mln/io/pnm/macros.hh>

# include <mln/geom/size2d.hh>


namespace mln
{

  namespace io
  {

    namespace pnm
    {

Roland Levillain's avatar
Roland Levillain committed
64
      /*! Save a Milena image as a pnm image.
65
66
67
68
69
70
       *
       * \param[in] type The type of the image to save (can be PPM,
       * PGM, PBM).
       * \param[in] ima_ The image to save.
       * \param[in,out] filename the destination.
       */
71
      template <typename I>
72
73
      void save(char type, const Image<I>& ima_, const std::string& filename);

74
75
76
77
78
79
80
81
82


# ifndef MLN_INCLUDE_ONLY

      namespace impl
      {

	// write a rgb value into for uncontiguous datas
	template <unsigned int n>
83
	inline
84
85
86
	void write_value(std::ofstream& file,
			 const value::rgb<n>& c)
	{
87
	  typedef typename value::int_u<n>::enc E;
88
89
90
91
92
93
94
95
96
97
98

	  E v = c.red().to_enc();
	  file.write((char*)&v, sizeof(E));
	  v = c.green().to_enc();
	  file.write((char*)&v, sizeof(E));
	  v = c.blue().to_enc();
	  file.write((char*)&v, sizeof(E));
	}

	// write a scalar value into for uncontiguous datas
	template <typename V>
99
	inline
100
	void write_value(std::ofstream& file,
101
			 const V& v)
102
	{
Guillaume Lazzara's avatar
Guillaume Lazzara committed
103
104
105
106
107
108
109
110
111
112
113
	  mlc_not_equal(V,bool)::check();
	  file.write((char*)(&v), sizeof(V));
	}

	// write a scalar value into for uncontiguous datas
	template <typename S>
	inline
	void write_value(std::ofstream& file,
			 const value::Scalar<S>& s)
	{
	  typedef typename S::enc E;
114

Guillaume Lazzara's avatar
Guillaume Lazzara committed
115
	  E c = s.to_enc();
116
117
118
119
120
	  file.write((char*)(&c), sizeof(E));
	}

	// save data for (sizeof(int_u8) != 1) and non fastest images
	template <typename I>
121
	inline
122
123
124
	void save_data_uncontiguous(std::ofstream& file,
				    const I& ima)
	{
125
	  const def::coord
126
127
128
129
130
131
132
133
134
135
136
137
138
139
	    min_row = geom::min_row(ima),
	    max_row = geom::max_row(ima),
	    min_col = geom::min_col(ima),
	    max_col = geom::max_col(ima);

	  point2d p;
	  for (p.row() = min_row; p.row() <= max_row; ++p.row())
	    for (p.col() = min_col; p.col() <= max_col; ++p.col())
	      write_value(file, ima(p));
	}

	// save data when (sizeof(int_u8) == 1) with fastest images
	// (faster)
	template <typename I>
140
	inline
141
142
143
144
	void save_data_contiguous(std::ofstream& file,
				  const I& ima_)
	{
	  const I& ima = exact(ima_);
145
	  const def::coord
146
147
148
149
	    min_row = geom::min_row(ima),
	    max_row = geom::max_row(ima);
	  point2d p;
	  p.col() = geom::min_col(ima);
150
	  std::size_t len = geom::ncols(ima) * sizeof(mln_value(I));
151
152
153
154
155
156
157
	  for (p.row() = min_row; p.row() <= max_row; ++p.row())
	    file.write((char*)(& ima(p)), len);
	}


	// caller for fastest images
	template <typename I>
158
	inline
159
160
161
	void save_data_(std::ofstream& file,
			trait::image::speed::fastest, const I& ima)
	{
162
	  // FIXME: GCC 4.1.1 crashes on that line.
163
164
165
166
167
168
169
170
	  if (sizeof(value::int_u8) == 1)
	    save_data_contiguous(file, ima);
	  else
	    save_data_uncontiguous(file, ima);
	}

	// caller for non fastest images
	template <typename I>
171
	inline
172
173
174
175
176
177
178
179
180
181
182
183
	void save_data_(std::ofstream& file,
			trait::image::speed::any, const I& ima)
	{
	  save_data_uncontiguous(file, ima);
	}

      } // end of namespace mln::io::pnm::impl


	// Facades.

      template <typename I>
184
      inline
185
      void save(char type, const Image<I>& ima_, const std::string& filename)
186
      {
187
	trace::entering("mln::io::pnm::save");
188
189
190
191
192
193
	const I& ima = exact(ima_);
	std::ofstream file(filename.c_str());
	io::pnm::save_header(type, ima, filename, file);

	impl::save_data_(file,
			 mln_trait_image_speed(I)(), ima);
194
	trace::exiting("mln::io::pnm::save");
195
196
197
198
199
200
201
202
203
204
205
206
      }

# endif // ! MLN_INCLUDE_ONLY

    } // end of namespace mln::io::pnm

  } // end of namespace mln::io

} // end of namespace mln


#endif // ! MLN_IO_PNM_SAVE_HH