$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
vtk/save.hh
1 // Copyright (C) 2008, 2009, 2010, 2011, 2013 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_VTK_SAVE_HH
28 # define MLN_IO_VTK_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 vtk
57  {
58 
65  void save(const bin_2complex_image3df& ima,
66  const std::string& filename);
67 
74  void save(const int_u8_2complex_image3df& ima,
75  const std::string& filename);
76 
82  void save(const unsigned_2complex_image3df& ima,
83  const std::string& filename);
84 
91  void save(const float_2complex_image3df& ima,
92  const std::string& filename);
93 
99  void save(const rgb8_2complex_image3df& ima,
100  const std::string& filename);
101 
102 
103  namespace internal
104  {
105 
106  template <typename I, typename E>
107  struct vtk_saver : public Object<E>
108  {
110  typedef I image;
111 
113  typedef mln_value(I) value;
114 
116  static const unsigned D = 2;
117 
119  vtk_saver();
120 
122  void operator()(const I& ima, const std::string& filename) const;
123 
124  protected:
127  void write_scalar_data(std::ostream& ostr, const image& ima,
128  const std::string& data_type) const;
129  };
130 
131 
132  struct bin_vtk_saver
133  : public vtk_saver< bin_2complex_image3df, bin_vtk_saver >
134  {
136  void write_face_data(std::ostream& ostr, const image& ima) const;
137  };
138 
139 
140  struct int_u8_vtk_saver
141  : public vtk_saver< int_u8_2complex_image3df, int_u8_vtk_saver >
142  {
144  void write_face_data(std::ostream& ostr, const image& ima) const;
145  };
146 
147 
148  struct unsigned_vtk_saver
149  : public vtk_saver< unsigned_2complex_image3df, unsigned_vtk_saver >
150  {
152  void write_face_data(std::ostream& ostr, const image& ima) const;
153  };
154 
155 
156  struct float_vtk_saver
157  : public vtk_saver< float_2complex_image3df, float_vtk_saver >
158  {
160  void write_face_data(std::ostream& ostr, const image& ima) const;
161  };
162 
163 
164  struct rgb8_vtk_saver
165  : public vtk_saver< rgb8_2complex_image3df, rgb8_vtk_saver >
166  {
168  void write_face_data(std::ostream& ostr, const image& ima) const;
169  };
170 
171  } // end of namespace mln::io::vtk::internal
172 
173 
174 
175 # ifndef MLN_INCLUDE_ONLY
176 
177  /*----------.
178  | Facades. |
179  `----------*/
180 
181  void
182  save(const bin_2complex_image3df& ima, const std::string& filename)
183  {
184  mln_trace("mln::io::vtk::save");
185  internal::bin_vtk_saver()(ima, filename);
186  }
187 
188  void
189  save(const int_u8_2complex_image3df& ima, const std::string& filename)
190  {
191  mln_trace("mln::io::vtk::save");
192  internal::int_u8_vtk_saver()(ima, filename);
193  }
194 
195  void
196  save(const unsigned_2complex_image3df& ima, const std::string& filename)
197  {
198  mln_trace("mln::io::vtk::save");
199  internal::unsigned_vtk_saver()(ima, filename);
200  }
201 
202  void
203  save(const float_2complex_image3df& ima, const std::string& filename)
204  {
205  mln_trace("mln::io::vtk::save");
206  internal::float_vtk_saver()(ima, filename);
207  }
208 
209  void
210  save(const rgb8_2complex_image3df& ima, const std::string& filename)
211  {
212  mln_trace("mln::io::vtk::save");
213  internal::rgb8_vtk_saver()(ima, filename);
214  }
215 
216 
217  /*-------------------------.
218  | Actual implementations. |
219  `-------------------------*/
220 
221  // -------- //
222  // Canvas. //
223  // -------- //
224 
225  namespace internal
226  {
227 
228  template <typename I, typename E>
229  vtk_saver<I, E>::vtk_saver()
230  {
231  // Concept checking.
232  void (E::*m1)(std::ostream&, const I&) const =
233  &E::write_face_data;
234  (void) m1;
235  }
236 
237 
238  template <typename I, typename E>
239  void
240  vtk_saver<I, E>::operator()(const I& ima,
241  const std::string& filename) const
242  {
243  const std::string me = "mln::io::vtk::save";
244 
245  std::ofstream ostr(filename.c_str());
246  if (!ostr)
247  {
248  std::cerr << me << ": `" << filename << "' invalid file."
249  << std::endl;
250  /* FIXME: Too violent. We should allow the use of
251  exceptions, at least to have Milena's code behave
252  correctly in interpreted environments (std::exit() or
253  std::abort() causes the termination of a Python
254  interpreter, for instance!). */
255  std::exit(1);
256  }
257 
258  /*---------.
259  | Header. |
260  `---------*/
261 
262  /* ``The legacy VTK file formats consist of five basic
263  parts.'' */
264 
265  /* ``1. The first part is the file version and
266  identifier. This part contains the single line:
267 
268  # vtk DataFile Version x.x.
269 
270  This line must be exactly as shown with the
271  exception of the version number x.x, which will vary
272  with different releases of VTK. (Note: the current
273  version number is 3.0. Version 1.0 and 2.0 files are
274  compatible with version 3.0 files.)'' */
275  ostr << "# vtk DataFile Version 2.0" << std::endl;
276 
277  /* ``2. The second part is the header. The header consists
278  of a character string terminated by end-of-line
279  character `\n'. The header is 256 characters
280  maximum. The header can be used to describe the data
281  and include any other pertinent information.'' */
282  ostr << "Generated by " OLN_PACKAGE_STRING " (" OLN_PACKAGE_URL ")"
283  << std::endl;
284 
285  /* ``3. The next part is the file format. The file format
286  describes the type of file, either ASCII or
287  binary. On this line the single word ASCII or BINARY
288  must appear.'' */
289  ostr << "ASCII" << std::endl;
290 
291  /*-------.
292  | Data. |
293  `-------*/
294 
295  /* ``4. The fourth part is the dataset structure. The
296  geometry part describes the geometry and topology of
297  the dataset. This part begins with a line containing
298  the keyword DATASET followed by a keyword describing
299  the type of dataset. Then, depending upon the type
300  of dataset, other keyword/data combinations define
301  the actual data.''
302 
303  [...]
304 
305  Dataset Format. The Visualization Toolkit supports
306  five different dataset formats: structured points,
307  structured grid, rectilinear grid, unstructured
308  grid, and polygonal data.'' */
309 
310  ostr << "DATASET POLYDATA" << std::endl << std::endl;
311 
312  // --------- //
313  // Complex. //
314  // --------- //
315 
316  typedef mln_geom(I) G;
317 
318  /* ``* Polygonal Data
319  The polygonal dataset consists of arbitrary
320  combinations of surface graphics primitives
321  vertices (and polyvertices), lines (and
322  polylines), polygons (of various types), and
323  triangle strips. Polygonal data is defined by
324  the POINTS, VERTICES, LINES, POLYGONS, or
325  TRIANGLE_STRIPS sections. The POINTS definition
326  is the same as we saw for structured grid
327  datasets.'' */
328 
329  // ---------------------------- //
330  // Geometry (point locations). //
331  // ---------------------------- //
332 
333  ostr << "POINTS "
334  << ima.domain().cplx().template nfaces_of_static_dim<0>()
335  << " float" << std::endl;
336  // Iterate on 0-faces (vertices).
337  p_n_faces_fwd_piter<D, G> v(ima.domain(), 0);
338  for_all(v)
339  {
340  mln_invariant(v.to_site().size() == 1);
341  ostr << v.to_site().front()[0] << ' '
342  << v.to_site().front()[1] << ' '
343  << v.to_site().front()[2] << std::endl;
344  }
345  ostr << std::endl;
346 
347  /* ``The VERTICES, LINES, POLYGONS, or
348  TRIANGLE_STRIPS keywords define the polygonal
349  dataset topology. Each of these keywords
350  requires two parameters: the number of cells `n'
351  and the size of the cell list `size'. The cell
352  list size is the total number of integer values
353  required to represent the list (i.e., sum of
354  `numPoints' and connectivity indices over each
355  cell). None of the keywords VERTICES, LINES,
356  POLYGONS, or TRIANGLE_STRIPS is required.'' */
357 
358  // ---------- //
359  // Vertices. //
360  // ---------- //
361 
362  /* We do not use
363 
364  ima.domain().cplx().template nfaces_of_static_dim<N>()
365 
366  to get the number of N-faces, since the image may be
367  masked, and exhibit less N-faces than its underlying
368  complex. Iterating on the N-faces is safer. */
369  /* FIXME: Is there anything faster? See what the interface
370  of the (morphed) image can provide. */
371  unsigned nvertices = 0;
372  for_all(v)
373  ++nvertices;
374 
375  if (nvertices > 0)
376  {
377  ostr << "VERTICES " << nvertices << ' '
378  /* Each vertex requires two numbers: the cardinal of
379  its ends (which is always 1) and the indices of the
380  point among the POINTS section. Hence the total
381  number of values in the VERTEX section is
382  nvertices * 2. */
383  << nvertices * 2 << std::endl;
384 
385  for_all(v)
386  ostr << "1 " << v.unproxy_().face().face_id() << std::endl;
387  ostr << std::endl;
388  }
389 
390  // ------- //
391  // Edges. //
392  // ------- //
393 
394  // Same comment as above about the count of N-faces.
395  unsigned nedges = 0;
396  p_n_faces_fwd_piter<D, G> e(ima.domain(), 1);
397  for_all (e)
398  ++nedges;
399 
400  if (nedges > 0)
401  {
402  ostr << "LINES " << nedges << ' '
403  /* Each edge requires three numbers: the cardinal of
404  its ends (which is always 2) and the indices of
405  these ends among the POINTS section. Hence the
406  total number of values in the LINES section is
407  nedges * 3. */
408  << nedges * 3 << std::endl;
409 
410  // Vertices adjacent to edges.
411  typedef complex_lower_neighborhood<D, G> adj_vertices_nbh_t;
412  adj_vertices_nbh_t adj_vertices_nbh;
413  mln_niter(adj_vertices_nbh_t) adj_v(adj_vertices_nbh, e);
414  // Iterate on 1-faces (edges).
415  for_all (e)
416  {
417  ostr << "2";
418  // Iterate on vertices (0-faces).
419  for_all (adj_v)
420  {
421  // FIXME: Accessing the face id is too complicated.
422  ostr << " " << adj_v.unproxy_().face().face_id();
423  }
424  ostr << std::endl;
425  }
426  ostr << std::endl;
427  }
428 
429  // ---------- //
430  // Polygons. //
431  // ---------- //
432 
433  // Same comment as above about the count of N-faces.
434  unsigned npolygons = 0;
435  p_n_faces_fwd_piter<D, G> p(ima.domain(), 2);
436  for_all (p)
437  ++npolygons;
438 
439  if (npolygons > 0)
440  {
441  // A neighborhood where neighbors are the set of 0-faces
442  // transitively adjacent to the reference point.
443  typedef complex_m_face_neighborhood<D, G> nbh_t;
444  nbh_t nbh;
445  mln_fwd_niter(nbh_t) u(nbh, p);
446  /* FIXME: We should be able to pass this value (m)
447  either at the construction of the neighborhood or at
448  the construction of the iterator. */
449  u.iter().set_m(0);
450 
451  /* Compute the number of values (`size') to be passed as
452  second parameter of the POLYGONS keyword. */
453  unsigned polygons_size = 0;
454  // Iterate on polygons (2-face).
455  for_all(p)
456  {
457  unsigned nvertices = 0;
458  /* FIXME: There may be a faster way to do this (e.g.,
459  the neighbordhood may provide a method returning
460  the number of P's neighbors. */
461  // Iterate on transitively adjacent vertices (0-face).
462  for_all(u)
463  ++nvertices;
464  // The number of values describing this polygon P is
465  // the cardinal of its set of vertices (1 value) plus
466  // the NVERTICES indices of these vertices.
467  polygons_size += 1 + nvertices;
468  }
469  ostr << "POLYGONS " << npolygons << ' ' << polygons_size
470  << std::endl;
471 
472  /* Output polygons (one per line), with their number of
473  vertices and the indices of these vertices. */
474  // Iterate on polygons (2-face).
475  for_all(p)
476  {
477  unsigned nvertices = 0;
478  std::ostringstream vertices;
479  // Iterate on transitively adjacent vertices (0-face).
480  for_all(u)
481  {
482  // FIXME: Likewise, this is a bit too long.
483  vertices << ' ' << u.unproxy_().face().face_id();
484  ++nvertices;
485  }
486  ostr << nvertices << vertices.str() << std::endl;
487  }
488  ostr << std::endl;
489  }
490 
491  // -------------------- //
492  // Dataset attributes. //
493  // -------------------- //
494 
495  /* ``5. The final part describes the dataset attributes.
496  This part begins with the keywords POINT_DATA or
497  CELL_DATA,followed by an integer number specifying
498  the number of points or cells, respectively. (It
499  doesn't matter whether POINT_DATA or CELL_DATA comes
500  first.) Other keyword/data combinations then define
501  the actual dataset attribute values (i.e., scalars,
502  vectors, tensors, normals, texture coordinates, or
503  field data).'' */
504 
505  unsigned nfaces = nvertices + nedges + npolygons;
506  if (nfaces > 0)
507  {
508  // We don't use POINT_DATA (to associate values to
509  // POINTs), since CELL_DATA is used to associate values
510  // to VERTICES, EDGES and POLYGONS.
511  ostr << "CELL_DATA " << nfaces << std::endl;
512  exact(this)->write_face_data(ostr, ima);
513  }
514 
515  ostr.close();
516  }
517 
518  // ---------------- //
519  // Specific parts. //
520  // ---------------- //
521 
522  /* ``Dataset Attribute Format. The Visualization Toolkit
523  supports the following dataset attributes: scalars
524  (one to four components), vectors, normals,
525  texture coordinates (1D, 2D, and 3D), 3 x 3
526  tensors, and field data. In addition, a lookup
527  table using the RGBA color specification,
528  associated with the scalar data, can be defined as
529  well. Dataset attributes are supported for both
530  points and cells.
531  Each type of attribute data has a `dataName'
532  associated with it. This is a character string
533  (without embedded whitespace) used to identify a
534  particular data. The `dataName' is used by the VTK
535  readers to extract data. As a result, more than
536  one attribute data of the same type can be
537  included in a file. For example, two different
538  scalar fields defined on the dataset points,
539  pressure and temperature, can be contained in the
540  same file. (If the appropriate dataName is not
541  specified in the VTK reader, then the first data
542  of that type is extracted from the file.)
543 
544  * Scalars
545  Scalar definition includes specification of a
546  lookup table. The definition of a lookup table
547  is optional.
548 
549  [...]
550 
551  SCALARS dataName dataType numComp
552  LOOKUP_TABLE tableName
553  s0
554  s1
555  ...
556  sn-1''
557 
558  Note: values accepted by Paraview 3.8 for `dataType' are:
559  "bit", "char", "unsigned_char", "short", "unsigned_short",
560  "vtkidtype", "int", "unsigned_int", "long",
561  "unsigned_long", "vtktypeint64", "vtktypeuint64", "float",
562  "double", "string", "utf8_string" and "variant". */
563 
565  template <typename I, typename E>
566  void
567  vtk_saver<I, E>::write_scalar_data(std::ostream& ostr,
568  const image& ima,
569  const std::string& data_type) const
570  {
571  ostr << "SCALARS values " << data_type << std::endl
572  << "LOOKUP_TABLE default" << std::endl;
573  // Iterate on all faces, dimension increasing.
574  mln_fwd_piter(image) p(ima.domain());
575  for_all(p)
576  ostr << ima(p) << std::endl;
577  }
578 
579 
580  void
581  bin_vtk_saver::write_face_data(std::ostream& ostr,
582  const image& ima) const
583  {
584  write_scalar_data(ostr, ima, "bit");
585  }
586 
587  void
588  int_u8_vtk_saver::write_face_data(std::ostream& ostr,
589  const image& ima) const
590  {
591  write_scalar_data(ostr, ima, "unsigned_char");
592  }
593 
594  void
595  unsigned_vtk_saver::write_face_data(std::ostream& ostr,
596  const image& ima) const
597  {
598  write_scalar_data(ostr, ima, "unsigned_int");
599  }
600 
601  void
602  float_vtk_saver::write_face_data(std::ostream& ostr,
603  const image& ima) const
604  {
605  write_scalar_data(ostr, ima, "float");
606  }
607 
608  /* ``The definition of color scalars (i.e., unsigned
609  char values directly mapped to color) varies
610  depending upon the number of values (`nValues')
611  per scalar. If the file format is ASCII, the
612  color scalars are defined using nValues float
613  values between (0,1).
614 
615  COLOR_SCALARS dataName nValues
616  c00 c01 ... c0(nValues-1)
617  c10 c11 ... c1(nValues-1)
618  ...
619  c(n-1)0 c(n-1)1 ... c(n-1)(nValues-1)'' */
620 
621  void
622  rgb8_vtk_saver::write_face_data(std::ostream& ostr,
623  const image& ima) const
624  {
625  ostr << "COLOR_SCALARS values 4" << std::endl;
626  // Iterate on all faces, dimension increasing.
627  mln_fwd_piter_(image) p(ima.domain());
628  for_all(p)
629  // RGBA values (with alpha channel always set to 1.0).
630  ostr << float(ima(p).red()) / mln_max(value::red_t) << ' '
631  << float(ima(p).green()) / mln_max(value::green_t) << ' '
632  << float(ima(p).blue()) / mln_max(value::blue_t) << ' '
633  << 1.f
634  << std::endl;
635  }
638  } // end of namespace mln::io::vtk::internal
639 
640 # endif // ! MLN_INCLUDE_ONLY
641 
642  } // end of namespace mln::io::vtk
643 
644  } // end of namespace mln::io
645 
646 } // end of namespace mln
647 
648 
649 #endif // ! MLN_IO_VTK_SAVE_HH