[ 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         #if HAVE_UNIQUE_PTR
00298         std::unique_ptr<Decoder> dec = decoder(info);
00299         #else
00300         std::auto_ptr<Decoder> dec = decoder(info);
00301         #endif
00302         std::string pixeltype = dec->getPixelType();
00303 
00304         if ( pixeltype == "UINT8" )
00305             read_band( dec.get(), iter, a, (UInt8)0 );
00306         else if ( pixeltype == "INT16" )
00307             read_band( dec.get(), iter, a, Int16() );
00308         else if ( pixeltype == "UINT16" )
00309             read_band( dec.get(), iter, a, (UInt16)0 );
00310         else if ( pixeltype == "INT32" )
00311             read_band( dec.get(), iter, a, Int32() );
00312         else if ( pixeltype == "UINT32" )
00313             read_band( dec.get(), iter, a, (UInt32)0 );
00314         else if ( pixeltype == "FLOAT" )
00315             read_band( dec.get(), iter, a, float() );
00316         else if ( pixeltype == "DOUBLE" )
00317             read_band( dec.get(), iter, a, double() );
00318         else
00319             vigra_precondition( false, "invalid pixeltype" );
00320 
00321         // close the decoder
00322         dec->close();
00323     }
00324 
00325 /********************************************************/
00326 /*                                                      */
00327 /*                     importImage                      */
00328 /*                                                      */
00329 /********************************************************/
00330 
00331     /** \brief Read the image specified by the given \ref vigra::ImageImportInfo object.
00332 
00333         <b> Declarations:</b>
00334 
00335         pass arguments explicitly:
00336         \code
00337         namespace vigra {
00338             template <class ImageIterator, class Accessor>
00339             void
00340             importImage(ImageImportInfo const & image, ImageIterator iter, Accessor a)
00341         }
00342         \endcode
00343 
00344         use argument objects in conjunction with \ref ArgumentObjectFactories :
00345         \code
00346         namespace vigra {
00347             template <class ImageIterator, class Accessor>
00348             inline void
00349             importImage(ImageImportInfo const & image, pair<ImageIterator, Accessor> dest)
00350         }
00351         \endcode
00352 
00353         <b> Usage:</b>
00354 
00355         <b>\#include</b> <<a href="impex_8hxx-source.html">vigra/impex.hxx</a>><br>
00356         Namespace: vigra
00357 
00358         \code
00359 
00360         vigra::ImageImportInfo info("myimage.gif");
00361 
00362         if(info.isGrayscale())
00363         {
00364             // create byte image of appropriate size
00365             vigra::BImage in(info.width(), info.height());
00366 
00367             vigra::importImage(info, destImage(in)); // read the image
00368             ...
00369         }
00370         else
00371         {
00372             // create byte RGB image of appropriate size
00373             vigra::BRGBImage in(info.width(), info.height());
00374 
00375             vigra::importImage(info, destImage(in)); // read the image
00376             ...
00377         }
00378 
00379         \endcode
00380 
00381         <b> Preconditions:</b>
00382 
00383         <UL>
00384 
00385         <LI> the image file must be readable
00386         <LI> the file type must be one of
00387 
00388                 <DL>
00389                 <DT>"BMP"<DD> Microsoft Windows bitmap image file.
00390                 <DT>"GIF"<DD> CompuServe graphics interchange format; 8-bit color.
00391                 <DT>"JPEG"<DD> Joint Photographic Experts Group JFIF format; compressed 24-bit color. (only available if libjpeg is installed)
00392                 <DT>"PNG"<DD> Portable Network Graphic. (only available if libpng is installed)
00393                 <DT>"PBM"<DD> Portable bitmap format (black and white).
00394                 <DT>"PGM"<DD> Portable graymap format (gray scale).
00395                 <DT>"PNM"<DD> Portable anymap.
00396                 <DT>"PPM"<DD> Portable pixmap format (color).
00397                 <DT>"SUN"<DD> SUN Rasterfile.
00398                 <DT>"TIFF"<DD> Tagged Image File Format. (only available if libtiff is installed.)
00399                 <DT>"VIFF"<DD> Khoros Visualization image file.
00400                 </DL>
00401         </UL>
00402     **/
00403 doxygen_overloaded_function(template <...> void importImage)
00404 
00405     template < class ImageIterator, class Accessor >
00406     void importImage( const ImageImportInfo & info, ImageIterator iter, Accessor a )
00407     {
00408         typedef typename NumericTraits<typename Accessor::value_type>::isScalar is_scalar;
00409         importImage( info, iter, a, is_scalar() );
00410     }
00411 
00412     template < class ImageIterator, class Accessor >
00413     void importImage( const ImageImportInfo & info, pair< ImageIterator, Accessor > dest )
00414     {
00415         importImage( info, dest.first, dest.second );
00416     }
00417 
00418     template < class ImageIterator, class Accessor >
00419     void importImage( const ImageImportInfo & info, ImageIterator iter, Accessor a, VigraFalseType )
00420     {
00421         importVectorImage( info, iter, a );
00422     }
00423 
00424     template < class ImageIterator, class Accessor >
00425     void importImage( const ImageImportInfo & info, ImageIterator iter, Accessor a, VigraTrueType )
00426     {
00427         importScalarImage( info, iter, a );
00428     }
00429 
00430     /*!
00431       \brief used for writing bands after the source data type has been figured out.
00432 
00433         <b>\#include</b> <<a href="impex_8hxx-source.html">vigra/impex.hxx</a>><br>
00434         Namespace: vigra
00435 
00436         <b> Declaration:</b>
00437 
00438         \code
00439         namespace vigra {
00440             template< class ImageIterator, class Accessor, class DstValueType >
00441             void write_bands( Encoder * enc, ImageIterator ul, ImageIterator lr, Accessor a, DstValueType )
00442         }
00443         \endcode
00444 
00445       \param enc encoder object through which the destination data will be accessed
00446       \param ul  image iterator referencing the upper left pixel of the source image
00447       \param lr  image iterator referencing the lower right pixel of the source image
00448       \param a   image accessor for the source image
00449     */
00450     template< class ImageIterator, class Accessor, class DstValueType >
00451     void write_bands( Encoder * enc, ImageIterator ul, ImageIterator lr, Accessor a, DstValueType)
00452     {
00453         typedef unsigned int size_type;
00454         typedef typename ImageIterator::row_iterator SrcRowIterator;
00455         typedef typename Accessor::value_type  AccessorValueType;
00456         typedef typename AccessorValueType::value_type SrcValueType;
00457 
00458         // complete decoder settings
00459         const size_type width = lr.x - ul.x;
00460         const size_type height = lr.y - ul.y;
00461         enc->setWidth(width);
00462         enc->setHeight(height);
00463         const size_type num_bands = a.size(ul);
00464         enc->setNumBands(num_bands);
00465         enc->finalizeSettings();
00466 
00467         DstValueType * scanline;
00468 
00469         // iterate
00470         ImageIterator ys(ul);
00471         // MIHAL no default constructor available for cachedfileimages
00472         SrcRowIterator xs = ys.rowIterator();
00473 
00474             // Speedup for the common cases
00475         switch (num_bands) 
00476         {
00477           case 2:
00478           {
00479             unsigned int offset = enc->getOffset();
00480             DstValueType * scanline0;
00481             DstValueType * scanline1;
00482             for( size_type y = 0; y < height; ++y, ++ys.y ) {
00483                 xs = ys.rowIterator();
00484                 scanline0 = static_cast< DstValueType * >
00485                         (enc->currentScanlineOfBand(0));
00486                 scanline1 = static_cast< DstValueType * >
00487                         (enc->currentScanlineOfBand(1));
00488                 for( size_type x = 0; x < width; ++x, ++xs) {
00489                     *scanline0 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 0));
00490                     *scanline1 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 1));
00491                     scanline0 += offset;
00492                     scanline1 += offset;
00493                 }
00494                 enc->nextScanline();
00495                 
00496             }
00497             break;
00498           }
00499           case 3:
00500           {
00501             unsigned int offset = enc->getOffset();
00502             DstValueType * scanline0;
00503             DstValueType * scanline1;
00504             DstValueType * scanline2;
00505             for( size_type y = 0; y < height; ++y, ++ys.y ) {
00506                 xs = ys.rowIterator();
00507                 scanline0 = static_cast< DstValueType * >
00508                         (enc->currentScanlineOfBand(0));
00509                 scanline1 = static_cast< DstValueType * >
00510                         (enc->currentScanlineOfBand(1));
00511                 scanline2 = static_cast< DstValueType * >
00512                         (enc->currentScanlineOfBand(2));
00513                 for( size_type x = 0; x < width; ++x, ++xs) {
00514                     *scanline0 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 0));
00515                     *scanline1 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 1));
00516                     *scanline2 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 2));
00517                     scanline0 += offset;
00518                     scanline1 += offset;
00519                     scanline2 += offset;
00520                 }
00521                 enc->nextScanline();
00522             }
00523             break;
00524           }
00525           case 4:
00526           {
00527             unsigned int offset = enc->getOffset();
00528             DstValueType * scanline0;
00529             DstValueType * scanline1;
00530             DstValueType * scanline2;
00531             DstValueType * scanline3;
00532             for( size_type y = 0; y < height; ++y, ++ys.y ) {
00533                 xs = ys.rowIterator();
00534                 scanline0 = static_cast< DstValueType * >
00535                         (enc->currentScanlineOfBand(0));
00536                 scanline1 = static_cast< DstValueType * >
00537                         (enc->currentScanlineOfBand(1));
00538                 scanline2 = static_cast< DstValueType * >
00539                         (enc->currentScanlineOfBand(2));
00540                 scanline3 = static_cast< DstValueType * >
00541                         (enc->currentScanlineOfBand(3));
00542                 for( size_type x = 0; x < width; ++x, ++xs) {
00543                     *scanline0 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 0));
00544                     *scanline1 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 1));
00545                     *scanline2 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 2));
00546                     *scanline3 = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, 3));
00547                     scanline0 += offset;
00548                     scanline1 += offset;
00549                     scanline2 += offset;
00550                     scanline3 += offset;
00551                 }
00552                 enc->nextScanline();
00553             }
00554             break;
00555           }
00556           default:
00557           {
00558             // General case
00559             for( size_type y = 0; y < height; ++y, ++ys.y ) {
00560                 for( size_type b = 0; b < num_bands; ++b ) {
00561                     xs = ys.rowIterator();
00562                     scanline = static_cast< DstValueType * >
00563                         (enc->currentScanlineOfBand(b));
00564                     for( size_type x = 0; x < width; ++x, ++xs ) {
00565                         *scanline = detail::RequiresExplicitCast<DstValueType>::cast(a.getComponent( xs, b ));
00566                         scanline += enc->getOffset();
00567                     }
00568                 }
00569                 enc->nextScanline();
00570             }
00571           }
00572         }
00573     } // write_bands()
00574 
00575     template< class MArray, class DstValueType >
00576     void write_bands( Encoder * enc, MArray const & array, DstValueType)
00577     {
00578         typedef unsigned int size_type;
00579 
00580         // complete decoder settings
00581         const size_type width = array.shape(0);
00582         const size_type height = array.shape(1);
00583         enc->setWidth(width);
00584         enc->setHeight(height);
00585         const size_type num_bands = array.shape(2);
00586         enc->setNumBands(num_bands);
00587         enc->finalizeSettings();
00588 
00589         DstValueType * scanline;
00590 
00591         // iterate
00592         for( size_type y = 0; y < height; ++y ) {
00593             for( size_type b = 0; b < num_bands; ++b ) {
00594                 scanline = static_cast< DstValueType * >
00595                     (enc->currentScanlineOfBand(b));
00596                 for( size_type x = 0; x < width; ++x) {
00597                     *scanline = array(x, y, b);
00598                     scanline += enc->getOffset();
00599                 }
00600             }
00601             enc->nextScanline();
00602         }
00603     } // write_bands()
00604 
00605     /*!
00606       \brief used for writing bands after the source data type has been figured out.
00607 
00608         <b>\#include</b> <<a href="impex_8hxx-source.html">vigra/impex.hxx</a>><br>
00609         Namespace: vigra
00610 
00611         <b> Declaration:</b>
00612 
00613         \code
00614         namespace vigra {
00615             template< class ImageIterator, class Accessor, class DstValueType >
00616             void write_band( Encoder * enc, ImageIterator ul, ImageIterator lr, Accessor a, DstValueType )
00617         }
00618         \endcode
00619 
00620       \param enc encoder object through which the destination data will be accessed
00621       \param ul  image iterator referencing the upper left pixel of the source image
00622       \param lr  image iterator referencing the lower right pixel of the source image
00623       \param a   image accessor for the source image
00624     */
00625     template< class ImageIterator, class Accessor, class DstValueType >
00626     void write_band( Encoder * enc, ImageIterator ul, ImageIterator lr, Accessor a, DstValueType)
00627     {
00628         typedef unsigned int size_type;
00629         typedef typename ImageIterator::row_iterator SrcRowIterator;
00630         typedef typename Accessor::value_type SrcValueType;
00631 
00632         // complete decoder settings
00633         const size_type width = size_type(lr.x - ul.x);
00634         const size_type height = size_type(lr.y - ul.y);
00635         enc->setWidth(width);
00636         enc->setHeight(height);
00637         enc->setNumBands(1);
00638         enc->finalizeSettings();
00639 
00640         DstValueType * scanline;
00641 
00642         // iterate
00643         ImageIterator ys(ul);
00644         // MIHAL no default constructor available for cachedfileimages.
00645         SrcRowIterator xs = ys.rowIterator();
00646         size_type y;
00647         for(  y = 0; y < height; ++y, ++ys.y ) {
00648             xs = ys.rowIterator();
00649             scanline = static_cast< DstValueType * >(enc->currentScanlineOfBand(0));
00650             for( size_type x = 0; x < width; ++x, ++xs, ++scanline )
00651                 *scanline = detail::RequiresExplicitCast<DstValueType>::cast(a(xs));
00652             enc->nextScanline();
00653         }
00654     } // write_band()
00655 
00656 namespace detail {
00657 
00658     // export scalar images without conversion
00659     template < class SrcIterator, class SrcAccessor, class T >
00660     void exportScalarImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00661                            Encoder * enc, T zero)
00662     {
00663         write_band( enc, sul, slr, sget, zero );
00664     }
00665 
00666     // export scalar images with conversion 
00667     template < class SrcIterator, class SrcAccessor, class T >
00668     void exportScalarImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00669                            Encoder * enc, 
00670                            const ImageExportInfo & info, 
00671                            T zero)
00672     {
00673         double fromMin, fromMax, toMin, toMax;
00674         if(info.getFromMin() < info.getFromMax())
00675         {
00676             fromMin = info.getFromMin();
00677             fromMax = info.getFromMax();
00678         }
00679         else
00680         {
00681             typedef typename SrcAccessor::value_type SrcValue;
00682             FindMinMax<SrcValue> minmax;
00683             inspectImage( sul, slr, sget, minmax );
00684             
00685             fromMin = (double)minmax.min;
00686             fromMax = (double)minmax.max;
00687             if(fromMax <= fromMin)
00688                 fromMax = fromMin + 1.0;
00689        }
00690         
00691         if(info.getToMin() < info.getToMax())
00692         {
00693             toMin = info.getToMin();
00694             toMax = info.getToMax();
00695         }
00696         else
00697         {
00698             toMin = (double)NumericTraits<T>::min();
00699             toMax = (double)NumericTraits<T>::max();
00700         }
00701         
00702         double scale = (toMax - toMin) / (fromMax - fromMin);
00703         double offset = (toMin / scale) - fromMin;
00704         BasicImage<T> image(slr-sul);
00705         transformImage( sul, slr, sget, image.upperLeft(), image.accessor(), 
00706                         linearIntensityTransform(scale, offset));
00707         write_band( enc, image.upperLeft(),
00708                     image.lowerRight(), image.accessor(), zero );
00709     }
00710 
00711     // export vector images without conversion
00712     template < class SrcIterator, class SrcAccessor, class T >
00713     void exportVectorImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00714                            Encoder * enc, T zero)
00715     {
00716         int bands = sget.size(sul);
00717         vigra_precondition(isBandNumberSupported(enc->getFileType(), bands),
00718            "exportImage(): file format does not support requested number of bands (color channels)");
00719         write_bands( enc, sul, slr, sget, zero );
00720     }
00721     
00722     // export vector images with conversion
00723     template < class SrcIterator, class SrcAccessor, class T >
00724     void exportVectorImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00725                            Encoder * enc, 
00726                            const ImageExportInfo & info, 
00727                            T zero)
00728     {
00729         unsigned int bands = sget.size(sul);
00730         vigra_precondition(isBandNumberSupported(enc->getFileType(), bands),
00731            "exportImage(): file format does not support requested number of bands (color channels)");
00732 
00733         typedef typename SrcAccessor::ElementAccessor SrcElementAccessor;
00734         typedef typename SrcElementAccessor::value_type SrcComponent;
00735         double fromMin, fromMax, toMin, toMax;
00736         if(info.getFromMin() < info.getFromMax())
00737         {
00738             fromMin = info.getFromMin();
00739             fromMax = info.getFromMax();
00740         }
00741         else
00742         {
00743             FindMinMax<SrcComponent> minmax;
00744             for(unsigned int i=0; i<bands; ++i)
00745             {
00746                 SrcElementAccessor band(i, sget);
00747                 inspectImage( sul, slr, band, minmax );
00748             }
00749 
00750             fromMin = (double)minmax.min;
00751             fromMax = (double)minmax.max;
00752             if(fromMax <= fromMin)
00753                 fromMax = fromMin + 1.0;
00754         }
00755         
00756         if(info.getToMin() < info.getToMax())
00757         {
00758             toMin = info.getToMin();
00759             toMax = info.getToMax();
00760         }
00761         else
00762         {
00763             toMin = (double)NumericTraits<T>::min();
00764             toMax = (double)NumericTraits<T>::max();
00765         }
00766 
00767         double scale = (toMax - toMin) / (fromMax - fromMin);
00768         double offset = (toMin / scale) - fromMin;
00769         int w = slr.x - sul.x;
00770         int h = slr.y - sul.y;
00771 
00772         typedef vigra::MultiArray<3, T> MArray;
00773         MArray array(typename MArray::difference_type(w, h, bands));
00774 
00775         for(unsigned int i=0; i<bands; ++i)
00776         {
00777             BasicImageView<T> subImage = makeBasicImageView(array.bindOuter(i));
00778             SrcElementAccessor band(i, sget);
00779             transformImage( sul, slr, band, subImage.upperLeft(), subImage.accessor(),
00780                             linearIntensityTransform( scale, offset ) );
00781         }
00782         write_bands( enc, array, zero );
00783     }
00784 
00785 } // namespace detail
00786 
00787 
00788     /*!
00789       \brief Deprecated.
00790 
00791         Use \ref exportImage() instead.
00792 
00793         <b> Declaration:</b>
00794 
00795         \code
00796         namespace vigra {
00797             template < class SrcIterator, class SrcAccessor >
00798             void exportFloatingVectorImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00799                                             const ImageExportInfo & info )
00800         }
00801         \endcode
00802     */
00803 doxygen_overloaded_function(template <...> void exportFloatingVectorImage)
00804 
00805     template < class SrcIterator, class SrcAccessor >
00806     void exportFloatingVectorImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00807                                     const ImageExportInfo & info )
00808     {
00809         exportImage(sul, slr, sget, info);
00810     }
00811 
00812     /*!
00813       \brief Deprecated.
00814 
00815         Use \ref exportImage() instead.
00816 
00817         <b> Declaration:</b>
00818 
00819         \code
00820         namespace vigra {
00821             template < class SrcIterator, class SrcAccessor >
00822             void exportIntegralVectorImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00823                                             const ImageExportInfo & info )
00824         }
00825         \endcode
00826     */
00827 doxygen_overloaded_function(template <...> void exportIntegralVectorImage)
00828 
00829     template < class SrcIterator, class SrcAccessor >
00830     void exportIntegralVectorImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00831                                     const ImageExportInfo & info )
00832     {
00833         exportImage(sul, slr, sget, info);
00834     }
00835 
00836     /*!
00837       \brief Deprecated.
00838 
00839         Use \ref exportImage() instead.
00840 
00841         <b> Declaration:</b>
00842 
00843         \code
00844         namespace vigra {
00845             template < class SrcIterator, class SrcAccessor >
00846             void exportFloatingScalarImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00847                                             const ImageExportInfo & info )
00848         }
00849         \endcode
00850     */
00851 doxygen_overloaded_function(template <...> void exportFloatingScalarImage)
00852 
00853     template < class SrcIterator, class SrcAccessor >
00854     void exportFloatingScalarImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00855                                     const ImageExportInfo & info )
00856     {
00857         exportImage(sul, slr, sget, info);
00858     }
00859 
00860     /*!
00861       \brief Deprecated.
00862 
00863         Use \ref exportImage() instead.
00864 
00865         <b> Declaration:</b>
00866 
00867         \code
00868         namespace vigra {
00869             template < class SrcIterator, class SrcAccessor >
00870             void exportIntegralScalarImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00871                                             const ImageExportInfo & info )
00872         }
00873         \endcode
00874     */
00875 doxygen_overloaded_function(template <...> void exportIntegralScalarImage)
00876 
00877     template < class SrcIterator, class SrcAccessor >
00878     void exportIntegralScalarImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00879                                     const ImageExportInfo & info )
00880     {
00881         exportImage(sul, slr, sget, info);
00882     }
00883 
00884 /********************************************************/
00885 /*                                                      */
00886 /*                     exportImage                      */
00887 /*                                                      */
00888 /********************************************************/
00889 
00890 /** \brief Write an image, given an \ref vigra::ImageExportInfo object.
00891 
00892     If the file format to be exported to supports the pixel type of the
00893     source image, the pixel type will be kept (e.g. <tt>float</tt>
00894     can be stored as TIFF without conversion, in contrast to most other
00895     image export toolkits). Otherwise, the pixel values are transformed
00896     to the range 0.255 and converted to <tt>unsigned char</tt>. Currently,
00897     the following file formats are supported. The pixel types given in
00898     brackets are those that are written without conversion:
00899 
00900     <DL>
00901     <DT>"BMP"<DD> Microsoft Windows bitmap image file (pixel types: UINT8 as gray and RGB).
00902     <DT>"GIF"<DD> CompuServe graphics interchange format; 8-bit color (pixel types: UINT8 as gray and RGB).
00903     <DT>"JPEG"<DD> Joint Photographic Experts Group JFIF format; compressed 24-bit color
00904                   (pixel types: UINT8 as gray and RGB). (only available if libjpeg is installed)
00905     <DT>"PNG"<DD> Portable Network Graphic (pixel types: UINT8 and UINT16 with up to 4 channels).
00906                   (only available if libpng is installed)
00907     <DT>"PBM"<DD> Portable bitmap format (black and white).
00908     <DT>"PGM"<DD> Portable graymap format (pixel types: UINT8, INT16, INT32 as gray scale)).
00909     <DT>"PNM"<DD> Portable anymap (pixel types: UINT8, INT16, INT32 as gray and RGB).
00910     <DT>"PPM"<DD> Portable pixmap format (pixel types: UINT8, INT16, INT32 as RGB).
00911     <DT>"SUN"<DD> SUN Rasterfile (pixel types: UINT8 as gray and RGB).
00912     <DT>"TIFF"<DD> Tagged Image File Format
00913                 (pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with up to 4 channels).
00914                 (only available if libtiff is installed.)
00915     <DT>"VIFF"<DD> Khoros Visualization image file
00916         (pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with arbitrary many channels).
00917     </DL>
00918 
00919     <b> Declarations:</b>
00920 
00921     pass arguments explicitly:
00922     \code
00923     namespace vigra {
00924         template <class SrcIterator, class SrcAccessor>
00925         void exportImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00926                          ImageExportInfo const & info)
00927     }
00928     \endcode
00929 
00930 
00931     use argument objects in conjunction with \ref ArgumentObjectFactories :
00932     \code
00933     namespace vigra {
00934         template <class SrcIterator, class SrcAccessor>
00935         void exportImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00936                          ImageExportInfo const & info)
00937     }
00938     \endcode
00939 
00940     <b> Usage:</b>
00941 
00942     <b>\#include</b> <<a href="impex_8hxx-source.html">vigra/impex.hxx</a>><br>
00943     Namespace: vigra
00944 
00945     \code
00946 
00947 
00948     vigra::BRGBImage out(w, h);
00949     ...
00950 
00951     // write as JPEG image, using compression quality 80
00952     vigra::exportImage(srcImageRange(out),
00953                       vigra::ImageExportInfo("myimage.jpg").setCompression("80"));
00954 
00955 
00956     // force it to a particular pixel type (the pixel type must be supported by the
00957     // desired image file format, otherwise an \ref vigra::PreconditionViolation exception will be thrown)
00958     vigra::exportImage(srcImageRange(out),
00959                       vigra::ImageExportInfo("myINT16image.tif").setPixelType("INT16"));
00960     \endcode
00961 
00962     <b> Preconditions:</b>
00963 
00964     <UL>
00965 
00966     <LI> the image file must be writable.
00967     <LI> the file type must be one of the supported file types.
00968 
00969 
00970     </UL>
00971 **/
00972 doxygen_overloaded_function(template <...> void exportImage)
00973 
00974     template < class SrcIterator, class SrcAccessor >
00975     void exportImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
00976                       const ImageExportInfo & info )
00977     {
00978         typedef typename NumericTraits<typename SrcAccessor::value_type>::isScalar is_scalar;
00979 
00980         try
00981         {
00982             exportImage( sul, slr, sget, info, is_scalar() );
00983         }
00984         catch(Encoder::TIFFCompressionException &)
00985         {
00986             const_cast<ImageExportInfo &>(info).setCompression("");
00987             exportImage( sul, slr, sget, info, is_scalar() );
00988         }
00989     }
00990 
00991     template < class SrcIterator, class SrcAccessor >
00992     inline
00993     void exportImage( triple<SrcIterator, SrcIterator, SrcAccessor> src,
00994                       const ImageExportInfo & info )
00995     {
00996         exportImage( src.first, src.second, src.third, info );
00997     }
00998 
00999     template < class SrcIterator, class SrcAccessor >
01000     void exportImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
01001                       const ImageExportInfo & info, VigraFalseType /*not scalar */)
01002     {
01003         typedef typename SrcAccessor::value_type AccessorValueType;
01004         typedef typename AccessorValueType::value_type SrcValueType;
01005         std::string pixeltype = info.getPixelType();
01006         std::auto_ptr<Encoder> enc = encoder(info);
01007         bool downcast = negotiatePixelType(enc->getFileType(),
01008                         TypeAsString<SrcValueType>::result(), pixeltype);
01009         enc->setPixelType(pixeltype);
01010         if(downcast || info.hasForcedRangeMapping())
01011         {
01012             if(pixeltype == "UINT8")
01013                 detail::exportVectorImage( sul, slr, sget, enc.get(), info, (UInt8)0);
01014             else if(pixeltype == "INT16")
01015                 detail::exportVectorImage( sul, slr, sget, enc.get(), info, Int16());
01016             else if(pixeltype == "UINT16")
01017                 detail::exportVectorImage( sul, slr, sget, enc.get(), info, (UInt16)0);
01018             else if(pixeltype == "INT32")
01019                 detail::exportVectorImage( sul, slr, sget, enc.get(), info, Int32());
01020             else if(pixeltype == "UINT32")
01021                 detail::exportVectorImage( sul, slr, sget, enc.get(), info, (UInt32)0);
01022             else if(pixeltype == "FLOAT")
01023                 detail::exportVectorImage( sul, slr, sget, enc.get(), info, float());
01024             else if(pixeltype == "DOUBLE")
01025                 detail::exportVectorImage( sul, slr, sget, enc.get(), info, double());
01026         }
01027         else
01028         {
01029             if(pixeltype == "UINT8")
01030                 detail::exportVectorImage( sul, slr, sget, enc.get(), (UInt8)0);
01031             else if(pixeltype == "INT16")
01032                 detail::exportVectorImage( sul, slr, sget, enc.get(), Int16());
01033             else if(pixeltype == "UINT16")
01034                 detail::exportVectorImage( sul, slr, sget, enc.get(), (UInt16)0);
01035             else if(pixeltype == "INT32")
01036                 detail::exportVectorImage( sul, slr, sget, enc.get(), Int32());
01037             else if(pixeltype == "UINT32")
01038                 detail::exportVectorImage( sul, slr, sget, enc.get(), (UInt32)0);
01039             else if(pixeltype == "FLOAT")
01040                 detail::exportVectorImage( sul, slr, sget, enc.get(), float());
01041             else if(pixeltype == "DOUBLE")
01042                 detail::exportVectorImage( sul, slr, sget, enc.get(), double());
01043         }
01044         enc->close();
01045     }
01046 
01047     template < class SrcIterator, class SrcAccessor >
01048     void exportImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
01049                       const ImageExportInfo & info, VigraTrueType /*scalar*/ )
01050     {
01051         typedef typename SrcAccessor::value_type SrcValueType;
01052         std::string pixeltype = info.getPixelType();
01053         #ifdef HAVE_UNIQUE_PTR
01054         std::unique_ptr<Encoder> enc = encoder(info);
01055         #else
01056         std::auto_ptr<Encoder> enc = encoder(info);
01057         #endif
01058         bool downcast = negotiatePixelType(enc->getFileType(),
01059                            TypeAsString<SrcValueType>::result(), pixeltype);
01060         enc->setPixelType(pixeltype);
01061         if(downcast || info.hasForcedRangeMapping())
01062         {
01063             if(pixeltype == "UINT8")
01064                 detail::exportScalarImage( sul, slr, sget, enc.get(), info, (UInt8)0);
01065             else if(pixeltype == "INT16")
01066                 detail::exportScalarImage( sul, slr, sget, enc.get(), info, Int16());
01067             else if(pixeltype == "UINT16")
01068                 detail::exportScalarImage( sul, slr, sget, enc.get(), info, (UInt16)0);
01069             else if(pixeltype == "INT32")
01070                 detail::exportScalarImage( sul, slr, sget, enc.get(), info, Int32());
01071             else if(pixeltype == "UINT32")
01072                 detail::exportScalarImage( sul, slr, sget, enc.get(), info, (UInt32)0);
01073             else if(pixeltype == "FLOAT")
01074                 detail::exportScalarImage( sul, slr, sget, enc.get(), info, float());
01075             else if(pixeltype == "DOUBLE")
01076                 detail::exportScalarImage( sul, slr, sget, enc.get(), info, double());
01077         }
01078         else
01079         {
01080             if(pixeltype == "UINT8")
01081                 detail::exportScalarImage( sul, slr, sget, enc.get(), (UInt8)0);
01082             else if(pixeltype == "INT16")
01083                 detail::exportScalarImage( sul, slr, sget, enc.get(), Int16());
01084             else if(pixeltype == "UINT16")
01085                 detail::exportScalarImage( sul, slr, sget, enc.get(), (UInt16)0);
01086             else if(pixeltype == "INT32")
01087                 detail::exportScalarImage( sul, slr, sget, enc.get(), Int32());
01088             else if(pixeltype == "UINT32")
01089                 detail::exportScalarImage( sul, slr, sget, enc.get(), (UInt32)0);
01090             else if(pixeltype == "FLOAT")
01091                 detail::exportScalarImage( sul, slr, sget, enc.get(), float());
01092             else if(pixeltype == "DOUBLE")
01093                 detail::exportScalarImage( sul, slr, sget, enc.get(), double());
01094         }
01095         enc->close();
01096     }
01097 
01098 //@}
01099 
01100 } // namespace vigra
01101 
01102 #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.0 (Thu Aug 25 2011)