[ 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)