[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]
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) |
html generated using doxygen and Python
|