$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
off/save.hh
1 // Copyright (C) 2008, 2009, 2011, 2012 EPITA Research and Development
2 // Laboratory (LRDE)
3 //
4 // This file is part of Olena.
5 //
6 // Olena is free software: you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free
8 // Software Foundation, version 2 of the License.
9 //
10 // Olena is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // 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 // file, or you compile this file and link it with other files to produce
22 // an executable, this file does not by itself cause the resulting
23 // executable to be covered by the GNU General Public License. This
24 // exception does not however invalidate any other reasons why the
25 // executable file might be covered by the GNU General Public License.
26 
27 #ifndef MLN_IO_OFF_SAVE_HH
28 # define MLN_IO_OFF_SAVE_HH
29 
35 
36 # include <cstdlib>
37 
38 # include <iostream>
39 # include <fstream>
40 # include <sstream>
41 
42 # include <string>
43 
44 # include <mln/version.hh>
45 # include <mln/core/alias/complex_image.hh>
46 # include <mln/core/image/complex_neighborhoods.hh>
47 # include <mln/core/image/complex_neighborhood_piter.hh>
48 
49 
50 namespace mln
51 {
52 
53  namespace io
54  {
55 
56  namespace off
57  {
58 
69  void save(const bin_2complex_image3df& ima,
70  const std::string& filename);
71 
82  void save(const int_u8_2complex_image3df& ima,
83  const std::string& filename);
84 
96  void save(const float_2complex_image3df& ima,
97  const std::string& filename);
98 
109  void save(const rgb8_2complex_image3df& ima,
110  const std::string& filename);
111 
112 
113  namespace internal
114  {
115 
116  template <typename I, typename E>
117  struct off_saver : public Object<E>
118  {
120  typedef mln_value(I) value;
121 
123  static const unsigned D = 2;
124 
126  off_saver();
127 
129  void operator()(const I& ima, const std::string& filename) const;
130  };
131 
132 
133  struct bin_off_saver
134  : public off_saver< bin_2complex_image3df, bin_off_saver >
135  {
139  void write_face_data(std::ostream& ostr, const value& v) const;
140  };
141 
142  struct int_u8_off_saver
143  : public off_saver< int_u8_2complex_image3df, int_u8_off_saver >
144  {
146  void write_face_data(std::ostream& ostr, const value& v) const;
147  };
148 
149 
150  /* FIXME: We should turn float_off_saver into a
151  float01_off_saver (see FIXME/comment in implementation
152  below). */
153  struct float_off_saver
154  : public off_saver< float_2complex_image3df, float_off_saver >
155  {
157  void write_face_data(std::ostream& ostr, const value& v) const;
158  };
159 
160 
161  struct rgb8_off_saver
162  : public off_saver< rgb8_2complex_image3df, rgb8_off_saver >
163  {
165  void write_face_data(std::ostream& ostr, const value& v) const;
166  };
167 
168  } // end of namespace mln::io::off::internal
169 
170 
171 
172 # ifndef MLN_INCLUDE_ONLY
173 
174  /*----------.
175  | Facades. |
176  `----------*/
177 
178  inline
179  void
180  save(const bin_2complex_image3df& ima, const std::string& filename)
181  {
182  mln_trace("mln::io::off::save");
183  internal::bin_off_saver()(ima, filename);
184  }
185 
186  inline
187  void
188  save(const int_u8_2complex_image3df& ima, const std::string& filename)
189  {
190  mln_trace("mln::io::off::save");
191  internal::int_u8_off_saver()(ima, filename);
192  }
193 
194  inline
195  void
196  save(const float_2complex_image3df& ima, const std::string& filename)
197  {
198  mln_trace("mln::io::off::save");
199  internal::float_off_saver()(ima, filename);
200  }
201 
202  inline
203  void
204  save(const rgb8_2complex_image3df& ima, const std::string& filename)
205  {
206  mln_trace("mln::io::off::save");
207  internal::rgb8_off_saver()(ima, filename);
208  }
209 
210 
211  /*-------------------------.
212  | Actual implementations. |
213  `-------------------------*/
214 
215  // -------- //
216  // Canvas. //
217  // -------- //
218 
219  namespace internal
220  {
221 
222  template <typename I, typename E>
223  off_saver<I, E>::off_saver()
224  {
225  // Concept checking.
226  void (E::*m1)(std::ostream&, const value&) const =
227  &E::write_face_data;
228  (void) m1;
229  }
230 
231 
232  template <typename I, typename E>
233  void
234  off_saver<I, E>::operator()(const I& ima,
235  const std::string& filename) const
236  {
237  const std::string me = "mln::io::off::save";
238 
239  std::ofstream ostr(filename.c_str());
240  if (!ostr)
241  {
242  std::cerr << me << ": `" << filename << "' invalid file."
243  << std::endl;
244  /* FIXME: Too violent. We should allow the use of
245  exceptions, at least to have Milena's code behave
246  correctly in interpreted environments (std::exit() or
247  std::abort() causes the termination of a Python
248  interpreter, for instance!). */
249  std::exit(1);
250  }
251 
252  /*---------.
253  | Header. |
254  `---------*/
255 
256  /* ``The .off files in the Princeton Shape Benchmark conform
257  to the following standard.'' */
258 
259  /* ``OFF files are all ASCII files beginning with the
260  keyword OFF. '' */
261  ostr << "OFF" << std::endl;
262 
263  // A comment.
264  ostr << "# Generated by " OLN_PACKAGE_STRING " (" OLN_PACKAGE_URL ")"
265  << std::endl
266  << "# " OLN_PACKAGE_AUTHORS
267  << std::endl;
268 
269  /* ``The next line states the number of vertices, the number
270  of faces, and the number of edges. The number of edges can
271  be safely ignored.'' */
272  /* FIXME: This is too long. We shall be able to write
273 
274  ima.domain().template nfaces_of_static_dim<0>()
275 
276  or even
277 
278  ima.template nfaces_of_static_dim<0>().
279  */
280  ostr << ima.domain().cplx().template nfaces_of_static_dim<0>() << ' '
281  << ima.domain().cplx().template nfaces_of_static_dim<2>() << ' '
282  << ima.domain().cplx().template nfaces_of_static_dim<1>()
283  << std::endl;
284 
285  /*-------.
286  | Data. |
287  `-------*/
288 
289  // --------- //
290  // Complex. //
291  // --------- //
292 
293  typedef mln_geom(I) G;
294 
295  // ------------------------------------------ //
296  // Vertices & geometry (vertices locations). //
297  // ------------------------------------------ //
298 
299  /* ``The vertices are listed with x, y, z coordinates, written
300  one per line.'' */
301 
302  // Traverse the 0-faces (vertices).
303  p_n_faces_fwd_piter<D, G> v(ima.domain(), 0);
304  for_all(v)
305  {
306  mln_invariant(v.to_site().size() == 1);
307  ostr << v.to_site().front()[0] << ' '
308  << v.to_site().front()[1] << ' '
309  << v.to_site().front()[2] << std::endl;
310  }
311 
312  // --------------- //
313  // Faces & edges. //
314  // --------------- //
315 
316  /* ``After the list of vertices, the faces are listed, with one
317  face per line. For each face, the number of vertices is
318  specified, followed by indices into the list of
319  vertices.'' */
320 
321  // Traverse the 2-faces (polygons).
322  p_n_faces_fwd_piter<D, G> f(ima.domain(), 2);
323 
324  typedef complex_m_face_neighborhood<D, G> nbh_t;
325  // A neighborhood where neighbors are the set of 0-faces
326  // transitively adjacent to the reference point.
327  nbh_t nbh;
328  mln_fwd_niter(nbh_t) u(nbh, f);
329  /* FIXME: We should be able to pass this value (m) either at
330  the construction of the neighborhood or at the construction
331  of the iterator. */
332  u.iter().set_m(0);
333 
334  // For each (2-)face, iterate on (transitively) ajacent
335  // vertices (0-faces).
336  for_all(f)
337  {
338  unsigned nvertices = 0;
339  std::ostringstream vertices;
340  for_all(u)
341  {
342  // FIXME: Likewise, this is a bit too long...
343  vertices << ' ' << u.unproxy_().face().face_id();
344  ++nvertices;
345  }
346  ostr << nvertices << vertices.str();
347  // Possibly save a value (depends on the actual format).
348  exact(this)->write_face_data(ostr, ima(f));
349  ostr << std::endl;
350  }
351 
352  ostr.close();
353  }
354 
355  // ---------------- //
356  // Specific parts. //
357  // ---------------- //
358 
398  inline
399  void
400  bin_off_saver::write_face_data(std::ostream& /* ostr */,
401  const value& /* v */) const
402  {
403  // Do nothing (no data associated to faces).
404  }
405 
406  inline
407  void
408  int_u8_off_saver::write_face_data(std::ostream& ostr,
409  const value& v) const
410  {
411  /* Using RGBA colors to represent an 8-bit integer value.
412 
413  Each channel (R, G, B) of the color V is an integer in
414  the range 0..255. A fourth channel, A, controls the
415  transparency.
416 
417  We just set the same value for each channel, as the OFF
418  file format does not support gray-level values as-is. */
419  ostr << ' ' << v << ' ' << v << ' ' << v
420  << ' ' << 1.0f << std::endl;
421  }
422 
423  /* FIXME: We should turn float_off_saver into a
424  float01_off_saver to avoid the assertions below. */
425  inline
426  void
427  float_off_saver::write_face_data(std::ostream& ostr,
428  const value& v) const
429  {
430  /* Using RGBA colors to represent a floating-point value.
431 
432  Each channel (R, G, B) of the color V is a floating-point
433  number in the range 0..1. A fourth channel, A, controls
434  the transparency.
435 
436  We just set the same value for each channel, as the OFF
437  file format does not support gray-level values as
438  such. */
439  mln_assertion(0.0f <= v);
440  mln_assertion(v <= 1.0f);
441  ostr << ' ' << v << ' ' << v << ' ' << v
442  << ' ' << 1.0f;
443  }
444 
445  inline
446  void
447  rgb8_off_saver::write_face_data(std::ostream& ostr,
448  const value& v) const
449  {
450  /* RGBA color.
451 
452  Each channel (R, G, B) of the color V is an integer in
453  the range 0..255. A fourth channel, A, controls the
454  transparency. */
455  ostr << ' ' << v.red() << ' ' << v.green() << ' ' << v.blue()
456  << ' ' << 1.0f;
457  }
458  /* \} */
459 
460  } // end of namespace mln::io::off::internal
461 
462 
463 # endif // ! MLN_INCLUDE_ONLY
464 
465  } // end of namespace mln::io::off
466 
467  } // end of namespace mln::io
468 
469 } // end of namespace mln
470 
471 
472 #endif // ! MLN_IO_OFF_SAVE_HH