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

vigra/impex.hxx
Go to the documentation of this file.
00001 /************************************************************************/
00002 /*                                                                      */
00003 /*               Copyright 2001-2002 by Gunnar Kedenburg                */
00004 /*                                                                      */
00005 /*    This file is part of the VIGRA computer vision library.           */
00006 /*    The VIGRA Website is                                              */
00007 /*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
00008 /*    Please direct questions, bug reports, and contributions to        */
00009 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
00010 /*        vigra@informatik.uni-hamburg.de                               */
00011 /*                                                                      */
00012 /*    Permission is hereby granted, free of charge, to any person       */
00013 /*    obtaining a copy of this software and associated documentation    */
00014 /*    files (the "Software"), to deal in the Software without           */
00015 /*    restriction, including without limitation the rights to use,      */
00016 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
00017 /*    sell copies of the Software, and to permit persons to whom the    */
00018 /*    Software is furnished to do so, subject to the following          */
00019 /*    conditions:                                                       */
00020 /*                                                                      */
00021 /*    The above copyright notice and this permission notice shall be    */
00022 /*    included in all copies or substantial portions of the             */
00023 /*    Software.                                                         */
00024 /*                                                                      */
00025 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
00026 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
00027 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
00028 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
00029 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
00030 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
00031 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
00032 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */
00033 /*                                                                      */
00034 /************************************************************************/
00035 /* Modifications by Pablo d'Angelo
00036  * updated to vigra 1.4 by Douglas Wilkins
00037  * as of 18 Febuary 2006:
00038  *  - Added import/export of UINT16 and UINT32 image types.
00039  * Modifications by Andrew Mihal
00040  * updated to vigra 1.4 by Douglas Wilkins
00041  * as of 18 Febuary 2006:
00042  *  - Moved some RowIterator declarations around to avoid using default ctors
00043  *    (cachedfileimages do not have default ctors for row iterators).
00044  *  - Added some case-specific optimizations
00045  */
00046 
00047 /*!
00048   \file  impex.hxx
00049   \brief image import and export functions
00050 
00051   this file provides the declarations and implementations of importImage()
00052   and exportImage(). the matching implementation for the given datatype is
00053   selected by template metacode.
00054 */
00055 
00056 #ifndef VIGRA_IMPEX_HXX
00057 #define VIGRA_IMPEX_HXX
00058 
00059 #include "sized_int.hxx"
00060 #include "stdimage.hxx"
00061 #include "tinyvector.hxx"
00062 #include "imageinfo.hxx"
00063 #include "numerictraits.hxx"
00064 #include "codec.hxx"
00065 #include "accessor.hxx"
00066 #include "inspectimage.hxx"
00067 #include "transformimage.hxx"
00068 #include "copyimage.hxx"
00069 #include "multi_array.hxx"
00070 
00071 // TODO
00072 // next refactoring: pluggable conversion algorithms
00073 
00074 namespace vigra
00075 {
00076 /** \addtogroup VigraImpex
00077 **/
00078 //@{
00079 
00080     /*!
00081       \brief used for reading bands after the source data type has been figured out.
00082 
00083         <b>\#include</b> <<a href="impex_8hxx-source.html">vigra/impex.hxx</a>><br>
00084         Namespace: vigra
00085 
00086         <b> Declaration:</b>
00087 
00088         \code
00089         namespace vigra {
00090             template< class ImageIterator, class Accessor, class SrcValueType >
00091             void read_bands( Decoder * dec, ImageIterator ys, Accessor a, SrcValueType )
00092         }
00093         \endcode
00094 
00095       \param dec decoder object through which the source data will be accessed
00096       \param ys  image iterator referencing the upper left pixel of the destination image
00097       \param a   image accessor for the destination image
00098     */
00099     template< class ImageIterator, class Accessor, class SrcValueType >
00100     void read_bands( Decoder * dec, ImageIterator ys, Accessor a, SrcValueType )
00101     {
00102         typedef unsigned int size_type;
00103         typedef typename ImageIterator::row_iterator DstRowIterator;
00104         typedef typename Accessor::value_type  AccessorValueType;
00105         typedef typename AccessorValueType::value_type DstValueType;
00106 
00107         const size_type width = dec->getWidth();
00108         const size_type height = dec->getHeight();
00109         const size_type num_bands = dec->getNumBands();
00110 
00111         vigra_precondition(num_bands == (size_type)a.size(ys),
00112            "importImage(): number of bands (color channels) in file and destination image differ.");
00113 
00114         SrcValueType const * scanline;
00115         // MIHAL no default constructor available for cachedfileimages.
00116         DstRowIterator xs = ys.rowIterator();
00117 
00118         // iterate
00119         if (num_bands == 4) {
00120             // Speedup for this particular case
00121             unsigned int offset = dec->getOffset();
00122             SrcValueType const * scanline0;
00123             SrcValueType const * scanline1;
00124             SrcValueType const * scanline2;
00125             SrcValueType const * scanline3;
00126             for( size_type y = 0; y < height; ++y, ++ys.y ) {
00127                 dec->nextScanline();
00128                 xs = ys.rowIterator();
00129                 scanline0 = static_cast< SrcValueType const * >
00130                     (dec->currentScanlineOfBand(0));
00131                 scanline1 = static_cast< SrcValueType const * >
00132                     (dec->currentScanlineOfBand(1));
00133                 scanline2 = static_cast< SrcValueType const * >
00134                     (dec->currentScanlineOfBand(2));
00135                 scanline3 = static_cast< SrcValueType const * >
00136                     (dec->currentScanlineOfBand(3));
00137                 for( size_type x = 0; x < width; ++x, ++xs ) {
00138 /*
00139                     a.template setComponent<SrcValueType, DstRowIterator, 0>( *scanline0, xs );
00140                     a.template setComponent<SrcValueType, DstRowIterator, 1>( *scanline1, xs );
00141                     a.template setComponent<SrcValueType, DstRowIterator, 2>( *scanline2, xs );
00142                     a.template setComponent<SrcValueType, DstRowIterator, 3>( *scanline3, xs );
00143 */
00144                     a.setComponent( *scanline0, xs, 0);
00145                     a.setComponent( *scanline1, xs, 1);
00146                     a.setComponent( *scanline2, xs, 2);
00147                     a.setComponent( *scanline3, xs, 3);
00148                     scanline0 += offset;
00149                     scanline1 += offset;
00150                     scanline2 += offset;
00151                     scanline3 += offset;
00152                 }
00153             }
00154         }
00155         else {
00156             // General case
00157         for( size_type y = 0; y < height; ++y, ++ys.y ) {
00158             dec->nextScanline();
00159             for( size_type b = 0; b < num_bands; ++b ) {
00160                 xs = ys.rowIterator();
00161                 scanline = static_cast< SrcValueType const * >
00162                     (dec->currentScanlineOfBand(b));
00163                 for( size_type x = 0; x < width; ++x, ++xs ) {
00164                     a.setComponent( *scanline, xs, b );
00165                     scanline += dec->getOffset();
00166                 }
00167             }
00168         }
00169         }
00170     } // read_bands()
00171 
00172     /*!
00173       \brief used for reading bands after the source data type has been figured out.
00174 
00175         <b>\#include</b> <<a href="impex_8hxx-source.html">vigra/impex.hxx</a>><br>
00176         Namespace: vigra
00177 
00178         <b> Declaration:</b>
00179 
00180         \code
00181         namespace vigra {
00182             template< class ImageIterator, class Accessor, class SrcValueType >
00183             void read_band( Decoder * dec, ImageIterator ys, Accessor a, SrcValueType )
00184         }
00185         \endcode
00186 
00187       \param dec decoder object through which the source data will be accessed
00188       \param ys  image iterator referencing the upper left pixel of the destination image
00189       \param a   image accessor for the destination image
00190     */
00191     template< class ImageIterator, class Accessor, class SrcValueType >
00192     void read_band( Decoder * dec, ImageIterator ys, Accessor a, SrcValueType )
00193     {
00194         typedef unsigned int size_type;
00195         typedef typename ImageIterator::row_iterator DstRowIterator;
00196         typedef typename Accessor::value_type DstValueType;
00197         const size_type width = dec->getWidth();
00198         const size_type height = dec->getHeight();
00199 
00200         SrcValueType const * scanline;
00201         // MIHAL no default constructor available for cachedfileimages.
00202         DstRowIterator xs = ys.rowIterator();
00203 
00204         for( size_type y = 0; y < height; ++y, ++ys.y ) {
00205             dec->nextScanline();
00206             xs = ys.rowIterator();
00207             scanline = static_cast< SrcValueType const * >(dec->currentScanlineOfBand(0));
00208             for( size_type x = 0; x < width; ++x, ++xs )
00209                 a.set( scanline[x], xs );
00210         }
00211     } // read_band()
00212 
00213     /*!
00214       \brief used for reading images of vector type, such as integer of float rgb.
00215 
00216         <b>\#include</b> <<a href="impex_8hxx-source.html">vigra/impex.hxx</a>><br>
00217         Namespace: vigra
00218 
00219         <b> Declaration:</b>
00220 
00221         \code
00222         namespace vigra {
00223             template< class ImageIterator, class Accessor >
00224             void importVectorImage( const ImageImportInfo & info, ImageIterator iter, Accessor a )
00225         }
00226         \endcode
00227 
00228         <b> Paramters:</b>
00229 
00230         <DL>
00231         <DT>ImageIterator<DD> the image iterator type for the destination image
00232         <DT>Accessor<DD> the image accessor type for the destination image
00233         <DT>info<DD> user supplied image import information
00234         <DT>iter<DD> image iterator referencing the upper left pixel of the destination image
00235         <DT>a<DD> image accessor for the destination image
00236         </DL>
00237     */
00238 doxygen_overloaded_function(template <...> void importVectorImage)
00239 
00240     template< class ImageIterator, class Accessor >
00241     void importVectorImage( const ImageImportInfo & info, ImageIterator iter, Accessor a )
00242     {
00243         std::auto_ptr<Decoder> dec = decoder(info);
00244         std::string pixeltype = dec->getPixelType();
00245 
00246         if ( pixeltype == "UINT8" )
00247             read_bands( dec.get(), iter, a, (UInt8)0 );
00248         else if ( pixeltype == "INT16" )
00249             read_bands( dec.get(), iter, a, Int16() );
00250         else if ( pixeltype == "UINT16" )
00251             read_bands( dec.get(), iter, a, (UInt16)0 );
00252         else if ( pixeltype == "INT32" )
00253             read_bands( dec.get(), iter, a, Int32() );
00254         else if ( pixeltype == "UINT32" )
00255             read_bands( dec.get(), iter, a, (UInt32)0 );
00256         else if ( pixeltype == "FLOAT" )
00257             read_bands( dec.get(), iter, a, float() );
00258         else if ( pixeltype == "DOUBLE" )
00259             read_bands( dec.get(), iter, a, double() );
00260         else
00261             vigra_precondition( false, "invalid pixeltype" );
00262 
00263         // close the decoder
00264         dec->close();
00265     }
00266 
00267     /*!
00268       \brief used for reading images of  scalar type, such as integer and float grayscale.
00269 
00270         <b>\#include</b> <<a href="impex_8hxx-source.html">vigra/impex.hxx</a>><br>
00271         Namespace: vigra
00272 
00273         <b> Declaration:</b>
00274 
00275         \code
00276         namespace vigra {
00277             template < class ImageIterator, class Accessor >
00278             void importScalarImage( const ImageImportInfo & info, ImageIterator iter, Accessor a )
00279         }
00280         \endcode
00281 
00282         <b> Paramters:</b>
00283 
00284         <DL>
00285         <DT>ImageIterator<DD> the image iterator type for the destination image
00286         <DT>Accessor<DD> the image accessor type for the destination image
00287         <DT>info<DD> user supplied image import information
00288         <DT>iter<DD> image iterator referencing the upper left pixel of the destination image
00289         <DT>a<DD> image accessor for the destination image
00290         </DL>
00291     */
00292 doxygen_overloaded_function(template <...> void importScalarImage)
00293 
00294     template < class ImageIterator, class Accessor >
00295     void importScalarImage( const ImageImportInfo & info, ImageIterator iter, Accessor a )
00296     {
00297         std::auto_ptr<Decoder> dec = decoder(info);
00298         std::string pixeltype = dec->getPixelType();
00299 
00300         if ( pixeltype == "UINT8" )
00301             read_band( dec.get(), iter, a, (UInt8)0 );
00302         else if ( pixeltype == "INT16" )
00303             read_band( dec.get(), iter, a, Int16() );
00304         else if ( pixeltype == "UINT16" )
00305             read_band( dec.get(), iter, a, (UInt16)0 );
00306         else if ( pixeltype == "INT32" )
00307             read_band( dec.get(), iter, a, Int32() );
00308         else if ( pixeltype == "UINT32" )
00309             read_band( dec.get(), iter, a, (UInt32)0 );
00310         else if ( pixeltype == "FLOAT" )
00311             read_band( dec.get(), iter, a, float() );
00312         else if ( pixeltype == "DOUBLE" )
00313             read_band( dec.get(), iter, a, double() );
00314         else
00315             vigra_precondition( false, "invalid pixeltype" );
00316 
00317         // close the decoder
00318         dec->close();
00319     }
00320 
00321 /********************************************************/
00322 /*                                                      */
00323 /*                     importImage                      */
00324 /*                                                      */
00325 /********************************************************/
00326 
00327     /** \brief Read the image specified by the given \ref vigra::ImageImportInfo object.
00328 
00329         <b> Declarations:</b>
00330 
00331         pass arguments explicitly:
00332         \code
00333         namespace vigra {
00334             template <class ImageIterator, class Accessor>
00335             void
00336             importImage(ImageImportInfo const & image, ImageIterator iter, Accessor a)
00337         }
00338         \endcode
00339 
00340         use argument objects in conjunction with \ref ArgumentObjectFactories :
00341         \code
00342         namespace vigra {
00343             template <class ImageIterator, class Accessor>
00344             inline void
00345             importImage(ImageImportInfo const & image, pair<ImageIterator, Accessor> dest)
00346         }
00347         \endcode
00348 
00349         <b> Usage:</b>
00350 
00351         <b>\#include</b> <<a href="impex_8hxx-source.html">vigra/impex.hxx</a>><br>
00352         Namespace: vigra
00353 
00354         \code
00355 
00356         vigra::ImageImportInfo info("myimage.gif");
00357 
00358         if(info.isGrayscale())
00359         {
00360             // create byte image of appropriate size
00361             vigra::BImage in(info.width(), info.height());
00362 
00363             vigra::importImage(info, destImage(in)); // read the image
00364             ...
00365         }
00366         else
00367         {
00368             // create byte RGB image of appropriate size
00369             vigra::BRGBImage in(info.width(), info.height());
00370 
00371             vigra::importImage(info, destImage(in)); // read the image
00372             ...
00373         }
00374 
00375         \endcode
00376 
00377         <b> Preconditions:</b>
00378 
00379         <UL>
00380 
00381         <LI> the image file must be readable
00382         <LI> the file type must be one of
00383 
00384                 <DL>
00385                 <DT>"BMP"<DD> Microsoft Windows bitmap image file.
00386                 <DT>"GIF"<DD> CompuServe graphics interchange format; 8-bit color.
00387                 <DT>"JPEG"<DD> Joint Photographic Experts Group JFIF format; compressed 24-bit color. (only available if libjpeg is installed)
00388                 <DT>"PNG"<DD> Portable Network Graphic. (only available if libpng is installed)
00389                 <DT>"PBM"<DD> Portable bitmap format (black and white).
00390                 <DT>"PGM"<DD> Portable graymap format (gray scale).
00391                 <DT>"PNM"<DD> Portable anymap.
00392                 <DT>"PPM"<DD> Portable pixmap format (color).
00393                 <DT>"SUN"<DD> SUN Rasterfile.
00394                 <DT>"TIFF"<DD> Tagged Image File Format. (only available if libtiff is installed.)
00395                 <DT>"VIFF"<DD> Khoros Visualization image file.
00396                 </DL>
00397         </UL>
00398     **/
00399 doxygen_overloaded_function(template <...> void importImage)
00400 
00401     template < class ImageIterator, class Accessor >
00402     void importImage( const ImageImportInfo & info, ImageIterator iter, Accessor a )
00403     {
00404         typedef typename NumericTraits<typename Accessor::value_type>::isScalar is_scalar;
00405         importImage( info, iter, a, is_scalar() );
00406     }
00407 
00408     template < class ImageIterator, class Accessor >
00409     void importImage( const ImageImportInfo & info, pair< ImageIterator, Accessor > dest )
00410     {
00411         importImage( info, dest.first, dest.second );
00412     }
00413 
00414     template < class ImageIterator, class Accessor >
00415     void importImage( const ImageImportInfo & info, ImageIterator iter, Accessor a, VigraFalseType )
00416     {
00417         importVectorImage( info, iter, a );
00418     }
00419 
00420     template < class ImageIterator, class Accessor >
00421     void importImage( const ImageImportInfo & info, ImageIterator iter, Accessor a, VigraTrueType )
00422     {
00423         importScalarImage( info, iter, a );
00424     }
00425 
00426     /*!
00427       \brief used for writing bands after the source data type has been figured out.
00428 
00429         <b>\#include</b> <<a href="impex_8hxx-source.html">vigra/impex.hxx</a>><br>
00430         Namespace: vigra
00431 
00432         <b> Declaration:</b>
00433 
00434         \code
00435         namespace vigra {
00436             template< class ImageIterator, class Accessor, class DstValueType >
00437             void write_bands( Encoder * enc, ImageIterator ul, ImageIterator lr, Accessor a, DstValueType )
00438         }
00439         \endcode
00440 
00441       \param enc encoder object through which the destination data will be accessed
00442       \param ul  image iterator referencing the upper left pixel of the source image
00443       \param lr  image iterator referencing the lower right pixel of the source image
00444       \param a   image accessor for the source image
00445     */
00446     template< class ImageIterator, class Accessor, class DstValueType >
00447     void write_bands( Encoder * enc, ImageIterator ul, ImageIterator lr, Accessor a, DstValueType)
00448     {
00449         typedef unsigned int size_type;
00450         typedef typename ImageIterator::row_iterator SrcRowIterator;
00451         typedef typename Accessor::value_type  AccessorValueType;
00452         typedef typename AccessorValueType::value_type SrcValueType;
00453 
00454         // complete decoder settings
00455         const size_type width = lr.x - ul.x;
00456         const size_type height = lr.y - ul.y;
00457         enc->setWidth(width);
00458         enc->setHeight(height);
00459         const size_type num_bands = a.size(ul);
00460         enc->setNumBands(num_bands);
00461         enc->finalizeSettings();
00462 
00463         DstValueType * scanline;
00464 
00465         // iterate
00466         ImageIterator ys(ul);
00467         // MIHAL no default constructor available for cachedfileimages
00468         SrcRowIterator xs = ys.rowIterator();
00469 
00470             // Speedup for the common cases
00471         switch (num_bands) 
00472         {
00473           case 2:
00474           {
00475             unsigned int offset = enc->getOffset();
00476             DstValueType * scanline0;
00477             DstValueType * scanline1;
00478             for( size_type y = 0; y < height; ++y, ++ys.y ) {
00479                 xs = ys.rowIterator();
00480                 scanline0 = static_cast< DstValueType * >
00481                         (enc->currentScanlineOfBand(0));
00482                 scanline1 = static_cast< DstValueType * >
00483                         (enc->currentScanlineOfBand(1));
00484                 for( size_type x = 0; x < width; ++x, ++xs) {
00485                     *scanline0 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 0));
00486                     *scanline1 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 1));
00487                     scanline0 += offset;
00488                     scanline1 += offset;
00489                 }
00490                 enc->nextScanline();
00491                 
00492             }
00493             break;
00494           }
00495           case 3:
00496           {
00497             unsigned int offset = enc->getOffset();
00498             DstValueType * scanline0;
00499             DstValueType * scanline1;
00500             DstValueType * scanline2;
00501             for( size_type y = 0; y < height; ++y, ++ys.y ) {
00502                 xs = ys.rowIterator();
00503                 scanline0 = static_cast< DstValueType * >
00504                         (enc->currentScanlineOfBand(0));
00505                 scanline1 = static_cast< DstValueType * >
00506                         (enc->currentScanlineOfBand(1));
00507                 scanline2 = static_cast< DstValueType * >
00508                         (enc->currentScanlineOfBand(2));
00509                 for( size_type x = 0; x < width; ++x, ++xs) {
00510                     *scanline0 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 0));
00511                     *scanline1 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 1));
00512                     *scanline2 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 2));
00513                     scanline0 += offset;
00514                     scanline1 += offset;
00515                     scanline2 += offset;
00516                 }
00517                 enc->nextScanline();
00518             }
00519             break;
00520           }
00521           case 4:
00522           {
00523             unsigned int offset = enc->getOffset();
00524             DstValueType * scanline0;
00525             DstValueType * scanline1;
00526             DstValueType * scanline2;
00527             DstValueType * scanline3;
00528             for( size_type y = 0; y < height; ++y, ++ys.y ) {
00529                 xs = ys.rowIterator();
00530                 scanline0 = static_cast< DstValueType * >
00531                         (enc->currentScanlineOfBand(0));
00532                 scanline1 = static_cast< DstValueType * >
00533                         (enc->currentScanlineOfBand(1));
00534                 scanline2 = static_cast< DstValueType * >
00535                         (enc->currentScanlineOfBand(2));
00536                 scanline3 = static_cast< DstValueType * >
00537                         (enc->currentScanlineOfBand(3));
00538                 for( size_type x = 0; x < width; ++x, ++xs) {
00539                     *scanline0 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 0));
00540                     *scanline1 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 1));
00541                     *scanline2 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 2));
00542                     *scanline3 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 3));
00543                     scanline0 += offset;
00544                     scanline1 += offset;
00545                     scanline2 += offset;
00546                     scanline3 += offset;
00547                 }
00548                 enc->nextScanline();
00549             }
00550             break;
00551           }
00552           default:
00553           {
00554             // General case
00555             for( size_type y = 0; y < height; ++y, ++ys.y ) {
00556                 for( size_type b = 0; b < num_bands; ++b ) {
00557                     xs = ys.rowIterator();
00558                     scanline = static_cast< DstValueType * >
00559                         (enc->currentScanlineOfBand(b));
00560                     for( size_type x = 0; x < width; ++x, ++xs ) {
00561                         *scanline = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, b ));
00562                         scanline += enc->getOffset();
00563                     }
00564                 }
00565                 enc->nextScanline();
00566             }
00567           }
00568         }
00569     } // write_bands()
00570 
00571     template< class MArray, class DstValueType >
00572     void write_bands( Encoder * enc, MArray const & array, DstValueType)
00573     {
00574         typedef unsigned int size_type;
00575 
00576         // complete decoder settings
00577         const size_type width = array.shape(0);
00578         const size_type height = array.shape(1);
00579         enc->setWidth(width);
00580         enc->setHeight(height);
00581         const size_type num_bands = array.shape(2);
00582         enc->setNumBands(num_bands);
00583         enc->finalizeSettings();
00584 
00585         DstValueType * scanline;
00586 
00587         // iterate
00588         for( size_type y = 0; y < height; ++y ) {
00589             for( size_type b = 0; b < num_bands; ++b ) {
00590                 scanline = static_cast< DstValueType * >
00591                     (enc->currentScanlineOfBand(b));
00592                 for( size_type x = 0; x < width; ++x) {
00593                     *scanline = array(x, y, b);
00594                     scanline += enc->getOffset();
00595                 }
00596             }
00597             enc->nextScanline();
00598         }
00599     } // write_bands()
00600 
00601     /*!
00602       \brief used for writing bands after the source data type has been figured out.
00603 
00604         <b>\#include</b> <<a href="impex_8hxx-source.html">vigra/impex.hxx</a>><br>
00605         Namespace: vigra
00606 
00607         <b> Declaration:</b>
00608 
00609         \code
00610         namespace vigra {
00611             template< class ImageIterator, class Accessor, class DstValueType >
00612             void write_band( Encoder * enc, ImageIterator ul, ImageIterator lr, Accessor a, DstValueType )
00613         }
00614         \endcode
00615 
00616       \param enc encoder object through which the destination data will be accessed
00617       \param ul  image iterator referencing the upper left pixel of the source image
00618       \param lr  image iterator referencing the lower right pixel of the source image
00619       \param a   image accessor for the source image
00620     */
00621     template< class ImageIterator, class Accessor, class DstValueType >
00622     void write_band( Encoder * enc, ImageIterator ul, ImageIterator lr, Accessor a, DstValueType)
00623     {
00624         typedef unsigned int size_type;
00625         typedef typename ImageIterator::row_iterator SrcRowIterator;
00626         typedef typename Accessor::value_type SrcValueType;
00627 
00628         // complete decoder settings
00629         const size_type width = size_type(lr.x - ul.x);
00630         const size_type height = size_type(lr.y - ul.y);
00631         enc->setWidth(width);
00632         enc->setHeight(height);
00633         enc->setNumBands(1);
00634         enc->finalizeSettings();
00635 
00636         DstValueType * scanline;
00637 
00638         // iterate
00639         ImageIterator ys(ul);
00640         // MIHAL no default constructor available for cachedfileimages.
00641         SrcRowIterator xs = ys.rowIterator();
00642         size_type y;
00643         for(  y = 0; y < height; ++y, ++ys.y ) {
00644             xs = ys.rowIterator();
00645             scanline = static_cast< DstValueType * >(enc->currentScanlineOfBand(0));
00646             for( size_type x = 0; x < width; ++x, ++xs, ++scanline )
00647                 *scanline = detail::RequiresExplicitCast<DstValueType>::cast(a(xs));
00648             enc->nextScanline();
00649         }
00650     } // write_band()
00651 
00652 namespace detail {
00653 
00654     // export scalar images without conversion
00655     template < class SrcIterator, class SrcAccessor, class T >
00656     void exportScalarImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00657                            Encoder * enc, T zero)
00658     {
00659         write_band( enc, sul, slr, sget, zero );
00660     }
00661 
00662     // export scalar images with conversion 
00663     template < class SrcIterator, class SrcAccessor, class T >
00664     void exportScalarImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00665                            Encoder * enc, 
00666                            const ImageExportInfo & info, 
00667                            T zero)
00668     {
00669         double fromMin, fromMax, toMin, toMax;
00670         if(info.getFromMin() < info.getFromMax())
00671         {
00672             fromMin = info.getFromMin();
00673             fromMax = info.getFromMax();
00674         }
00675         else
00676         {
00677             typedef typename SrcAccessor::value_type SrcValue;
00678             FindMinMax<SrcValue> minmax;
00679             inspectImage( sul, slr, sget, minmax );
00680             
00681             fromMin = (double)minmax.min;
00682             fromMax = (double)minmax.max;
00683             if(fromMax <= fromMin)
00684                 fromMax = fromMin + 1.0;
00685        }
00686         
00687         if(info.getToMin() < info.getToMax())
00688         {
00689             toMin = info.getToMin();
00690             toMax = info.getToMax();
00691         }
00692         else
00693         {
00694             toMin = (double)NumericTraits<T>::min();
00695             toMax = (double)NumericTraits<T>::max();
00696         }
00697         
00698         double scale = (toMax - toMin) / (fromMax - fromMin);
00699         double offset = (toMin / scale) - fromMin;
00700         BasicImage<T> image(slr-sul);
00701         transformImage( sul, slr, sget, image.upperLeft(), image.accessor(), 
00702                         linearIntensityTransform(scale, offset));
00703         write_band( enc, image.upperLeft(),
00704                     image.lowerRight(), image.accessor(), zero );
00705     }
00706 
00707     // export vector images without conversion
00708     template < class SrcIterator, class SrcAccessor, class T >
00709     void exportVectorImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00710                            Encoder * enc, T zero)
00711     {
00712         int bands = sget.size(sul);
00713         vigra_precondition(isBandNumberSupported(enc->getFileType(), bands),
00714            "exportImage(): file format does not support requested number of bands (color channels)");
00715         write_bands( enc, sul, slr, sget, zero );
00716     }
00717     
00718     // export vector images with conversion
00719     template < class SrcIterator, class SrcAccessor, class T >
00720     void exportVectorImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00721                            Encoder * enc, 
00722                            const ImageExportInfo & info, 
00723                            T zero)
00724     {
00725         unsigned int bands = sget.size(sul);
00726         vigra_precondition(isBandNumberSupported(enc->getFileType(), bands),
00727            "exportImage(): file format does not support requested number of bands (color channels)");
00728 
00729         typedef typename SrcAccessor::ElementAccessor SrcElementAccessor;
00730         typedef typename SrcElementAccessor::value_type SrcComponent;
00731         double fromMin, fromMax, toMin, toMax;
00732         if(info.getFromMin() < info.getFromMax())
00733         {
00734             fromMin = info.getFromMin();
00735             fromMax = info.getFromMax();
00736         }
00737         else
00738         {
00739             FindMinMax<SrcComponent> minmax;
00740             for(unsigned int i=0; i<bands; ++i)
00741             {
00742                 SrcElementAccessor band(i, sget);
00743                 inspectImage( sul, slr, band, minmax );
00744             }
00745 
00746             fromMin = (double)minmax.min;
00747             fromMax = (double)minmax.max;
00748             if(fromMax <= fromMin)
00749                 fromMax = fromMin + 1.0;
00750         }
00751         
00752         if(info.getToMin() < info.getToMax())
00753         {
00754             toMin = info.getToMin();
00755             toMax = info.getToMax();
00756         }
00757         else
00758         {
00759             toMin = (double)NumericTraits<T>::min();
00760             toMax = (double)NumericTraits<T>::max();
00761         }
00762 
00763         double scale = (toMax - toMin) / (fromMax - fromMin);
00764         double offset = (toMin / scale) - fromMin;
00765         int w = slr.x - sul.x;
00766         int h = slr.y - sul.y;
00767 
00768         typedef vigra::MultiArray<3, T> MArray;
00769         MArray array(typename MArray::difference_type(w, h, bands));
00770 
00771         for(unsigned int i=0; i<bands; ++i)
00772         {
00773             BasicImageView<T> subImage = makeBasicImageView(array.bindOuter(i));
00774             SrcElementAccessor band(i, sget);
00775             transformImage( sul, slr, band, subImage.upperLeft(), subImage.accessor(),
00776                             linearIntensityTransform( scale, offset ) );
00777         }
00778         write_bands( enc, array, zero );
00779     }
00780 
00781 } // namespace detail
00782 
00783 
00784     /*!
00785       \brief Deprecated.
00786 
00787         Use \ref exportImage() instead.
00788 
00789         <b> Declaration:</b>
00790 
00791         \code
00792         namespace vigra {
00793             template < class SrcIterator, class SrcAccessor >
00794             void exportFloatingVectorImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00795                                             const ImageExportInfo & info )
00796         }
00797         \endcode
00798     */
00799 doxygen_overloaded_function(template <...> void exportFloatingVectorImage)
00800 
00801     template < class SrcIterator, class SrcAccessor >
00802     void exportFloatingVectorImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00803                                     const ImageExportInfo & info )
00804     {
00805         exportImage(sul, slr, sget, info);
00806     }
00807 
00808     /*!
00809       \brief Deprecated.
00810 
00811         Use \ref exportImage() instead.
00812 
00813         <b> Declaration:</b>
00814 
00815         \code
00816         namespace vigra {
00817             template < class SrcIterator, class SrcAccessor >
00818             void exportIntegralVectorImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00819                                             const ImageExportInfo & info )
00820         }
00821         \endcode
00822     */
00823 doxygen_overloaded_function(template <...> void exportIntegralVectorImage)
00824 
00825     template < class SrcIterator, class SrcAccessor >
00826     void exportIntegralVectorImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00827                                     const ImageExportInfo & info )
00828     {
00829         exportImage(sul, slr, sget, info);
00830     }
00831 
00832     /*!
00833       \brief Deprecated.
00834 
00835         Use \ref exportImage() instead.
00836 
00837         <b> Declaration:</b>
00838 
00839         \code
00840         namespace vigra {
00841             template < class SrcIterator, class SrcAccessor >
00842             void exportFloatingScalarImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00843                                             const ImageExportInfo & info )
00844         }
00845         \endcode
00846     */
00847 doxygen_overloaded_function(template <...> void exportFloatingScalarImage)
00848 
00849     template < class SrcIterator, class SrcAccessor >
00850     void exportFloatingScalarImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00851                                     const ImageExportInfo & info )
00852     {
00853         exportImage(sul, slr, sget, info);
00854     }
00855 
00856     /*!
00857       \brief Deprecated.
00858 
00859         Use \ref exportImage() instead.
00860 
00861         <b> Declaration:</b>
00862 
00863         \code
00864         namespace vigra {
00865             template < class SrcIterator, class SrcAccessor >
00866             void exportIntegralScalarImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00867                                             const ImageExportInfo & info )
00868         }
00869         \endcode
00870     */
00871 doxygen_overloaded_function(template <...> void exportIntegralScalarImage)
00872 
00873     template < class SrcIterator, class SrcAccessor >
00874     void exportIntegralScalarImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00875                                     const ImageExportInfo & info )
00876     {
00877         exportImage(sul, slr, sget, info);
00878     }
00879 
00880 /********************************************************/
00881 /*                                                      */
00882 /*                     exportImage                      */
00883 /*                                                      */
00884 /********************************************************/
00885 
00886 /** \brief Write an image, given an \ref vigra::ImageExportInfo object.
00887 
00888     If the file format to be exported to supports the pixel type of the
00889     source image, the pixel type will be kept (e.g. <tt>float</tt>
00890     can be stored as TIFF without conversion, in contrast to most other
00891     image export toolkits). Otherwise, the pixel values are transformed
00892     to the range 0.255 and converted to <tt>unsigned char</tt>. Currently,
00893     the following file formats are supported. The pixel types given in
00894     brackets are those that are written without conversion:
00895 
00896     <DL>
00897     <DT>"BMP"<DD> Microsoft Windows bitmap image file (pixel types: UINT8 as gray and RGB).
00898     <DT>"GIF"<DD> CompuServe graphics interchange format; 8-bit color (pixel types: UINT8 as gray and RGB).
00899     <DT>"JPEG"<DD> Joint Photographic Experts Group JFIF format; compressed 24-bit color
00900                   (pixel types: UINT8 as gray and RGB). (only available if libjpeg is installed)
00901     <DT>"PNG"<DD> Portable Network Graphic (pixel types: UINT8 and UINT16 with up to 4 channels).
00902                   (only available if libpng is installed)
00903     <DT>"PBM"<DD> Portable bitmap format (black and white).
00904     <DT>"PGM"<DD> Portable graymap format (pixel types: UINT8, INT16, INT32 as gray scale)).
00905     <DT>"PNM"<DD> Portable anymap (pixel types: UINT8, INT16, INT32 as gray and RGB).
00906     <DT>"PPM"<DD> Portable pixmap format (pixel types: UINT8, INT16, INT32 as RGB).
00907     <DT>"SUN"<DD> SUN Rasterfile (pixel types: UINT8 as gray and RGB).
00908     <DT>"TIFF"<DD> Tagged Image File Format
00909                 (pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with up to 4 channels).
00910                 (only available if libtiff is installed.)
00911     <DT>"VIFF"<DD> Khoros Visualization image file
00912         (pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with arbitrary many channels).
00913     </DL>
00914 
00915     <b> Declarations:</b>
00916 
00917     pass arguments explicitly:
00918     \code
00919     namespace vigra {
00920         template <class SrcIterator, class SrcAccessor>
00921         void exportImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00922                          ImageExportInfo const & info)
00923     }
00924     \endcode
00925 
00926 
00927     use argument objects in conjunction with \ref ArgumentObjectFactories :
00928     \code
00929     namespace vigra {
00930         template <class SrcIterator, class SrcAccessor>
00931         void exportImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00932                          ImageExportInfo const & info)
00933     }
00934     \endcode
00935 
00936     <b> Usage:</b>
00937 
00938     <b>\#include</b> <<a href="impex_8hxx-source.html">vigra/impex.hxx</a>><br>
00939     Namespace: vigra
00940 
00941     \code
00942 
00943 
00944     vigra::BRGBImage out(w, h);
00945     ...
00946 
00947     // write as JPEG image, using compression quality 80
00948     vigra::exportImage(srcImageRange(out),
00949                       vigra::ImageExportInfo("myimage.jpg").setCompression("80"));
00950 
00951 
00952     // force it to a particular pixel type (the pixel type must be supported by the
00953     // desired image file format, otherwise an \ref vigra::PreconditionViolation exception will be thrown)
00954     vigra::exportImage(srcImageRange(out),
00955                       vigra::ImageExportInfo("myINT16image.tif").setPixelType("INT16"));
00956     \endcode
00957 
00958     <b> Preconditions:</b>
00959 
00960     <UL>
00961 
00962     <LI> the image file must be writable.
00963     <LI> the file type must be one of the supported file types.
00964 
00965 
00966     </UL>
00967 **/
00968 doxygen_overloaded_function(template <...> void exportImage)
00969 
00970     template < class SrcIterator, class SrcAccessor >
00971     void exportImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00972                       const ImageExportInfo & info )
00973     {
00974         typedef typename NumericTraits<typename SrcAccessor::value_type>::isScalar is_scalar;
00975 
00976         try
00977         {
00978             exportImage( sul, slr, sget, info, is_scalar() );
00979         }
00980         catch(Encoder::TIFFCompressionException &)
00981         {
00982             const_cast<ImageExportInfo &>(info).setCompression("");
00983             exportImage( sul, slr, sget, info, is_scalar() );
00984         }
00985     }
00986 
00987     template < class SrcIterator, class SrcAccessor >
00988     inline
00989     void exportImage( triple<SrcIterator, SrcIterator, SrcAccessor> src,
00990                       const ImageExportInfo & info )
00991     {
00992         exportImage( src.first, src.second, src.third, info );
00993     }
00994 
00995     template < class SrcIterator, class SrcAccessor >
00996     void exportImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00997                       const ImageExportInfo & info, VigraFalseType /*not scalar */)
00998     {
00999         typedef typename SrcAccessor::value_type AccessorValueType;
01000         typedef typename AccessorValueType::value_type SrcValueType;
01001         std::string pixeltype = info.getPixelType();
01002         std::auto_ptr<Encoder> enc = encoder(info);
01003         bool downcast = negotiatePixelType(enc->getFileType(),
01004                         TypeAsString<SrcValueType>::result(), pixeltype);
01005         enc->setPixelType(pixeltype);
01006         if(downcast || info.hasForcedRangeMapping())
01007         {
01008             if(pixeltype == "UINT8")
01009                 detail::exportVectorImage( sul, slr, sget, enc.get(), info, (UInt8)0);
01010             else if(pixeltype == "INT16")
01011                 detail::exportVectorImage( sul, slr, sget, enc.get(), info, Int16());
01012             else if(pixeltype == "UINT16")
01013                 detail::exportVectorImage( sul, slr, sget, enc.get(), info, (UInt16)0);
01014             else if(pixeltype == "INT32")
01015                 detail::exportVectorImage( sul, slr, sget, enc.get(), info, Int32());
01016             else if(pixeltype == "UINT32")
01017                 detail::exportVectorImage( sul, slr, sget, enc.get(), info, (UInt32)0);
01018             else if(pixeltype == "FLOAT")
01019                 detail::exportVectorImage( sul, slr, sget, enc.get(), info, float());
01020             else if(pixeltype == "DOUBLE")
01021                 detail::exportVectorImage( sul, slr, sget, enc.get(), info, double());
01022         }
01023         else
01024         {
01025             if(pixeltype == "UINT8")
01026                 detail::exportVectorImage( sul, slr, sget, enc.get(), (UInt8)0);
01027             else if(pixeltype == "INT16")
01028                 detail::exportVectorImage( sul, slr, sget, enc.get(), Int16());
01029             else if(pixeltype == "UINT16")
01030                 detail::exportVectorImage( sul, slr, sget, enc.get(), (UInt16)0);
01031             else if(pixeltype == "INT32")
01032                 detail::exportVectorImage( sul, slr, sget, enc.get(), Int32());
01033             else if(pixeltype == "UINT32")
01034                 detail::exportVectorImage( sul, slr, sget, enc.get(), (UInt32)0);
01035             else if(pixeltype == "FLOAT")
01036                 detail::exportVectorImage( sul, slr, sget, enc.get(), float());
01037             else if(pixeltype == "DOUBLE")
01038                 detail::exportVectorImage( sul, slr, sget, enc.get(), double());
01039         }
01040         enc->close();
01041     }
01042 
01043     template < class SrcIterator, class SrcAccessor >
01044     void exportImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
01045                       const ImageExportInfo & info, VigraTrueType /*scalar*/ )
01046     {
01047         typedef typename SrcAccessor::value_type SrcValueType;
01048         std::string pixeltype = info.getPixelType();
01049         std::auto_ptr<Encoder> enc = encoder(info);
01050         bool downcast = negotiatePixelType(enc->getFileType(),
01051                            TypeAsString<SrcValueType>::result(), pixeltype);
01052         enc->setPixelType(pixeltype);
01053         if(downcast || info.hasForcedRangeMapping())
01054         {
01055             if(pixeltype == "UINT8")
01056                 detail::exportScalarImage( sul, slr, sget, enc.get(), info, (UInt8)0);
01057             else if(pixeltype == "INT16")
01058                 detail::exportScalarImage( sul, slr, sget, enc.get(), info, Int16());
01059             else if(pixeltype == "UINT16")
01060                 detail::exportScalarImage( sul, slr, sget, enc.get(), info, (UInt16)0);
01061             else if(pixeltype == "INT32")
01062                 detail::exportScalarImage( sul, slr, sget, enc.get(), info, Int32());
01063             else if(pixeltype == "UINT32")
01064                 detail::exportScalarImage( sul, slr, sget, enc.get(), info, (UInt32)0);
01065             else if(pixeltype == "FLOAT")
01066                 detail::exportScalarImage( sul, slr, sget, enc.get(), info, float());
01067             else if(pixeltype == "DOUBLE")
01068                 detail::exportScalarImage( sul, slr, sget, enc.get(), info, double());
01069         }
01070         else
01071         {
01072             if(pixeltype == "UINT8")
01073                 detail::exportScalarImage( sul, slr, sget, enc.get(), (UInt8)0);
01074             else if(pixeltype == "INT16")
01075                 detail::exportScalarImage( sul, slr, sget, enc.get(), Int16());
01076             else if(pixeltype == "UINT16")
01077                 detail::exportScalarImage( sul, slr, sget, enc.get(), (UInt16)0);
01078             else if(pixeltype == "INT32")
01079                 detail::exportScalarImage( sul, slr, sget, enc.get(), Int32());
01080             else if(pixeltype == "UINT32")
01081                 detail::exportScalarImage( sul, slr, sget, enc.get(), (UInt32)0);
01082             else if(pixeltype == "FLOAT")
01083                 detail::exportScalarImage( sul, slr, sget, enc.get(), float());
01084             else if(pixeltype == "DOUBLE")
01085                 detail::exportScalarImage( sul, slr, sget, enc.get(), double());
01086         }
01087         enc->close();
01088     }
01089 
01090 //@}
01091 
01092 } // namespace vigra
01093 
01094 #endif /* VIGRA_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.7.1 (Mon Apr 16 2012)