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

multi_impex.hxx VIGRA

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 #include "sifImport.hxx"
53 
54 #ifdef _MSC_VER
55 # include <direct.h>
56 #else
57 # include <unistd.h>
58 #endif
59 
60 namespace vigra {
61 
62 /** \addtogroup VolumeImpex Import/export of volume data.
63 */
64 
65 //@{
66 
67 /** \brief Argument object for the function importVolume().
68 
69  This object can be used to define the properties of a volume
70  data set to be read from disk. It works like \ref vigra::ImageImportInfo,
71  but for 3-dimensional data. See \ref importVolume() for usage example.
72 
73  <b>\#include</b> <vigra/multi_impex.hxx> <br/>
74  Namespace: vigra
75 **/
77 {
78  public:
79  typedef ImageImportInfo::PixelType PixelType;
80 
81  /// type of volume size returned by shape()
83 
84  /// type of volume size returned by shape()
86 
87  /// 3D resolution type returned by resolution()
89 
90  /** Construct VolumeImportInfo from a single filename.
91 
92  The \a filename (which may contain a path) can be interpreted in three different ways:
93  <ul>
94  <li>If the name refers to a file that contains volume data, the header information
95  of this file is read. Two file formats are currently supported: Andor .SIF
96  and multi-page TIFF.
97  <li>If the name refers to a textfile, the constructor will attempt to interpret the file
98  in the ".info" format to obtain the header information. The volume data
99  are then expected to be located in an accompanying RAW file. The ".info" file must
100  contain the following key-value pairs:
101  <UL>
102  <LI> name = [short descriptive name of the volume] (optional)
103  <LI> filename = [absolute or relative path to raw voxel data file] (required)
104  <li> description = [arbitrary description of the data set] (optional)
105  <li> width = [positive integer] (required)
106  <li> height = [positive integer] (required)
107  <li> depth = [positive integer] (required)
108  <li> datatype = [ UINT8 | INT16 | UINT16 | INT32 | UINT32 | FLOAT | DOUBLE ] (required)
109  </UL>
110  Lines starting with "#" are ignored. To read the data correctly, the
111  value_type of the target MultiArray must match the datatype stored in the file.
112  Only single-band files are currently supported.
113  <li>If the name refers to a 2D image file, the constructor will attempt to decompose
114  the filename into the format <tt>base_name + slice_number + name_extension</tt>.
115  If this decomposition succeeds, all images with the same base_name and name_extension
116  will be considered as the slices of an image stack. Slice numbers need not be consecutive
117  (i.e. gaps are allowed) and will be interpreted according to their numerical order
118  (i.e. "009", "010", "011" are read in the same order as "9", "10", "11"). The number of images
119  found determines the depth of the volume, the remaining header data are read from the given image.
120  </ul>
121  */
122  VIGRA_EXPORT VolumeImportInfo(const std::string &filename);
123 
124  /** Construct VolumeImportInfo for a stack of images.
125 
126  The constructor will look for filenames of the form <tt>base_name + slice_number + name_extension</tt>.
127  All images conforming to this pattern will be considered as the slices of an image stack.
128  Slice numbers need not be consecutive (i.e. gaps are allowed) and will be interpreted according
129  to their numerical order (i.e. "009", "010", "011" are read in the same order as "9", "10", "11").
130  The number of images found determines the depth of the volume, the remaining header data are read
131  from the given image. \a name_base may contain a path.
132  */
133  VIGRA_EXPORT VolumeImportInfo(const std::string &base_name, const std::string &name_extension);
134 
135  /** Get the shape of the volume.
136  */
137  VIGRA_EXPORT ShapeType shape() const;
138 
139  /** Get width of the volume.
140  **/
141  VIGRA_EXPORT MultiArrayIndex width() const;
142 
143  /** Get height of the volume.
144  **/
145  VIGRA_EXPORT MultiArrayIndex height() const;
146 
147  /** Get depth of the volume.
148  **/
149  VIGRA_EXPORT MultiArrayIndex depth() const;
150 
151  /**
152  * resolution() contains the alignment and resolution of the
153  * volume. resolution()[0] is the x increment in a left-handed
154  * world coordinate system of one unstrided step in the volume
155  * memory. The [1] and [2] elements contain the y resp. z
156  * increments of the strided row resp. slice steps in the
157  * volume.
158  *
159  * EXAMPLES: (1.f, 1.f, 4.f) means that the slices are four
160  * times thicker than the x/y resolution.
161  * (1.f, -1.f, 1.f) means that the volume coordinate system is
162  * right-handed.
163  */
164  VIGRA_EXPORT Resolution resolution() const;
165 
166  /** Query the file type.
167 
168  Possible values are:
169  <DL>
170  <DT>"MULTIPAGE"<DD> Multiple 2D images in a single file (currently only supported by TIFF).
171  <DT>"SIF"<DD> <a href="http://www.andor.com">Andor Technology's</a> .sif format.
172  <DT>"RAW"<DD> Raw data file, accompanied by a .info file
173  <DT>"STACK"<DD> A numbered set of 2D image files, one per slice of the volume.
174  </DL>
175  **/
176  VIGRA_EXPORT const char * getFileType() const;
177 
178  /** Query the pixel type of the volume data.
179 
180  Possible values are:
181  <DL>
182  <DT>"INT8"<DD> 8-bit signed integer (signed char)
183  <DT>"UINT8"<DD> 8-bit unsigned integer (unsigned char)
184  <DT>"INT16"<DD> 16-bit signed integer (short)
185  <DT>"UINT16"<DD> 16-bit unsigned integer (unsigned short)
186  <DT>"INT32"<DD> 32-bit signed integer (long)
187  <DT>"UINT32"<DD> 32-bit unsigned integer (unsigned long)
188  <DT>"INT64"<DD> 64-bit signed integer (long long)
189  <DT>"UINT64"<DD> 64-bit unsigned integer (unsigned long long)
190  <DT>"FLOAT"<DD> 32-bit floating point (float)
191  <DT>"DOUBLE"<DD> 64-bit floating point (double)
192  <DT>"UNKNOWN"<DD> any other type
193  </DL>
194  **/
195  VIGRA_EXPORT const char * getPixelType() const;
196 
197  /** Query the pixel type of the volume data.
198 
199  Same as getPixelType(), but the result is returned as a
200  ImageImportInfo::PixelType enum. This is useful to implement
201  a switch() on the pixel type.
202 
203  Possible values are:
204  <DL>
205  <DT>UINT8<DD> 8-bit unsigned integer (unsigned char)
206  <DT>INT16<DD> 16-bit signed integer (short)
207  <DT>UINT16<DD> 16-bit unsigned integer (unsigned short)
208  <DT>INT32<DD> 32-bit signed integer (long)
209  <DT>UINT32<DD> 32-bit unsigned integer (unsigned long)
210  <DT>FLOAT<DD> 32-bit floating point (float)
211  <DT>DOUBLE<DD> 64-bit floating point (double)
212  </DL>
213  **/
214  VIGRA_EXPORT PixelType pixelType() const;
215 
216  VIGRA_EXPORT MultiArrayIndex numBands() const;
217  VIGRA_EXPORT bool isGrayscale() const;
218  VIGRA_EXPORT bool isColor() const;
219 
220  // get base file name without path, image index, and extension
221  VIGRA_EXPORT const std::string &name() const;
222 
223  VIGRA_EXPORT const std::string &description() const;
224 
225  template <class T, class Stride>
226  void importImpl(MultiArrayView <3, T, Stride> &volume) const;
227 
228  protected:
229  void getVolumeInfoFromFirstSlice(const std::string &filename);
230 
231  size_type shape_;
232  Resolution resolution_;
233  //PixelType pixelType_;
234  int numBands_;
235 
236  std::string path_, name_, description_, fileType_, pixelType_;
237 
238  std::string rawFilename_;
239  std::string baseName_, extension_;
240  std::vector<std::string> numbers_;
241 };
242 
243 /********************************************************/
244 /* */
245 /* VolumeExportInfo */
246 /* */
247 /********************************************************/
248 
249 /** \brief Argument object for the function exportVolume().
250 
251  See \ref exportVolume() for usage example. This object must be used
252  to define the properties of a volume to be written to disk.
253 
254  <b>\#include</b> <vigra/imageinfo.hxx> <br/>
255  Namespace: vigra
256 **/
258 {
259  public:
260  /** Construct VolumeExportInfo object to output volume data as a multi-page tiff.
261 
262  The filename must refer to a TIFF file (extension '.tif' or '.tiff'). This function
263  is only available when libtiff is installed.
264  **/
265  VIGRA_EXPORT VolumeExportInfo( const char * filename );
266 
267  /** Construct VolumeExportInfo object to output volume data as an image stack.
268 
269  The volume will be stored in a by-slice manner, where the number of slices
270  equals the depth of the volume. The file names will be enumerated like
271  <tt>name_base+"000"+name_ext</tt>, <tt>name_base+"001"+name_ext</tt> etc.
272  (the actual number of zeros depends on the depth). If the target image type
273  does not support the source voxel type, all slices will be mapped
274  simultaneously to the appropriate target range.
275  The file type will be guessed from the extension unless overridden
276  by \ref setFileType().
277 
278  Recognized extensions: '.bmp', '.gif',
279  '.jpeg', '.jpg', '.p7', '.png', '.pbm', '.pgm', '.pnm', '.ppm', '.ras',
280  '.tif', '.tiff', '.xv', '.hdr'.
281 
282  JPEG support requires libjpeg, PNG support requires libpng, and
283  TIFF support requires libtiff.
284 
285  If \a name_ext is an empty string, the data is written as a multi-page tiff.
286  **/
287  VIGRA_EXPORT VolumeExportInfo( const char * name_base, const char * name_ext );
288  VIGRA_EXPORT ~VolumeExportInfo();
289 
290  /** Set volume file name base.
291 
292  **/
293  VIGRA_EXPORT VolumeExportInfo & setFileNameBase(const char * name_base);
294 
295  /** Set volume file name extension.
296 
297  The file type will be guessed from the extension unless overridden
298  by \ref setFileType(). Recognized extensions: '.bmp', '.gif',
299  '.jpeg', '.jpg', '.p7', '.png', '.pbm', '.pgm', '.pnm', '.ppm', '.ras',
300  '.tif', '.tiff', '.xv', '.hdr'.
301 
302  JPEG support requires libjpeg, PNG support requires libpng, and
303  TIFF support requires libtiff.
304  **/
305  VIGRA_EXPORT VolumeExportInfo & setFileNameExt(const char * name_ext);
306  VIGRA_EXPORT const char * getFileNameBase() const;
307  VIGRA_EXPORT const char * getFileNameExt() const;
308 
309  /** Store volume as given file type.
310 
311  This will override any type guessed
312  from the file name's extension. Recognized file types:
313 
314  <DL>
315  <DT>"BMP"<DD> Microsoft Windows bitmap image file.
316  <DT>"GIF"<DD> CompuServe graphics interchange format; 8-bit color.
317  <DT>"JPEG"<DD> Joint Photographic Experts Group JFIF format;
318  compressed 24-bit color (only available if libjpeg is installed).
319  <DT>"PNG"<DD> Portable Network Graphic
320  (only available if libpng is installed).
321  <DT>"PBM"<DD> Portable bitmap format (black and white).
322  <DT>"PGM"<DD> Portable graymap format (gray scale).
323  <DT>"PNM"<DD> Portable anymap.
324  <DT>"PPM"<DD> Portable pixmap format (color).
325  <DT>"SUN"<DD> SUN Rasterfile.
326  <DT>"TIFF"<DD> Tagged Image File Format.
327  (only available if libtiff is installed.)
328  <DT>"MULTIPAGE"<DD> Multi-page TIFF.
329  (only available if libtiff is installed.)
330  <DT>"VIFF"<DD> Khoros Visualization image file.
331  </DL>
332 
333  With the exception of TIFF, VIFF, PNG, and PNM all file types store
334  only 1 byte (gray scale and mapped RGB) or 3 bytes (RGB) per
335  pixel.
336 
337  PNG can store UInt8 and UInt16 values, and supports 1 and 3 channel
338  images. One additional alpha channel is also supported.
339 
340  PNM can store 1 and 3 channel images with UInt8, UInt16 and UInt32
341  values in each channel.
342 
343  TIFF and VIFF are additionally able to store short and long
344  integers (2 or 4 bytes) and real values (32 bit float and
345  64 bit double) without conversion. So you will need to use
346  TIFF or VIFF if you need to store images with high
347  accuracy (the appropriate type to write is automatically
348  derived from the image type to be exported). However, many
349  other programs using TIFF (e.g. ImageMagick) have not
350  implemented support for those pixel types. So don't be
351  surprised if the generated TIFF is not readable in some
352  cases. If this happens, export the image as 'unsigned
353  char' or 'RGBValue<unsigned char>' by calling
354  \ref ImageExportInfo::setPixelType().
355 
356  Support to reading and writing ICC color profiles is
357  provided for TIFF, JPEG, and PNG images.
358  **/
359  VIGRA_EXPORT VolumeExportInfo & setFileType( const char * );
360  VIGRA_EXPORT const char * getFileType() const;
361 
362  /** Set compression type and quality.
363 
364  See \ref ImageExportInfo::setCompression() for details.
365  **/
366  VIGRA_EXPORT VolumeExportInfo & setCompression( const char * type);
367  VIGRA_EXPORT const char * getCompression() const;
368 
369  /** Set the pixel type of the volume file(s). Possible values are:
370  <DL>
371  <DT>"UINT8"<DD> 8-bit unsigned integer (unsigned char)
372  <DT>"INT16"<DD> 16-bit signed integer (short)
373  <DT>"UINT16"<DD> 16-bit unsigned integer (unsigned short)
374  <DT>"INT32"<DD> 32-bit signed integer (long)
375  <DT>"UINT32"<DD> 32-bit unsigned integer (unsigned long)
376  <DT>"FLOAT"<DD> 32-bit floating point (float)
377  <DT>"DOUBLE"<DD> 64-bit floating point (double)
378  </DL>
379  **/
380  VIGRA_EXPORT VolumeExportInfo & setPixelType( const char * );
381 
382  /** Get the pixel type of the images in the volume. Possible values are:
383  <DL>
384  <DT>"UINT8"<DD> 8-bit unsigned integer (unsigned char)
385  <DT>"INT16"<DD> 16-bit signed integer (short)
386  <DT>"INT32"<DD> 32-bit signed integer (long)
387  <DT>"FLOAT"<DD> 32-bit floating point (float)
388  <DT>"DOUBLE"<DD> 64-bit floating point (double)
389  </DL>
390  **/
391  VIGRA_EXPORT const char * getPixelType() const;
392 
393  VIGRA_EXPORT VolumeExportInfo & setForcedRangeMapping(double fromMin, double fromMax,
394  double toMin, double toMax);
395  VIGRA_EXPORT bool hasForcedRangeMapping() const;
396  VIGRA_EXPORT double getFromMin() const;
397  VIGRA_EXPORT double getFromMax() const;
398  VIGRA_EXPORT double getToMin() const;
399  VIGRA_EXPORT double getToMax() const;
400 
401  /** Set the volume resolution in horizontal direction
402  **/
403  VIGRA_EXPORT VolumeExportInfo & setXResolution( float );
404  VIGRA_EXPORT float getXResolution() const;
405 
406  /** Set the image resolution in vertical direction
407  **/
408  VIGRA_EXPORT VolumeExportInfo & setYResolution( float );
409  VIGRA_EXPORT float getYResolution() const;
410 
411  /** Set the image resolution in depth direction
412  **/
413  VIGRA_EXPORT VolumeExportInfo & setZResolution( float );
414  VIGRA_EXPORT float getZResolution() const;
415 
416  /** Set the position of the upper Left corner on a global
417  canvas.
418 
419  Currently only supported by TIFF and PNG files.
420 
421  The offset is encoded in the XPosition and YPosition TIFF tags.
422 
423  @param pos position of the upper left corner in pixels
424  (must be >= 0)
425  **/
426  // FIXME: mhanselm: we might want to support 3D positions
427  VIGRA_EXPORT VolumeExportInfo & setPosition(const Diff2D & pos);
428 
429  /** Get the position of the upper left corner on
430  a global canvas.
431  **/
432  // FIXME: mhanselm: we might want to support 3D positions
433  VIGRA_EXPORT Diff2D getPosition() const;
434 
435  /**
436  ICC profiles (handled as raw data so far).
437  see getICCProfile()/setICCProfile()
438  **/
440 
441  /** Returns a reference to the ICC profile.
442  */
443  VIGRA_EXPORT const ICCProfile & getICCProfile() const;
444 
445  /** Sets the ICC profile.
446  ICC profiles are currently supported by TIFF, PNG and JPEG images.
447  (Otherwise, the profile data is silently ignored.)
448  **/
449  VIGRA_EXPORT VolumeExportInfo & setICCProfile(const ICCProfile & profile);
450 
451  private:
452  float m_x_res, m_y_res, m_z_res;
453 
454  std::string m_filetype, m_filename_base, m_filename_ext, m_pixeltype, m_comp;
455  Diff2D m_pos;
456  ICCProfile m_icc_profile;
457  double fromMin_, fromMax_, toMin_, toMax_;
458 };
459 
460 namespace detail {
461 
462 template <class DestIterator, class Shape, class T>
463 inline void
464 readVolumeImpl(DestIterator d, Shape const & shape, std::ifstream & s, ArrayVector<T> & buffer, MetaInt<0>)
465 {
466  s.read(reinterpret_cast<char*>(buffer.begin()), shape[0]*sizeof(T));
467 
468  DestIterator dend = d + shape[0];
469  int k = 0;
470  for(; d < dend; ++d, k++)
471  {
472  *d = buffer[k];
473  }
474 }
475 
476 template <class DestIterator, class Shape, class T, int N>
477 void
478 readVolumeImpl(DestIterator d, Shape const & shape, std::ifstream & s, ArrayVector<T> & buffer, MetaInt<N>)
479 {
480  DestIterator dend = d + shape[N];
481  for(; d < dend; ++d)
482  {
483  readVolumeImpl(d.begin(), shape, s, buffer, MetaInt<N-1>());
484  }
485 }
486 
487 } // namespace detail
488 
489 template <class T, class Stride>
490 void VolumeImportInfo::importImpl(MultiArrayView <3, T, Stride> &volume) const
491 {
492  vigra_precondition(this->shape() == volume.shape(), "importVolume(): Output array must be shaped according to VolumeImportInfo.");
493 
494  if(fileType_ == "RAW")
495  {
496  std::string dirName, baseName;
497  char oldCWD[2048];
498 
499 #ifdef _MSC_VER
500  if(_getcwd(oldCWD, 2048) == 0)
501  {
502  perror("getcwd");
503  vigra_fail("VolumeImportInfo: Unable to query current directory (getcwd).");
504  }
505  if(_chdir(path_.c_str()))
506  {
507  perror("chdir");
508  vigra_fail("VolumeImportInfo: Unable to change to new directory (chdir).");
509  }
510 #else
511  if(getcwd(oldCWD, 2048) == 0)
512  {
513  perror("getcwd");
514  vigra_fail("VolumeImportInfo: Unable to query current directory (getcwd).");
515  }
516  if(chdir(path_.c_str()))
517  {
518  perror("chdir");
519  vigra_fail("VolumeImportInfo: Unable to change to new directory (chdir).");
520  }
521 #endif
522 
523  std::ifstream s(rawFilename_.c_str(), std::ios::binary);
524  vigra_precondition(s.good(), "RAW file could not be opened");
525 
526  ArrayVector<T> buffer(shape_[0]);
527  detail::readVolumeImpl(volume.traverser_begin(), shape_, s, buffer, vigra::MetaInt<2>());
528 
529  //vigra_precondition(s.good(), "RAW file could not be opened");
530  //s.read((char*)volume.data(), shape_[0]*shape_[1]*shape_[2]*sizeof(T));
531 
532 #ifdef _MSC_VER
533  if(_chdir(oldCWD))
534  perror("chdir");
535 #else
536  if(chdir(oldCWD))
537  perror("chdir");
538 #endif
539 
540  vigra_postcondition(
541  volume.shape() == shape(), "imported volume has wrong size");
542  }
543  else if(fileType_ == "STACK")
544  {
545  for (unsigned int i = 0; i < numbers_.size(); ++i)
546  {
547  // build the filename
548  std::string filename = baseName_ + numbers_[i] + extension_;
549 
550  // import the image
551  ImageImportInfo info (filename.c_str ());
552 
553  // generate a basic image view to the current layer
554  MultiArrayView <2, T, Stride> view (volume.bindOuter (i));
555  vigra_precondition(view.shape() == info.shape(),
556  "importVolume(): the images have inconsistent sizes.");
557 
558  importImage (info, destImage(view));
559  }
560  }
561  else if(fileType_ == "MULTIPAGE")
562  {
563  ImageImportInfo info(baseName_.c_str());
564 
565  for(int k=0; k<info.numImages(); ++k)
566  {
567  info.setImageIndex(k);
568  importImage(info, volume.bindOuter(k));
569  }
570  }
571  // else if(fileType_ == "HDF5")
572  // {
573  // HDF5File file(baseName_, HDF5File::OpenReadOnly);
574  // file.read(extension_, volume);
575  // }
576  else if(fileType_ == "SIF")
577  {
578  SIFImportInfo infoSIF(baseName_.c_str());
579  readSIF(infoSIF, volume);
580  }
581 }
582 
583 
584 VIGRA_EXPORT void findImageSequence(const std::string &name_base,
585  const std::string &name_ext,
586  std::vector<std::string> & numbers);
587 
588 /********************************************************/
589 /* */
590 /* importVolume */
591 /* */
592 /********************************************************/
593 
594 /** \brief Function for importing a 3D volume.
595 
596  <b>Declarations: </b>
597 
598  \code
599  namespace vigra {
600  // variant 1: read data specified by the given VolumeImportInfo object
601  template <class T, class Stride>
602  void
603  importVolume(VolumeImportInfo const & info,
604  MultiArrayView <3, T, Stride> &volume);
605 
606  // variant 2: read data using a single filename, resize volume automatically
607  template <class T, class Allocator>
608  void
609  importVolume(MultiArray <3, T, Allocator> & volume,
610  const std::string &filename);
611 
612  // variant 3: read data from an image stack, resize volume automatically
613  template <class T, class Allocator>
614  void
615  importVolume(MultiArray <3, T, Allocator> & volume,
616  const std::string &name_base,
617  const std::string &name_ext);
618  }
619  \endcode
620 
621  Data can be read either from a single file containing 3D data (supported formats:
622  Andor .SIF or multi-page TIFF), a ".info" text file which describes the contents of
623  an accompanying raw data file, or a stack of 2D images (numbered according to the
624  scheme <tt>name_base+"[0-9]+"+name_extension</tt>) each representing a slice of
625  the volume. The decision which of these possibilities applies is taken in the
626  \ref vigra::VolumeImportInfo::VolumeImportInfo(const std::string &) "VolumeImportInfo constructor",
627  see there for full details.
628 
629  Variant 1 is the basic version of this function. Here, the info object and a destination
630  array of approriate size must already be constructed. The other variants are just abbreviations
631  provided for your convenience:
632  \code
633  // variant 2 is equivalent to
634  VolumeImportInfo info(filename);
635  volume.reshape(info.shape());
636  importVolume(info, volume); // call variant 1
637 
638  // variant 3 is equivalent to
639  VolumeImportInfo info(name_base, name_ext);
640  volume.reshape(info.shape());
641  importVolume(info, volume); // call variant 1
642  \endcode
643 
644  <b> Usage:</b>
645 
646  <b>\#include</b> <vigra/multi_impex.hxx> <br/>
647  Namespace: vigra
648 
649  \code
650  // read data from a multi-page TIFF file, using variant 1
651  VolumeImportInfo info("multipage.tif");
652  MultiArray<3, float> volume(info.shape());
653  importVolume(info, volume);
654 
655  // read data from a stack of 2D png-images, using variant 1
656  VolumeImportInfo info("my_data", ".png"); // looks for files 'my_data0.png', 'my_data1.png' etc.
657  MultiArray<3, float> volume(info.shape());
658  importVolume(info, volume);
659  \endcode
660  Notice that slice numbers in a stack need not be consecutive (i.e. gaps are allowed) and
661  will be interpreted according to their numerical order (i.e. "009", "010", "011"
662  are read in the same order as "9", "10", "11"). The number of images
663  found determines the depth of the volume.
664 */
665 doxygen_overloaded_function(template <...> void importVolume)
666 
667 template <class T, class Stride>
668 void
669 importVolume(VolumeImportInfo const & info,
670  MultiArrayView <3, T, Stride> &volume)
671 {
672  info.importImpl(volume);
673 }
674 
675 template <class T, class Allocator>
676 void
677 importVolume(MultiArray <3, T, Allocator> &volume,
678  const std::string &filename)
679 {
680  VolumeImportInfo info(filename);
681  volume.reshape(info.shape());
682 
683  info.importImpl(volume);
684 }
685 
686 template <class T, class Allocator>
687 void importVolume (MultiArray <3, T, Allocator> & volume,
688  const std::string &name_base,
689  const std::string &name_ext)
690 {
691  VolumeImportInfo info(name_base, name_ext);
692  volume.reshape(info.shape());
693 
694  info.importImpl(volume);
695 }
696 
697 namespace detail {
698 
699 template <class T>
700 void setRangeMapping(std::string const & pixeltype,
701  FindMinMax<T> const & minmax, ImageExportInfo & info)
702 {
703  if(pixeltype == "UINT8")
704  info.setForcedRangeMapping((double)minmax.min, (double)minmax.max,
705  (double)NumericTraits<UInt8>::min(),
706  (double)NumericTraits<UInt8>::max());
707  else if(pixeltype == "INT16")
708  info.setForcedRangeMapping((double)minmax.min, (double)minmax.max,
709  (double)NumericTraits<Int16>::min(),
710  (double)NumericTraits<Int16>::max());
711  else if(pixeltype == "UINT16")
712  info.setForcedRangeMapping((double)minmax.min, (double)minmax.max,
713  (double)NumericTraits<UInt16>::min(),
714  (double)NumericTraits<UInt16>::max());
715  else if(pixeltype == "INT32")
716  info.setForcedRangeMapping((double)minmax.min, (double)minmax.max,
717  (double)NumericTraits<Int32>::min(),
718  (double)NumericTraits<Int32>::max());
719  else if(pixeltype == "UINT32")
720  info.setForcedRangeMapping((double)minmax.min, (double)minmax.max,
721  (double)NumericTraits<UInt32>::min(),
722  (double)NumericTraits<UInt32>::max());
723  else if(pixeltype == "FLOAT")
724  info.setForcedRangeMapping((double)minmax.min, (double)minmax.max, 0.0, 1.0);
725  else if(pixeltype == "DOUBLE")
726  info.setForcedRangeMapping((double)minmax.min, (double)minmax.max, 0.0, 1.0);
727 }
728 
729 template <class T, class Tag>
730 void setRangeMapping(MultiArrayView <3, T, Tag> const & volume,
731  ImageExportInfo & info, VigraTrueType /* isScalar */)
732 {
733  std::string pixeltype = info.getPixelType();
734  bool downcast = negotiatePixelType(getEncoderType(info.getFileName(), info.getFileType()),
735  TypeAsString<T>::result(), pixeltype);
736 
737  if(downcast)
738  {
739  FindMinMax<T> minmax;
740  inspectMultiArray(srcMultiArrayRange(volume), minmax);
741  setRangeMapping(pixeltype, minmax, info);
742  }
743 }
744 
745 template <class T, class Tag>
746 void setRangeMapping(MultiArrayView <3, T, Tag> const & volume,
747  ImageExportInfo & info, VigraFalseType /* isScalar */)
748 {
749  typedef typename T::value_type SrcComponent;
750  std::string pixeltype = info.getPixelType();
751  bool downcast = negotiatePixelType(getEncoderType(info.getFileName(), info.getFileType()),
752  TypeAsString<SrcComponent>::result(), pixeltype);
753 
754  if(downcast)
755  {
756  unsigned int bands = volume(0,0,0).size();
757  FindMinMax<SrcComponent> minmax;
758  for(unsigned int i=0; i<bands; ++i)
759  {
760  VectorComponentValueAccessor<T> band(i);
761  inspectMultiArray(srcMultiArrayRange(volume, band), minmax );
762  }
763  setRangeMapping(pixeltype, minmax, info);
764  }
765 }
766 
767 } // namespace detail
768 
769 /********************************************************/
770 /* */
771 /* exportVolume */
772 /* */
773 /********************************************************/
774 
775 /** \brief Function for exporting a 3D volume.
776 
777  <b> Declarations:</b>
778 
779  \code
780  namespace vigra {
781  // variant 1: writa data as specified in the given VolumeExportInfo object
782  template <class T, class Tag>
783  void
784  exportVolume (MultiArrayView <3, T, Tag> const & volume,
785  const VolumeExportInfo & info);
786 
787  // variant 2: write data to a multi-page TIFF file
788  template <class T, class Tag>
789  void
790  exportVolume (MultiArrayView <3, T, Tag> const & volume,
791  const std::string &filename);
792 
793  // variant 3: write data to an image stack
794  template <class T, class Tag>
795  void
796  exportVolume (MultiArrayView <3, T, Tag> const & volume,
797  const std::string &name_base,
798  const std::string &name_ext);
799  }
800  \endcode
801 
802  The volume can either be exported as a multi-page TIFF file (variant 2, only available if
803  libtiff is installed), or as a stack of 2D images, one image per slice (variant 3, files are named
804  according to the scheme <tt>name_base+"000"+name_ext</tt>, <tt>name_base+"001"+name_ext</tt> etc.).
805  If the target image format does not support the source <tt>value_type</tt>, all slices will
806  be mapped to the appropriate target range in the same way.
807 
808  Variant 1 is the basic version of the function. It allows full control over the export via
809  an already constructed \ref vigra::VolumeExportInfo object. The other two are just abbreviations
810  that construct the VolumeExportInfo object internally.
811 
812  <b> Usage:</b>
813 
814  <b>\#include</b> <vigra/multi_impex.hxx> <br/>
815  Namespace: vigra
816 
817  \code
818  MultiArray<3, RGBValue<UInt8> > volume(shape);
819  ... // fill in data
820 
821  // export a stack named "my_data01.jpg", "my_data02.jpg" etc.
822  VolumeExportInfo info("my_data", ".jpg");
823  info.setCompression("JPEG QUALITY=95");
824  exportVolume(volume, info);
825  \endcode
826 */
827 doxygen_overloaded_function(template <...> void exportVolume)
828 
829 template <class T, class Tag>
830 void
831 exportVolume (MultiArrayView <3, T, Tag> const & volume,
832  const VolumeExportInfo & volinfo)
833 {
834  if(volinfo.getFileType() == std::string("MULTIPAGE"))
835  {
836  char const * mode = "w";
837  std::string compression = "LZW";
838  if(volinfo.getCompression() != std::string())
839  compression = volinfo.getCompression();
840 
841  for(MultiArrayIndex k=0; k<volume.shape(2); ++k)
842  {
843  ImageExportInfo info(volinfo.getFileNameBase(), mode);
844  info.setFileType("TIFF");
845  info.setCompression(compression.c_str());
846  info.setPixelType(volinfo.getPixelType());
847  detail::setRangeMapping(volume, info, typename NumericTraits<T>::isScalar());
848  exportImage(volume.bindOuter(k), info);
849  mode = "a";
850  }
851  }
852  else
853  {
854  std::string name = std::string(volinfo.getFileNameBase()) + std::string(volinfo.getFileNameExt());
855  ImageExportInfo info(name.c_str());
856  info.setCompression(volinfo.getCompression());
857  info.setPixelType(volinfo.getPixelType());
858  detail::setRangeMapping(volume, info, typename NumericTraits<T>::isScalar());
859 
860  const unsigned int depth = volume.shape (2);
861  int numlen = static_cast <int> (std::ceil (std::log10 ((double)depth)));
862  for (unsigned int i = 0; i < depth; ++i)
863  {
864  // build the filename
865  std::stringstream stream;
866  stream << std::setfill ('0') << std::setw (numlen) << i;
867  std::string name_num;
868  stream >> name_num;
869  std::string sliceFilename =
870  std::string(volinfo.getFileNameBase()) +
871  name_num +
872  std::string(volinfo.getFileNameExt());
873 
874  MultiArrayView <2, T, Tag> view (volume.bindOuter (i));
875 
876  // export the image
877  info.setFileName(sliceFilename.c_str ());
878  exportImage(srcImageRange(view), info);
879  }
880  }
881 }
882 
883 template <class T, class Tag>
884 inline void
885 exportVolume (MultiArrayView <3, T, Tag> const & volume,
886  const std::string &filename)
887 {
888  VolumeExportInfo volinfo(filename.c_str());
889  exportVolume(volume, volinfo);
890 }
891 
892 template <class T, class Tag>
893 inline void
894 exportVolume (MultiArrayView <3, T, Tag> const & volume,
895  const std::string &name_base,
896  const std::string &name_ext)
897 {
898  VolumeExportInfo volinfo(name_base.c_str(), name_ext.c_str());
899  exportVolume(volume, volinfo);
900 }
901 
902 //@}
903 
904 } // namespace vigra
905 
906 #endif // VIGRA_MULTI_IMPEX_HXX
VolumeExportInfo & setZResolution(float)
VolumeExportInfo & setFileNameBase(const char *name_base)
void importVolume(...)
Function for importing a 3D volume.
VolumeExportInfo & setCompression(const char *type)
const_iterator begin() const
Definition: array_vector.hxx:223
void exportVolume(...)
Function for exporting a 3D volume.
ShapeType shape() const
void readSIF(const SIFImportInfo &info, MultiArrayView< 3, float > array)
Read the image data specified by the given vigra::SIFImportInfo object and write them into the given ...
Two dimensional difference vector.
Definition: diff2d.hxx:185
VolumeExportInfo & setPosition(const Diff2D &pos)
Diff2D getPosition() const
std::ptrdiff_t MultiArrayIndex
Definition: multi_fwd.hxx:60
const char * getFileType() const
const char * getPixelType() const
VolumeExportInfo & setYResolution(float)
void exportImage(...)
Write an image to a file.
const ICCProfile & getICCProfile() const
linalg::TemporaryMatrix< T > log10(MultiArrayView< 2, T, C > const &v)
Argument object for the function exportVolume().
Definition: multi_impex.hxx:257
TinyVector< float, 3 > Resolution
3D resolution type returned by resolution()
Definition: multi_impex.hxx:88
const char * getPixelType() const
Argument object for the function importVolume().
Definition: multi_impex.hxx:76
void importImage(...)
Read an image from a file.
doxygen_overloaded_function(template<...> void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.
VolumeExportInfo & setPixelType(const char *)
MultiArrayIndex width() const
Class for fixed size vectors.This class contains an array of size SIZE of the specified VALUETYPE...
Definition: accessor.hxx:940
ArrayVector< unsigned char > ICCProfile
Definition: multi_impex.hxx:439
MultiArrayIndex depth() const
MultiArrayIndex height() const
image import and export functions
Base class for, and view to, vigra::MultiArray.
Definition: multi_array.hxx:704
MultiArrayShape< 3 >::type ShapeType
type of volume size returned by shape()
Definition: multi_impex.hxx:82
ShapeType size_type
type of volume size returned by shape()
Definition: multi_impex.hxx:85
int ceil(FixedPoint< IntBits, FracBits > v)
rounding up.
Definition: fixedpoint.hxx:675
VolumeExportInfo & setFileNameExt(const char *name_ext)
void inspectMultiArray(...)
Call an analyzing functor at every element of a multi-dimensional array.
Resolution resolution() const
PixelType pixelType() const
VolumeImportInfo(const std::string &filename)
VolumeExportInfo & setXResolution(float)
VolumeExportInfo & setICCProfile(const ICCProfile &profile)
VolumeExportInfo(const char *filename)
VolumeExportInfo & setFileType(const char *)

© 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.11.1 (Fri May 19 2017)