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

vigra/multi_impex.hxx

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)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
VIGRA 1.6.0 (13 Aug 2008)