[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

multi_impex.hxx
1 /************************************************************************/
2 /* */
3 /* Copyright 2003 by Gunnar Kedenburg */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 
36 
37 #ifndef VIGRA_MULTI_IMPEX_HXX
38 #define VIGRA_MULTI_IMPEX_HXX
39 
40 #include <memory>
41 #include <iomanip>
42 #include <sstream>
43 #include <iostream>
44 #include <string>
45 #include <fstream>
46 
47 #include "config.hxx"
48 #include "basicimageview.hxx"
49 #include "impex.hxx"
50 #include "multi_array.hxx"
51 #include "multi_pointoperators.hxx"
52 
53 #ifdef _MSC_VER
54 # include <direct.h>
55 #else
56 # include <unistd.h>
57 #endif
58 
59 namespace vigra {
60 
61 /** \addtogroup VolumeImpex Import/export of volume data.
62 */
63 
64 //@{
65 
66 /** \brief Argument object for the function importVolume().
67 
68  See \ref importVolume() for usage example. This object can be used
69  to define the properties of a volume data set to be read from disk.
70  Sorry, no \ref detailedDocumentation() available yet.
71 
72  <b>\#include</b> <vigra/multi_impex.hxx><br>
73  Namespace: vigra
74 **/
76 {
77  public:
78  typedef ImageImportInfo::PixelType PixelType;
79 
80  /// type of volume size returned by shape()
82 
83  /// provided for backwards-compatibility (deprecated)
85 
86  /// 3D resolution type returned by resolution()
88 
89  VIGRA_EXPORT VolumeImportInfo(const std::string &filename);
90  VIGRA_EXPORT VolumeImportInfo(const std::string &baseName, const std::string &extension);
91 
92  VIGRA_EXPORT ShapeType shape() const;
93 
94  /** Get width of the volume.
95  **/
96  VIGRA_EXPORT MultiArrayIndex width() const;
97 
98  /** Get height of the volume.
99  **/
100  VIGRA_EXPORT MultiArrayIndex height() const;
101 
102  /** Get depth of the volume.
103  **/
104  VIGRA_EXPORT MultiArrayIndex depth() const;
105 
106  /**
107  * resolution() contains the alignment and resolution of the
108  * volume. resolution()[0] is the x increment in a left-handed
109  * world coordinate system of one unstrided step in the volume
110  * memory. The [1] and [2] elements contain the y resp. z
111  * increments of the strided row resp. slice steps in the
112  * volume.
113  *
114  * EXAMPLES: (1.f, 1.f, 4.f) means that the slices are four
115  * times thicker than the x/y resolution.
116  * (1.f, -1.f, 1.f) means that the volume coordinate system is
117  * right-handed.
118  */
119  VIGRA_EXPORT Resolution resolution() const;
120 
121  /** Query the pixel type of the image.
122 
123  Possible values are:
124  <DL>
125  <DT>"UINT8"<DD> 8-bit unsigned integer (unsigned char)
126  <DT>"INT16"<DD> 16-bit signed integer (short)
127  <DT>"UINT16"<DD> 16-bit unsigned integer (unsigned short)
128  <DT>"INT32"<DD> 32-bit signed integer (long)
129  <DT>"UINT32"<DD> 32-bit unsigned integer (unsigned long)
130  <DT>"FLOAT"<DD> 32-bit floating point (float)
131  <DT>"DOUBLE"<DD> 64-bit floating point (double)
132  </DL>
133  **/
134  VIGRA_EXPORT const char * getPixelType() const;
135 
136  /** Query the pixel type of the image.
137 
138  Same as getPixelType(), but the result is returned as a
139  ImageImportInfo::PixelType enum. This is useful to implement
140  a switch() on the pixel type.
141 
142  Possible values are:
143  <DL>
144  <DT>UINT8<DD> 8-bit unsigned integer (unsigned char)
145  <DT>INT16<DD> 16-bit signed integer (short)
146  <DT>UINT16<DD> 16-bit unsigned integer (unsigned short)
147  <DT>INT32<DD> 32-bit signed integer (long)
148  <DT>UINT32<DD> 32-bit unsigned integer (unsigned long)
149  <DT>FLOAT<DD> 32-bit floating point (float)
150  <DT>DOUBLE<DD> 64-bit floating point (double)
151  </DL>
152  **/
153  VIGRA_EXPORT PixelType pixelType() const;
154 
155  VIGRA_EXPORT MultiArrayIndex numBands() const;
156  VIGRA_EXPORT bool isGrayscale() const;
157  VIGRA_EXPORT bool isColor() const;
158 
159  // get base file name without path, image index, and extension
160  VIGRA_EXPORT const std::string &name() const;
161 
162  VIGRA_EXPORT const std::string &description() const;
163 
164  template <class T, class Stride>
165  void importImpl(MultiArrayView <3, T, Stride> &volume) const;
166 
167  protected:
168  void getVolumeInfoFromFirstSlice(const std::string &filename);
169 
170  size_type shape_;
171  Resolution resolution_;
172  //PixelType pixelType_;
173  int numBands_;
174 
175  std::string path_, name_, description_, pixelType_;
176 
177  std::string rawFilename_;
178  std::string baseName_, extension_;
179  std::vector<std::string> numbers_;
180 };
181 
182 /********************************************************/
183 /* */
184 /* VolumeExportInfo */
185 /* */
186 /********************************************************/
187 
188 /** \brief Argument object for the function exportVolume().
189 
190  See \ref exportVolume() for usage example. This object must be used
191  to define the properties of a volume to be written to disk.
192 
193  <b>\#include</b> <vigra/imageinfo.hxx><br>
194  Namespace: vigra
195 **/
197 {
198  public:
199  /** Construct VolumeExportInfo object.
200 
201  The volume will be stored in a by-slice manner, where the number of slices
202  equals the depth of the volume. The file names will be enumerated like
203  <tt>name_base+"000"+name_ext</tt>, <tt>name_base+"001"+name_ext</tt> etc.
204  (the actual number of zeros depends on the depth). If the target image type
205  does not support the source voxel type, all slices will be mapped
206  simultaneously to the appropriate target range.
207  The file type will be guessed from the extension unless overridden
208  by \ref setFileType(). Recognized extensions: '.bmp', '.gif',
209  '.jpeg', '.jpg', '.p7', '.png', '.pbm', '.pgm', '.pnm', '.ppm', '.ras',
210  '.tif', '.tiff', '.xv', '.hdr'.
211  JPEG support requires libjpeg, PNG support requires libpng, and
212  TIFF support requires libtiff.
213  **/
214  VIGRA_EXPORT VolumeExportInfo( const char * name_base, const char * name_ext );
215  VIGRA_EXPORT ~VolumeExportInfo();
216 
217  /** Set volume file name base.
218 
219  **/
220  VIGRA_EXPORT VolumeExportInfo & setFileNameBase(const char * name_base);
221  /** Set volume file name extension.
222 
223  The file type will be guessed from the extension unless overridden
224  by \ref setFileType(). Recognized extensions: '.bmp', '.gif',
225  '.jpeg', '.jpg', '.p7', '.png', '.pbm', '.pgm', '.pnm', '.ppm', '.ras',
226  '.tif', '.tiff', '.xv', '.hdr'.
227  JPEG support requires libjpeg, PNG support requires libpng, and
228  TIFF support requires libtiff.
229  **/
230  VIGRA_EXPORT VolumeExportInfo & setFileNameExt(const char * name_ext);
231  VIGRA_EXPORT const char * getFileNameBase() const;
232  VIGRA_EXPORT const char * getFileNameExt() const;
233 
234  /** Store volume as given file type.
235 
236  This will override any type guessed
237  from the file name's extension. Recognized file types:
238 
239  <DL>
240  <DT>"BMP"<DD> Microsoft Windows bitmap image file.
241  <DT>"GIF"<DD> CompuServe graphics interchange format; 8-bit color.
242  <DT>"JPEG"<DD> Joint Photographic Experts Group JFIF format;
243  compressed 24-bit color (only available if libjpeg is installed).
244  <DT>"PNG"<DD> Portable Network Graphic
245  (only available if libpng is installed).
246  <DT>"PBM"<DD> Portable bitmap format (black and white).
247  <DT>"PGM"<DD> Portable graymap format (gray scale).
248  <DT>"PNM"<DD> Portable anymap.
249  <DT>"PPM"<DD> Portable pixmap format (color).
250  <DT>"SUN"<DD> SUN Rasterfile.
251  <DT>"TIFF"<DD> Tagged Image File Format.
252  (only available if libtiff is installed.)
253  <DT>"VIFF"<DD> Khoros Visualization image file.
254  </DL>
255 
256  With the exception of TIFF, VIFF, PNG, and PNM all file types store
257  1 byte (gray scale and mapped RGB) or 3 bytes (RGB) per
258  pixel.
259 
260  PNG can store UInt8 and UInt16 values, and supports 1 and 3 channel
261  images. One additional alpha channel is also supported.
262 
263  PNM can store 1 and 3 channel images with UInt8, UInt16 and UInt32
264  values in each channel.
265 
266  TIFF and VIFF are additionally able to store short and long
267  integers (2 or 4 bytes) and real values (32 bit float and
268  64 bit double) without conversion. So you will need to use
269  TIFF or VIFF if you need to store images with high
270  accuracy (the appropriate type to write is automatically
271  derived from the image type to be exported). However, many
272  other programs using TIFF (e.g. ImageMagick) have not
273  implemented support for those pixel types. So don't be
274  surprised if the generated TIFF is not readable in some
275  cases. If this happens, export the image as 'unsigned
276  char' or 'RGBValue<unsigned char>' by calling
277  \ref ImageExportInfo::setPixelType().
278 
279  Support to reading and writing ICC color profiles is
280  provided for TIFF, JPEG, and PNG images.
281  **/
282  VIGRA_EXPORT VolumeExportInfo & setFileType( const char * );
283  VIGRA_EXPORT const char * getFileType() const;
284 
285  /** Set compression type and quality.
286 
287  See \ref ImageExportInfo::setCompression() for details.
288  **/
289  VIGRA_EXPORT VolumeExportInfo & setCompression( const char * type);
290  VIGRA_EXPORT const char * getCompression() const;
291 
292  /** Set the pixel type of the volume file(s). Possible values are:
293  <DL>
294  <DT>"UINT8"<DD> 8-bit unsigned integer (unsigned char)
295  <DT>"INT16"<DD> 16-bit signed integer (short)
296  <DT>"UINT16"<DD> 16-bit unsigned integer (unsigned short)
297  <DT>"INT32"<DD> 32-bit signed integer (long)
298  <DT>"UINT32"<DD> 32-bit unsigned integer (unsigned long)
299  <DT>"FLOAT"<DD> 32-bit floating point (float)
300  <DT>"DOUBLE"<DD> 64-bit floating point (double)
301  </DL>
302  **/
303  VIGRA_EXPORT VolumeExportInfo & setPixelType( const char * );
304 
305  /** Get the pixel type of the images in the volume. Possible values are:
306  <DL>
307  <DT>"UINT8"<DD> 8-bit unsigned integer (unsigned char)
308  <DT>"INT16"<DD> 16-bit signed integer (short)
309  <DT>"INT32"<DD> 32-bit signed integer (long)
310  <DT>"FLOAT"<DD> 32-bit floating point (float)
311  <DT>"DOUBLE"<DD> 64-bit floating point (double)
312  </DL>
313  **/
314  VIGRA_EXPORT const char * getPixelType() const;
315 
316  VIGRA_EXPORT VolumeExportInfo & setForcedRangeMapping(double fromMin, double fromMax,
317  double toMin, double toMax);
318  VIGRA_EXPORT bool hasForcedRangeMapping() const;
319  VIGRA_EXPORT double getFromMin() const;
320  VIGRA_EXPORT double getFromMax() const;
321  VIGRA_EXPORT double getToMin() const;
322  VIGRA_EXPORT double getToMax() const;
323 
324  /** Set the volume resolution in horizontal direction
325  **/
326  VIGRA_EXPORT VolumeExportInfo & setXResolution( float );
327  VIGRA_EXPORT float getXResolution() const;
328 
329  /** Set the image resolution in vertical direction
330  **/
331  VIGRA_EXPORT VolumeExportInfo & setYResolution( float );
332  VIGRA_EXPORT float getYResolution() const;
333 
334  /** Set the image resolution in depth direction
335  **/
336  VIGRA_EXPORT VolumeExportInfo & setZResolution( float );
337  VIGRA_EXPORT float getZResolution() const;
338 
339  /** Set the position of the upper Left corner on a global
340  canvas.
341 
342  Currently only supported by TIFF and PNG files.
343 
344  The offset is encoded in the XPosition and YPosition TIFF tags.
345 
346  @param pos position of the upper left corner in pixels
347  (must be >= 0)
348  **/
349  // FIXME: mhanselm: we might want to support 3D positions
350  VIGRA_EXPORT VolumeExportInfo & setPosition(const Diff2D & pos);
351 
352  /** Get the position of the upper left corner on
353  a global canvas.
354  **/
355  // FIXME: mhanselm: we might want to support 3D positions
356  VIGRA_EXPORT Diff2D getPosition() const;
357 
358  /**
359  ICC profiles (handled as raw data so far).
360  see getICCProfile()/setICCProfile()
361  **/
363 
364  /** Returns a reference to the ICC profile.
365  */
366  VIGRA_EXPORT const ICCProfile & getICCProfile() const;
367 
368  /** Sets the ICC profile.
369  ICC profiles are currently supported by TIFF, PNG and JPEG images.
370  (Otherwise, the profile data is silently ignored.)
371  **/
372  VIGRA_EXPORT VolumeExportInfo & setICCProfile(const ICCProfile & profile);
373 
374  private:
375  float m_x_res, m_y_res, m_z_res;
376 
377  std::string m_filetype, m_filename_base, m_filename_ext, m_pixeltype, m_comp;
378  Diff2D m_pos;
379  ICCProfile m_icc_profile;
380  double fromMin_, fromMax_, toMin_, toMax_;
381 };
382 
383 namespace detail {
384 
385 template <class DestIterator, class Shape, class T>
386 inline void
387 readVolumeImpl(DestIterator d, Shape const & shape, std::ifstream & s, ArrayVector<T> & buffer, MetaInt<0>)
388 {
389  s.read((char*)buffer.begin(), shape[0]*sizeof(T));
390 
391  DestIterator dend = d + shape[0];
392  int k = 0;
393  for(; d < dend; ++d, k++)
394  {
395  *d = buffer[k];
396  }
397 }
398 
399 template <class DestIterator, class Shape, class T, int N>
400 void
401 readVolumeImpl(DestIterator d, Shape const & shape, std::ifstream & s, ArrayVector<T> & buffer, MetaInt<N>)
402 {
403  DestIterator dend = d + shape[N];
404  for(; d < dend; ++d)
405  {
406  readVolumeImpl(d.begin(), shape, s, buffer, MetaInt<N-1>());
407  }
408 }
409 
410 } // namespace detail
411 
412 template <class T, class Stride>
413 void VolumeImportInfo::importImpl(MultiArrayView <3, T, Stride> &volume) const
414 {
415  vigra_precondition(this->shape() == volume.shape(), "importVolume(): Volume must be shaped according to VolumeImportInfo.");
416 
417  if(rawFilename_.size())
418  {
419  std::string dirName, baseName;
420  char oldCWD[2048];
421 
422 #ifdef _MSC_VER
423  if(_getcwd(oldCWD, 2048) == 0)
424  {
425  perror("getcwd");
426  vigra_fail("VolumeImportInfo: Unable to query current directory (getcwd).");
427  }
428  if(_chdir(path_.c_str()))
429  {
430  perror("chdir");
431  vigra_fail("VolumeImportInfo: Unable to change to new directory (chdir).");
432  }
433 #else
434  if(getcwd(oldCWD, 2048) == 0)
435  {
436  perror("getcwd");
437  vigra_fail("VolumeImportInfo: Unable to query current directory (getcwd).");
438  }
439  if(chdir(path_.c_str()))
440  {
441  perror("chdir");
442  vigra_fail("VolumeImportInfo: Unable to change to new directory (chdir).");
443  }
444 #endif
445 
446  std::ifstream s(rawFilename_.c_str(), std::ios::binary);
447  vigra_precondition(s.good(), "RAW file could not be opened");
448 
449  ArrayVector<T> buffer(shape_[0]);
450  detail::readVolumeImpl(volume.traverser_begin(), shape_, s, buffer, vigra::MetaInt<2>());
451 
452  //vigra_precondition(s.good(), "RAW file could not be opened");
453  //s.read((char*)volume.data(), shape_[0]*shape_[1]*shape_[2]*sizeof(T));
454 
455 #ifdef _MSC_VER
456  if(_chdir(oldCWD))
457  perror("chdir");
458 #else
459  if(chdir(oldCWD))
460  perror("chdir");
461 #endif
462 
463  vigra_postcondition(
464  volume.shape() == shape(), "imported volume has wrong size");
465  }
466  else
467  {
468  for (unsigned int i = 0; i < numbers_.size(); ++i)
469  {
470  // build the filename
471  std::string name = baseName_ + numbers_[i] + extension_;
472 
473  // import the image
474  ImageImportInfo info (name.c_str ());
475 
476  // generate a basic image view to the current layer
477  MultiArrayView <2, T, Stride> view (volume.bindOuter (i));
478  vigra_precondition(view.shape() == info.shape(),
479  "importVolume(): the images have inconsistent sizes.");
480 
481  importImage (info, destImage(view));
482  }
483  }
484 }
485 
486 
487 VIGRA_EXPORT void findImageSequence(const std::string &name_base,
488  const std::string &name_ext,
489  std::vector<std::string> & numbers);
490 
491 /********************************************************/
492 /* */
493 /* importVolume */
494 /* */
495 /********************************************************/
496 
497 /** \brief Function for importing a 3D volume.
498 
499  The data are expected to be stored in a by-slice manner,
500  where the slices are enumerated from <tt>name_base+"[0-9]+"+name_ext</tt>.
501  <tt>name_base</tt> may contain a path. All slice files with the same name base and
502  extension are considered part of the same volume. Slice numbers must be non-negative,
503  but can otherwise start anywhere and need not be successive. Slices will be read
504  in ascending numerical (not lexicographic) order. All slices must have the
505  same size. The <tt>volume</tt> will be reshaped to match the count and
506  size of the slices found.
507 
508  <b>\#include</b>
509  <vigra/multi_impex.hxx>
510 
511  Namespace: vigra
512 */
513 template <class T, class Allocator>
515  const std::string &name_base,
516  const std::string &name_ext)
517 {
518  VolumeImportInfo info(name_base, name_ext);
519  volume.reshape(info.shape());
520 
521  info.importImpl(volume);
522 }
523 
524 
525 /** \brief Function for importing a 3D volume.
526 
527  The data can be given in two ways:
528 
529  <UL>
530  <LI> If the volume is stored in a by-slice manner (e.g. one image per slice),
531  the <tt>filename</tt> can refer to an arbitrary image from the set. <tt>importVolume()</tt>
532  then assumes that the slices are enumerated like <tt>name_base+"[0-9]+"+name_ext</tt>,
533  where <tt>name_base</tt>, the index, and <tt>name_ext</tt> are determined automatically.
534  All slice files with the same name base and extension are considered part of the same
535  volume. Slice numbers must be non-negative, but can otherwise start anywhere and need
536  not be successive. Slices will be read in ascending numerical (not lexicographic) order.
537  All slices must have the same size.
538  <li> Otherwise, <tt>importVolume()</tt> will try to read <tt>filename</tt> as an
539  info text file with the following key-value pairs:
540  <UL>
541  <LI> name = [short descriptive name of the volume] (optional)
542  <LI> filename = [absolute or relative path to raw voxel data file] (required)
543  <li> gradfile = [absolute or relative path to gradient data file] (currently ignored)
544  <li> description = [arbitrary description of the data set] (optional)
545  <li> width = [positive integer] (required)
546  <li> height = [positive integer] (required)
547  <li> depth = [positive integer] (required)
548  <li> datatype = [UNSIGNED_CHAR | UNSIGNED_BYTE] (default: UNSIGNED_CHAR)
549  </UL>
550  The voxel type is currently assumed to be binary compatible to the <tt>value_type T</TT>
551  of the <tt>MuliArray</tt>. Lines starting with "#" are ignored.
552  </UL>
553 
554  In either case, the <tt>volume</tt> will be reshaped to match the count and
555  size of the slices found.
556 
557  <b>\#include</b>
558  <vigra/multi_impex.hxx>
559 
560  Namespace: vigra
561 */
562 template <class T, class Allocator>
564  const std::string &filename)
565 {
566  VolumeImportInfo info(filename);
567  volume.reshape(info.shape());
568 
569  info.importImpl(volume);
570 }
571 
572 /** \brief Function for importing a 3D volume.
573 
574  Read the volume data set <tt>info</tt> refers to. Explicit construction
575  of the info object allows to allocate a <tt>volume</tt> object type whose
576  <tt>value_type</tt> matches the voxel type of the stored data.
577  The <tt>volume</tt> will be reshaped to match the count and
578  size of the slices found.
579 
580  <b>\#include</b>
581  <vigra/multi_impex.hxx>
582 
583  Namespace: vigra
584 */
585 template <class T, class Stride>
587 {
588  info.importImpl(volume);
589 }
590 
591 namespace detail {
592 
593 template <class T>
594 void setRangeMapping(std::string const & pixeltype,
595  FindMinMax<T> const & minmax, ImageExportInfo & info)
596 {
597  if(pixeltype == "UINT8")
598  info.setForcedRangeMapping((double)minmax.min, (double)minmax.max,
599  (double)NumericTraits<UInt8>::min(),
600  (double)NumericTraits<UInt8>::max());
601  else if(pixeltype == "INT16")
602  info.setForcedRangeMapping((double)minmax.min, (double)minmax.max,
603  (double)NumericTraits<Int16>::min(),
604  (double)NumericTraits<Int16>::max());
605  else if(pixeltype == "UINT16")
606  info.setForcedRangeMapping((double)minmax.min, (double)minmax.max,
607  (double)NumericTraits<UInt16>::min(),
608  (double)NumericTraits<UInt16>::max());
609  else if(pixeltype == "INT32")
610  info.setForcedRangeMapping((double)minmax.min, (double)minmax.max,
611  (double)NumericTraits<Int32>::min(),
612  (double)NumericTraits<Int32>::max());
613  else if(pixeltype == "UINT32")
614  info.setForcedRangeMapping((double)minmax.min, (double)minmax.max,
615  (double)NumericTraits<UInt32>::min(),
616  (double)NumericTraits<UInt32>::max());
617  else if(pixeltype == "FLOAT")
618  info.setForcedRangeMapping((double)minmax.min, (double)minmax.max, 0.0, 1.0);
619  else if(pixeltype == "DOUBLE")
620  info.setForcedRangeMapping((double)minmax.min, (double)minmax.max, 0.0, 1.0);
621 }
622 
623 template <class T, class Tag>
624 void setRangeMapping(MultiArrayView <3, T, Tag> const & volume,
625  ImageExportInfo & info, VigraTrueType /* isScalar */)
626 {
627  std::string pixeltype = info.getPixelType();
628  bool downcast = negotiatePixelType(getEncoderType(info.getFileName(), info.getFileType()),
629  TypeAsString<T>::result(), pixeltype);
630 
631  if(downcast)
632  {
633  FindMinMax<T> minmax;
634  inspectMultiArray(srcMultiArrayRange(volume), minmax);
635  setRangeMapping(pixeltype, minmax, info);
636  }
637 }
638 
639 template <class T, class Tag>
640 void setRangeMapping(MultiArrayView <3, T, Tag> const & volume,
641  ImageExportInfo & info, VigraFalseType /* isScalar */)
642 {
643  typedef typename T::value_type SrcComponent;
644  std::string pixeltype = info.getPixelType();
645  bool downcast = negotiatePixelType(getEncoderType(info.getFileName(), info.getFileType()),
646  TypeAsString<SrcComponent>::result(), pixeltype);
647 
648  if(downcast)
649  {
650  unsigned int bands = volume(0,0,0).size();
651  FindMinMax<SrcComponent> minmax;
652  for(unsigned int i=0; i<bands; ++i)
653  {
654  VectorComponentValueAccessor<T> band(i);
655  inspectMultiArray(srcMultiArrayRange(volume, band), minmax );
656  }
657  setRangeMapping(pixeltype, minmax, info);
658  }
659 }
660 
661 } // namespace detail
662 
663 /********************************************************/
664 /* */
665 /* exportVolume */
666 /* */
667 /********************************************************/
668 
669 /** \brief Function for exporting a 3D volume.
670 
671  The volume is exported in a by-slice manner, where the number of slices equals
672  the depth of the volume. The file names will be enumerated like
673  <tt>name_base+"000"+name_ext</tt>, <tt>name_base+"001"+name_ext</tt> etc.
674  (the actual number of zeros depends on the depth). If the target image type
675  does not support the source voxel type, all slices will be mapped simultaneously
676  to the appropriate target range.
677 
678  <b>\#include</b>
679  <vigra/multi_impex.hxx>
680 
681  Namespace: vigra
682 */
683 template <class T, class Tag>
685  const VolumeExportInfo & volinfo)
686 {
687  std::string name = std::string(volinfo.getFileNameBase()) + std::string(volinfo.getFileNameExt());
688  ImageExportInfo info(name.c_str());
689  info.setCompression(volinfo.getCompression());
690  info.setPixelType(volinfo.getPixelType());
691  detail::setRangeMapping(volume, info, typename NumericTraits<T>::isScalar());
692 
693  const unsigned int depth = volume.shape (2);
694  int numlen = static_cast <int> (std::ceil (std::log10 ((double)depth)));
695  for (unsigned int i = 0; i < depth; ++i)
696  {
697 
698  // build the filename
699  std::stringstream stream;
700  stream << std::setfill ('0') << std::setw (numlen) << i;
701  std::string name_num;
702  stream >> name_num;
703  std::string name = std::string(volinfo.getFileNameBase()) + name_num + std::string(volinfo.getFileNameExt());
704 
705  MultiArrayView <2, T, Tag> view (volume.bindOuter (i));
706 
707  // export the image
708  info.setFileName(name.c_str ());
709  exportImage(srcImageRange(view), info);
710  }
711 }
712 
713 // for backward compatibility
714 template <class T, class Tag>
715 inline
716 void exportVolume (MultiArrayView <3, T, Tag> const & volume,
717  const std::string &name_base,
718  const std::string &name_ext)
719 {
720  VolumeExportInfo volinfo(name_base.c_str(), name_ext.c_str());
721  exportVolume(volume, volinfo);
722 }
723 
724 //@}
725 
726 } // namespace vigra
727 
728 #endif // VIGRA_MULTI_IMPEX_HXX

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.9.0 (Wed Feb 27 2013)