[ 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 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) |
html generated using doxygen and Python
|