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