[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]
00001 /************************************************************************/ 00002 /* */ 00003 /* Copyright 2003 by Gunnar Kedenburg */ 00004 /* Cognitive Systems Group, University of Hamburg, Germany */ 00005 /* */ 00006 /* This file is part of the VIGRA computer vision library. */ 00007 /* ( Version 1.6.0, Aug 13 2008 ) */ 00008 /* The VIGRA Website is */ 00009 /* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ 00010 /* Please direct questions, bug reports, and contributions to */ 00011 /* ullrich.koethe@iwr.uni-heidelberg.de or */ 00012 /* vigra@informatik.uni-hamburg.de */ 00013 /* */ 00014 /* Permission is hereby granted, free of charge, to any person */ 00015 /* obtaining a copy of this software and associated documentation */ 00016 /* files (the "Software"), to deal in the Software without */ 00017 /* restriction, including without limitation the rights to use, */ 00018 /* copy, modify, merge, publish, distribute, sublicense, and/or */ 00019 /* sell copies of the Software, and to permit persons to whom the */ 00020 /* Software is furnished to do so, subject to the following */ 00021 /* conditions: */ 00022 /* */ 00023 /* The above copyright notice and this permission notice shall be */ 00024 /* included in all copies or substantial portions of the */ 00025 /* Software. */ 00026 /* */ 00027 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */ 00028 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ 00029 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ 00030 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ 00031 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ 00032 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ 00033 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ 00034 /* OTHER DEALINGS IN THE SOFTWARE. */ 00035 /* */ 00036 /************************************************************************/ 00037 00038 00039 #ifndef VIGRA_MULTI_IMPEX_HXX 00040 #define VIGRA_MULTI_IMPEX_HXX 00041 00042 #include <memory> 00043 #include <iomanip> 00044 #include <sstream> 00045 #include <iostream> 00046 #include <string> 00047 #include <fstream> 00048 00049 #include "config.hxx" 00050 #include "basicimageview.hxx" 00051 #include "impex.hxx" 00052 #include "multi_array.hxx" 00053 #include "multi_pointoperators.hxx" 00054 00055 #ifdef _MSC_VER 00056 # include <direct.h> 00057 #else 00058 # include <unistd.h> 00059 #endif 00060 00061 namespace vigra { 00062 00063 class VolumeImportInfo 00064 { 00065 public: 00066 typedef ImageImportInfo::PixelType PixelType; 00067 00068 /// type of volume size returned by shape() 00069 typedef MultiArrayShape<3>::type ShapeType; 00070 00071 /// provided for backwards-compatibility (deprecated) 00072 typedef ShapeType size_type; 00073 00074 /// 3D resolution type returned by resolution() 00075 typedef TinyVector<float, 3> Resolution; 00076 00077 VIGRA_EXPORT VolumeImportInfo(const std::string &filename); 00078 VIGRA_EXPORT VolumeImportInfo(const std::string &baseName, const std::string &extension); 00079 00080 VIGRA_EXPORT ShapeType shape() const { return shape_; } 00081 00082 /** 00083 * resolution() contains the alignment and resolution of the 00084 * volume. resolution()[0] is the x increment in a left-handed 00085 * world coordinate system of one unstrided step in the volume 00086 * memory. The [1] and [2] elements contain the y resp. z 00087 * increments of the strided row resp. slice steps in the 00088 * volume. 00089 * 00090 * EXAMPLES: (1.f, 1.f, 4.f) means that the slices are four 00091 * times thicker than the x/y resolution. 00092 * (1.f, -1.f, 1.f) means that the volume coordinate system is 00093 * right-handed. 00094 */ 00095 VIGRA_EXPORT Resolution resolution() const { return resolution_; } 00096 00097 VIGRA_EXPORT PixelType pixelType() const { return pixelType_; } 00098 00099 VIGRA_EXPORT int numBands() const { return numBands_; } 00100 VIGRA_EXPORT bool isGrayscale() const { return numBands_ == 1; } 00101 VIGRA_EXPORT bool isColor() const { return numBands_ > 1; } 00102 00103 // get base file name without path, image index, and extension 00104 VIGRA_EXPORT const std::string &name() const { return name_; } 00105 00106 VIGRA_EXPORT const std::string &description() const { return description_; } 00107 00108 template <class T, class Allocator> 00109 void importImpl(MultiArray <3, T, Allocator> &volume) const; 00110 00111 protected: 00112 void getVolumeInfoFromFirstSlice(const std::string &filename); 00113 00114 size_type shape_; 00115 Resolution resolution_; 00116 PixelType pixelType_; 00117 int numBands_; 00118 00119 std::string path_, name_, description_; 00120 00121 std::string rawFilename_; 00122 std::string baseName_, extension_; 00123 std::vector<std::string> numbers_; 00124 }; 00125 00126 template <class T, class Allocator> 00127 void VolumeImportInfo::importImpl(MultiArray <3, T, Allocator> &volume) const 00128 { 00129 volume.reshape(this->shape()); 00130 00131 if(rawFilename_.size()) 00132 { 00133 std::string dirName, baseName; 00134 char oldCWD[2048]; 00135 00136 #ifdef _MSC_VER 00137 _getcwd(oldCWD, 2048); 00138 if(_chdir(path_.c_str())) 00139 perror("chdir"); 00140 #else 00141 getcwd(oldCWD, 2048); 00142 if(chdir(path_.c_str())) 00143 perror("chdir"); 00144 #endif 00145 00146 std::ifstream s(rawFilename_.c_str(), std::ios::binary); 00147 vigra_precondition(s.good(), "RAW file could not be opened"); 00148 s.read((char*)volume.begin(), shape_[0]*shape_[1]*shape_[2]*sizeof(T)); 00149 00150 #ifdef _MSC_VER 00151 _chdir(oldCWD); 00152 #else 00153 chdir(oldCWD); 00154 #endif 00155 00156 vigra_postcondition( 00157 volume.shape() == shape(), "imported volume has wrong size"); 00158 } 00159 else 00160 { 00161 for (unsigned int i = 0; i < numbers_.size(); ++i) 00162 { 00163 // build the filename 00164 std::string name = baseName_ + numbers_[i] + extension_; 00165 00166 // import the image 00167 ImageImportInfo info (name.c_str ()); 00168 00169 // generate a basic image view to the current layer 00170 MultiArrayView <2, T> array_view (volume.bindOuter (i)); 00171 BasicImageView <T> view = makeBasicImageView (array_view); 00172 vigra_precondition(view.size() == info.size(), 00173 "importVolume(): image size mismatch."); 00174 00175 importImage (info, destImage(view)); 00176 } 00177 } 00178 } 00179 00180 00181 VIGRA_EXPORT void findImageSequence(const std::string &name_base, 00182 const std::string &name_ext, 00183 std::vector<std::string> & numbers); 00184 00185 /** \addtogroup VolumeImpex Import/export of volume data. 00186 */ 00187 00188 //@{ 00189 00190 /********************************************************/ 00191 /* */ 00192 /* importVolume */ 00193 /* */ 00194 /********************************************************/ 00195 00196 /** \brief Function for importing a 3D volume. 00197 00198 The data are expected to be stored in a by-slice manner, 00199 where the slices are enumerated from <tt>name_base+"[0-9]+"+name_ext</tt>. 00200 <tt>name_base</tt> may contain a path. All slice files with the same name base and 00201 extension are considered part of the same volume. Slice numbers must be non-negative, 00202 but can otherwise start anywhere and need not be successive. Slices will be read 00203 in ascending numerical (not lexicographic) order. All slices must have the 00204 same size. The <tt>volume</tt> will be reshaped to match the count and 00205 size of the slices found. 00206 00207 <b>\#include</b> 00208 <<a href="multi__impex_8hxx-source.html">vigra/multi_impex.hxx</a>> 00209 00210 Namespace: vigra 00211 */ 00212 template <class T, class Allocator> 00213 void importVolume (MultiArray <3, T, Allocator> & volume, 00214 const std::string &name_base, 00215 const std::string &name_ext) 00216 { 00217 VolumeImportInfo info(name_base, name_ext); 00218 00219 info.importImpl(volume); 00220 } 00221 00222 00223 /** \brief Function for importing a 3D volume. 00224 00225 The data can be given in two ways: 00226 00227 <UL> 00228 <LI> If the volume is stored in a by-slice manner (e.g. one image per slice), 00229 the <tt>filename</tt> can refer to an arbitrary image from the set. <tt>importVolume()</tt> 00230 then assumes that the slices are enumerated like <tt>name_base+"[0-9]+"+name_ext</tt>, 00231 where <tt>name_base</tt>, the index, and <tt>name_ext</tt> are determined automatically. 00232 All slice files with the same name base and extension are considered part of the same 00233 volume. Slice numbers must be non-negative, but can otherwise start anywhere and need 00234 not be successive. Slices will be read in ascending numerical (not lexicographic) order. 00235 All slices must have the same size. 00236 <li> Otherwise, <tt>importVolume()</tt> will try to read <tt>filename</tt> as an 00237 info text file with the following key-value pairs: 00238 <UL> 00239 <LI> name = [short descriptive name of the volume] (optional) 00240 <LI> filename = [absolute or relative path to raw voxel data file] (required) 00241 <li> gradfile = [absolute or relative path to gradient data file] (currently ignored) 00242 <li> description = [arbitrary description of the data set] (optional) 00243 <li> width = [positive integer] (required) 00244 <li> height = [positive integer] (required) 00245 <li> depth = [positive integer] (required) 00246 <li> datatype = [UNSIGNED_CHAR | UNSIGNED_BYTE] (default: UNSIGNED_CHAR) 00247 </UL> 00248 The voxel type is currently assumed to be binary compatible to the <tt>value_type T</TT> 00249 of the <tt>MuliArray</tt>. Lines starting with "#" are ignored. 00250 </UL> 00251 00252 In either case, the <tt>volume</tt> will be reshaped to match the count and 00253 size of the slices found. 00254 00255 <b>\#include</b> 00256 <<a href="multi__impex_8hxx-source.html">vigra/multi_impex.hxx</a>> 00257 00258 Namespace: vigra 00259 */ 00260 template <class T, class Allocator> 00261 void importVolume(MultiArray <3, T, Allocator> &volume, 00262 const std::string &filename) 00263 { 00264 VolumeImportInfo info(filename); 00265 00266 info.importImpl(volume); 00267 } 00268 00269 /** \brief Function for importing a 3D volume. 00270 00271 Read the volume data set <tt>info</tt> refers to. Explicit construction 00272 of the info object allows to allocate a <tt>volume</tt> object type whose 00273 <tt>value_type</tt> matches the voxel type of the stored data. 00274 The <tt>volume</tt> will be reshaped to match the count and 00275 size of the slices found. 00276 00277 <b>\#include</b> 00278 <<a href="multi__impex_8hxx-source.html">vigra/multi_impex.hxx</a>> 00279 00280 Namespace: vigra 00281 */ 00282 template <class T, class Allocator> 00283 void importVolume(VolumeImportInfo const & info, MultiArray <3, T, Allocator> &volume) 00284 { 00285 info.importImpl(volume); 00286 } 00287 00288 namespace detail { 00289 00290 template <class T> 00291 void setRangeMapping(std::string const & pixeltype, 00292 FindMinMax<T> const & minmax, ImageExportInfo & info) 00293 { 00294 if(pixeltype == "UINT8") 00295 info.setForcedRangeMapping(minmax.min, minmax.max, 00296 (double)NumericTraits<Int8>::min(), 00297 (double)NumericTraits<Int8>::max()); 00298 else if(pixeltype == "INT16") 00299 info.setForcedRangeMapping(minmax.min, minmax.max, 00300 (double)NumericTraits<Int16>::min(), 00301 (double)NumericTraits<Int16>::max()); 00302 else if(pixeltype == "UINT16") 00303 info.setForcedRangeMapping(minmax.min, minmax.max, 00304 (double)NumericTraits<UInt16>::min(), 00305 (double)NumericTraits<UInt16>::max()); 00306 else if(pixeltype == "INT32") 00307 info.setForcedRangeMapping(minmax.min, minmax.max, 00308 (double)NumericTraits<Int32>::min(), 00309 (double)NumericTraits<Int32>::max()); 00310 else if(pixeltype == "UINT32") 00311 info.setForcedRangeMapping(minmax.min, minmax.max, 00312 (double)NumericTraits<UInt32>::min(), 00313 (double)NumericTraits<UInt32>::max()); 00314 else if(pixeltype == "FLOAT") 00315 info.setForcedRangeMapping(minmax.min, minmax.max, 0.0, 1.0); 00316 else if(pixeltype == "DOUBLE") 00317 info.setForcedRangeMapping(minmax.min, minmax.max, 0.0, 1.0); 00318 } 00319 00320 template <class T, class Tag> 00321 void setRangeMapping(MultiArrayView <3, T, Tag> const & volume, 00322 ImageExportInfo & info, VigraTrueType /* isScalar */) 00323 { 00324 std::string pixeltype = info.getPixelType(); 00325 bool downcast = negotiatePixelType(getEncoderType(info.getFileName(), info.getFileType()), 00326 TypeAsString<T>::result(), pixeltype); 00327 00328 if(downcast) 00329 { 00330 FindMinMax<T> minmax; 00331 inspectMultiArray(srcMultiArrayRange(volume), minmax); 00332 setRangeMapping(pixeltype, minmax, info); 00333 } 00334 } 00335 00336 template <class T, class Tag> 00337 void setRangeMapping(MultiArrayView <3, T, Tag> const & volume, 00338 ImageExportInfo & info, VigraFalseType /* isScalar */) 00339 { 00340 typedef typename T::value_type SrcComponent; 00341 std::string pixeltype = info.getPixelType(); 00342 bool downcast = negotiatePixelType(getEncoderType(info.getFileName(), info.getFileType()), 00343 TypeAsString<SrcComponent>::result(), pixeltype); 00344 00345 if(downcast) 00346 { 00347 unsigned int bands = volume(0,0,0).size(); 00348 FindMinMax<SrcComponent> minmax; 00349 for(unsigned int i=0; i<bands; ++i) 00350 { 00351 VectorComponentValueAccessor<T> band(i); 00352 inspectMultiArray(srcMultiArrayRange(volume, band), minmax ); 00353 } 00354 setRangeMapping(pixeltype, minmax, info); 00355 } 00356 } 00357 00358 } // namespace detail 00359 00360 /********************************************************/ 00361 /* */ 00362 /* exportVolume */ 00363 /* */ 00364 /********************************************************/ 00365 00366 /** \brief Function for exporting a 3D volume. 00367 00368 The volume is exported in a by-slice manner, where the number of slices equals 00369 the depth of the volume. The file names will be enumerated like 00370 <tt>name_base+"000"+name_ext</tt>, <tt>name_base+"001"+name_ext</tt> etc. 00371 (the actual number of zeros depends on the depth). If the target image type 00372 does not support the source voxel type, all slices will be mapped simultaneously 00373 to the appropriate target range. 00374 00375 <b>\#include</b> 00376 <<a href="multi__impex_8hxx-source.html">vigra/multi_impex.hxx</a>> 00377 00378 Namespace: vigra 00379 */ 00380 template <class T, class Tag> 00381 void exportVolume (MultiArrayView <3, T, Tag> const & volume, 00382 const std::string &name_base, 00383 const std::string &name_ext) 00384 { 00385 std::string name = name_base + name_ext; 00386 ImageExportInfo info(name.c_str()); 00387 detail::setRangeMapping(volume, info, typename NumericTraits<T>::isScalar()); 00388 00389 const unsigned int depth = volume.shape (2); 00390 int numlen = static_cast <int> (std::ceil (std::log10 ((double)depth))); 00391 for (unsigned int i = 0; i < depth; ++i) 00392 { 00393 00394 // build the filename 00395 std::stringstream stream; 00396 stream << std::setfill ('0') << std::setw (numlen) << i; 00397 std::string name_num; 00398 stream >> name_num; 00399 std::string name = name_base + name_num + name_ext; 00400 00401 if(i == 0) 00402 { 00403 } 00404 00405 // generate a basic image view to the current layer 00406 MultiArrayView <2, T, Tag> array_view (volume.bindOuter (i)); 00407 BasicImageView <T> view = makeBasicImageView (array_view); 00408 00409 // export the image 00410 info.setFileName(name.c_str ()); 00411 exportImage(srcImageRange(view), info); 00412 } 00413 } 00414 00415 //@} 00416 00417 } // namespace vigra 00418 00419 #endif // VIGRA_MULTI_IMPEX_HXX
© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) |
html generated using doxygen and Python
|