[ 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#include "sifImport.hxx"
53
54#ifdef _MSC_VER
55# include <direct.h>
56#else
57# include <unistd.h>
58#endif
59
60namespace 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
460namespace detail {
461
462template <class DestIterator, class Shape, class T>
463inline void
464readVolumeImpl(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
476template <class DestIterator, class Shape, class T, int N>
477void
478readVolumeImpl(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
489template <class T, class Stride>
490void 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
584VIGRA_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*/
665doxygen_overloaded_function(template <...> void importVolume)
666
667template <class T, class Stride>
668void
669importVolume(VolumeImportInfo const & info,
670 MultiArrayView <3, T, Stride> &volume)
671{
672 info.importImpl(volume);
673}
674
675template <class T, class Allocator>
676void
677importVolume(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
686template <class T, class Allocator>
687void 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
697namespace detail {
698
699template <class T>
700void 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
729template <class T, class Tag>
730void 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
745template <class T, class Tag>
746void 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*/
827doxygen_overloaded_function(template <...> void exportVolume)
828
829template <class T, class Tag>
830void
831exportVolume (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
883template <class T, class Tag>
884inline void
885exportVolume (MultiArrayView <3, T, Tag> const & volume,
886 const std::string &filename)
887{
888 VolumeExportInfo volinfo(filename.c_str());
889 exportVolume(volume, volinfo);
890}
891
892template <class T, class Tag>
893inline void
894exportVolume (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
const_iterator begin() const
Definition array_vector.hxx:223
Definition array_vector.hxx:514
Two dimensional difference vector.
Definition diff2d.hxx:186
Argument object for the function exportImage().
Definition imageinfo.hxx:134
ImageExportInfo & setPixelType(const char *)
ImageExportInfo & setFileType(const char *)
ImageExportInfo & setFileName(const char *filename)
ImageExportInfo & setCompression(const char *type)
TinyVector< MultiArrayIndex, N > type
Definition multi_shape.hxx:272
const difference_type & shape() const
Definition multi_array.hxx:1650
MultiArrayView< N-M, T, StrideTag > bindOuter(const TinyVector< Index, M > &d) const
Definition multi_array.hxx:2186
Class for fixed size vectors.
Definition tinyvector.hxx:1008
Argument object for the function exportVolume().
Definition multi_impex.hxx:258
VolumeExportInfo & setPosition(const Diff2D &pos)
VolumeExportInfo & setCompression(const char *type)
ArrayVector< unsigned char > ICCProfile
Definition multi_impex.hxx:439
const char * getPixelType() const
VolumeExportInfo & setYResolution(float)
VolumeExportInfo(const char *filename)
Diff2D getPosition() const
const ICCProfile & getICCProfile() const
VolumeExportInfo & setFileType(const char *)
VolumeExportInfo & setZResolution(float)
VolumeExportInfo & setXResolution(float)
VolumeExportInfo & setFileNameBase(const char *name_base)
VolumeExportInfo(const char *name_base, const char *name_ext)
VolumeExportInfo & setICCProfile(const ICCProfile &profile)
VolumeExportInfo & setPixelType(const char *)
VolumeExportInfo & setFileNameExt(const char *name_ext)
Argument object for the function importVolume().
Definition multi_impex.hxx:77
MultiArrayShape< 3 >::type ShapeType
type of volume size returned by shape()
Definition multi_impex.hxx:82
MultiArrayIndex height() const
const char * getPixelType() const
MultiArrayIndex width() const
ShapeType size_type
type of volume size returned by shape()
Definition multi_impex.hxx:85
TinyVector< float, 3 > Resolution
3D resolution type returned by resolution()
Definition multi_impex.hxx:88
VolumeImportInfo(const std::string &base_name, const std::string &name_extension)
MultiArrayIndex depth() const
PixelType pixelType() const
ShapeType shape() const
const char * getFileType() const
Resolution resolution() const
VolumeImportInfo(const std::string &filename)
void exportImage(...)
Write an image to a file.
void importImage(...)
Read an image from a file.
image import and export functions
void readSIF(const SIFImportInfo &info, MultiArrayView< 3, float > array)
Read the image data specified by the given SIFImportInfo object and write them into the given 'array'...
void inspectMultiArray(...)
Call an analyzing functor at every element of a multi-dimensional array.
void importVolume(...)
Function for importing a 3D volume.
std::ptrdiff_t MultiArrayIndex
Definition multi_fwd.hxx:60
void exportVolume(...)
Function for exporting a 3D volume.

© 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.12.2 (Mon Apr 14 2025)