[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]
vigra/impexalpha.hxx | ![]() |
00001 /************************************************************************/ 00002 /* */ 00003 /* Copyright 2012 Christoph Spiel */ 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 00036 #ifndef VIGRA_IMPEXALPHA_HXX 00037 #define VIGRA_IMPEXALPHA_HXX 00038 00039 #include <vector> 00040 00041 #include "imageinfo.hxx" 00042 #include "impex.hxx" 00043 #include "impexbase.hxx" 00044 00045 namespace vigra 00046 { 00047 /** \addtogroup VigraImpex 00048 * @{ 00049 */ 00050 namespace detail 00051 { 00052 template <class ValueType, 00053 class ImageIterator, class ImageAccessor, 00054 class AlphaIterator, class AlphaAccessor> 00055 void 00056 read_image_band_and_alpha(Decoder* decoder, 00057 ImageIterator image_iterator, ImageAccessor image_accessor, 00058 AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor) 00059 { 00060 typedef typename ImageIterator::row_iterator ImageRowIterator; 00061 typedef typename AlphaIterator::row_iterator AlphaRowIterator; 00062 00063 vigra_precondition(decoder->getNumExtraBands() == 1, 00064 "vigra::detail::read_image_band_and_alpha: expecting exactly one alpha band"); 00065 vigra_precondition(decoder->getNumBands() - decoder->getNumExtraBands() == 1, 00066 "vigra::detail::read_image_band_and_alpha: expecting exactly one image band"); 00067 00068 const unsigned width(decoder->getWidth()); 00069 const unsigned height(decoder->getHeight()); 00070 const unsigned offset(decoder->getOffset()); 00071 00072 for (unsigned y = 0U; y != height; ++y) 00073 { 00074 decoder->nextScanline(); 00075 00076 const ValueType* scanline0 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(0)); 00077 const ValueType* scanline1 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(1)); 00078 00079 ImageRowIterator is(image_iterator.rowIterator()); 00080 const ImageRowIterator is_end(is + width); 00081 AlphaRowIterator as(alpha_iterator.rowIterator()); 00082 00083 while (is != is_end) 00084 { 00085 image_accessor.set(*scanline0, is); 00086 scanline0 += offset; 00087 ++is; 00088 00089 alpha_accessor.set(*scanline1, as); 00090 scanline1 += offset; 00091 ++as; 00092 } 00093 00094 ++image_iterator.y; 00095 ++alpha_iterator.y; 00096 } 00097 } 00098 00099 00100 template <class ValueType, 00101 class ImageIterator, class ImageAccessor, 00102 class AlphaIterator, class AlphaAccessor> 00103 void 00104 read_image_bands_and_alpha(Decoder* decoder, 00105 ImageIterator image_iterator, ImageAccessor image_accessor, 00106 AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor) 00107 { 00108 typedef typename ImageIterator::row_iterator ImageRowIterator; 00109 typedef typename AlphaIterator::row_iterator AlphaRowIterator; 00110 00111 vigra_precondition(decoder->getNumExtraBands() == 1, 00112 "vigra::detail::read_image_bands_and_alpha: expecting exactly one alpha band"); 00113 vigra_precondition(decoder->getNumBands() - decoder->getNumExtraBands() == image_accessor.size(image_iterator), 00114 "vigra::detail::read_image_bands_and_alpha: number of channels and image accessor do not match"); 00115 00116 const unsigned width(decoder->getWidth()); 00117 const unsigned height(decoder->getHeight()); 00118 const unsigned offset(decoder->getOffset()); 00119 const unsigned accessor_size(image_accessor.size(image_iterator)); 00120 00121 // OPTIMIZATION: Specialization for the most common case 00122 // of an RGBA-image, i.e. three color channels plus one 00123 // alpha channel. 00124 if (accessor_size == 3U) 00125 { 00126 const ValueType* scanline_0; 00127 const ValueType* scanline_1; 00128 const ValueType* scanline_2; 00129 const ValueType* scanline_3; // alpha 00130 00131 for (unsigned y = 0U; y != height; ++y) 00132 { 00133 decoder->nextScanline(); 00134 00135 scanline_0 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(0)); 00136 scanline_1 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(1)); 00137 scanline_2 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(2)); 00138 scanline_3 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(3)); 00139 00140 ImageRowIterator is(image_iterator.rowIterator()); 00141 const ImageRowIterator is_end(is + width); 00142 AlphaRowIterator as(alpha_iterator.rowIterator()); 00143 00144 while (is != is_end) 00145 { 00146 image_accessor.setComponent(*scanline_0, is, 0); 00147 image_accessor.setComponent(*scanline_1, is, 1); 00148 image_accessor.setComponent(*scanline_2, is, 2); 00149 alpha_accessor.set(*scanline_3, as); 00150 scanline_0 += offset; 00151 scanline_1 += offset; 00152 scanline_2 += offset; 00153 scanline_3 += offset; 00154 00155 ++is; 00156 ++as; 00157 } 00158 00159 ++image_iterator.y; 00160 ++alpha_iterator.y; 00161 } 00162 } 00163 else 00164 { 00165 std::vector<const ValueType*> scanlines(accessor_size + 1U); 00166 00167 for (unsigned y = 0U; y != height; ++y) 00168 { 00169 decoder->nextScanline(); 00170 00171 for (unsigned i = 0U; i != accessor_size + 1U; ++i) 00172 { 00173 scanlines[i] = static_cast<const ValueType*>(decoder->currentScanlineOfBand(i)); 00174 } 00175 00176 ImageRowIterator is(image_iterator.rowIterator()); 00177 const ImageRowIterator is_end(is + width); 00178 AlphaRowIterator as(alpha_iterator.rowIterator()); 00179 00180 while (is != is_end) 00181 { 00182 for (unsigned i = 0U; i != accessor_size; ++i) 00183 { 00184 image_accessor.setComponent(*scanlines[i], is, static_cast<int>(i)); 00185 scanlines[i] += offset; 00186 } 00187 ++is; 00188 00189 alpha_accessor.set(*scanlines[accessor_size], as); 00190 scanlines[accessor_size] += offset; 00191 ++as; 00192 } 00193 00194 ++image_iterator.y; 00195 ++alpha_iterator.y; 00196 } 00197 } 00198 } 00199 00200 00201 template <class ImageIterator, class ImageAccessor, 00202 class AlphaIterator, class AlphaAccessor> 00203 void 00204 importImageAlpha(const ImageImportInfo& import_info, 00205 ImageIterator image_iterator, ImageAccessor image_accessor, 00206 AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor, 00207 /* isScalar? */ VigraTrueType) 00208 { 00209 VIGRA_UNIQUE_PTR<Decoder> decoder(vigra::decoder(import_info)); 00210 00211 switch (pixel_t_of_string(decoder->getPixelType())) 00212 { 00213 case UNSIGNED_INT_8: 00214 read_image_band_and_alpha<UInt8>(decoder.get(), 00215 image_iterator, image_accessor, 00216 alpha_iterator, alpha_accessor); 00217 break; 00218 case UNSIGNED_INT_16: 00219 read_image_band_and_alpha<UInt16>(decoder.get(), 00220 image_iterator, image_accessor, 00221 alpha_iterator, alpha_accessor); 00222 break; 00223 case UNSIGNED_INT_32: 00224 read_image_band_and_alpha<UInt32>(decoder.get(), 00225 image_iterator, image_accessor, 00226 alpha_iterator, alpha_accessor); 00227 break; 00228 case SIGNED_INT_16: 00229 read_image_band_and_alpha<Int16>(decoder.get(), 00230 image_iterator, image_accessor, 00231 alpha_iterator, alpha_accessor); 00232 break; 00233 case SIGNED_INT_32: 00234 read_image_band_and_alpha<Int32>(decoder.get(), 00235 image_iterator, image_accessor, 00236 alpha_iterator, alpha_accessor); 00237 break; 00238 case IEEE_FLOAT_32: 00239 read_image_band_and_alpha<float>(decoder.get(), 00240 image_iterator, image_accessor, 00241 alpha_iterator, alpha_accessor); 00242 break; 00243 case IEEE_FLOAT_64: 00244 read_image_band_and_alpha<double>(decoder.get(), 00245 image_iterator, image_accessor, 00246 alpha_iterator, alpha_accessor); 00247 break; 00248 default: 00249 vigra_fail("vigra::detail::importImageAlpha<scalar>: not reached"); 00250 } 00251 00252 decoder->close(); 00253 } 00254 00255 00256 template <class ImageIterator, class ImageAccessor, 00257 class AlphaIterator, class AlphaAccessor> 00258 void 00259 importImageAlpha(const ImageImportInfo& import_info, 00260 ImageIterator image_iterator, ImageAccessor image_accessor, 00261 AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor, 00262 /* isScalar? */ VigraFalseType) 00263 { 00264 VIGRA_UNIQUE_PTR<Decoder> decoder(vigra::decoder(import_info)); 00265 00266 switch (pixel_t_of_string(decoder->getPixelType())) 00267 { 00268 case UNSIGNED_INT_8: 00269 read_image_bands_and_alpha<UInt8>(decoder.get(), 00270 image_iterator, image_accessor, 00271 alpha_iterator, alpha_accessor); 00272 break; 00273 case UNSIGNED_INT_16: 00274 read_image_bands_and_alpha<UInt16>(decoder.get(), 00275 image_iterator, image_accessor, 00276 alpha_iterator, alpha_accessor); 00277 break; 00278 case UNSIGNED_INT_32: 00279 read_image_bands_and_alpha<UInt32>(decoder.get(), 00280 image_iterator, image_accessor, 00281 alpha_iterator, alpha_accessor); 00282 break; 00283 case SIGNED_INT_16: 00284 read_image_bands_and_alpha<Int16>(decoder.get(), 00285 image_iterator, image_accessor, 00286 alpha_iterator, alpha_accessor); 00287 break; 00288 case SIGNED_INT_32: 00289 read_image_bands_and_alpha<Int32>(decoder.get(), 00290 image_iterator, image_accessor, 00291 alpha_iterator, alpha_accessor); 00292 break; 00293 case IEEE_FLOAT_32: 00294 read_image_bands_and_alpha<float>(decoder.get(), 00295 image_iterator, image_accessor, 00296 alpha_iterator, alpha_accessor); 00297 break; 00298 case IEEE_FLOAT_64: 00299 read_image_bands_and_alpha<double>(decoder.get(), 00300 image_iterator, image_accessor, 00301 alpha_iterator, alpha_accessor); 00302 break; 00303 default: 00304 vigra_fail("vigra::detail::importImageAlpha<non-scalar>: not reached"); 00305 } 00306 00307 decoder->close(); 00308 } 00309 } // end namespace detail 00310 00311 00312 /*! 00313 * \brief Read the image specified by the given \ref 00314 * vigra::ImageImportInfo object including its alpha channel. 00315 * 00316 * <B>Declarations</B> 00317 * 00318 * Pass arguments explicitly: 00319 * \code 00320 * namespace vigra { 00321 * template <class ImageIterator, class ImageAccessor, 00322 * class AlphaIterator, class AlphaAccessor> 00323 * void 00324 * importImageAlpha(const ImageImportInfo& importInfo, 00325 * ImageIterator imageIterator, ImageAccessor imageAccessor, 00326 * AlphaIterator alphaIterator, AlphaAccessor alphaAccessor) 00327 * } 00328 * \endcode 00329 * 00330 * Use argument objects in conjunction with \ref ArgumentObjectFactories : 00331 * \code 00332 * namespace vigra { 00333 * template <class ImageIterator, class ImageAccessor, 00334 * class AlphaIterator, class AlphaAccessor> 00335 * void 00336 * importImageAlpha(const ImageImportInfo& importInfo, 00337 * const pair<ImageIterator, ImageAccessor>& image, 00338 * const pair<AlphaIterator, AlphaAccessor>& alpha) 00339 * } 00340 * \endcode 00341 * 00342 * <B>Usage</B> 00343 * 00344 * <B>\#include <vigra/impexalpha.hxx></B> 00345 * 00346 * Namespace: vigra 00347 * \code 00348 * typedef UInt8 value_t; 00349 * ImageImportInfo info("zorro.tif"); 00350 * 00351 * if (info.isGrayscale()) 00352 * { 00353 * BasicImage<value_t> alpha(info.size()); 00354 * BasicImage<value_t> image(info.size()); 00355 * 00356 * importImageAlpha(info, 00357 * image.upperLeft(), image.accessor(), 00358 * alpha.upperLeft(), alpha.accessor()); 00359 * ... 00360 * } 00361 * else 00362 * { 00363 * BasicImage<value_t> alpha(info.size()); 00364 * BasicImage<vigra::RGBValue<value_t> > image(info.size()); 00365 * 00366 * importImageAlpha(info, 00367 * image.upperLeft(), image.accessor(), 00368 * alpha.upperLeft(), alpha.accessor()); 00369 * ... 00370 * } 00371 * \endcode 00372 * 00373 * <B>Preconditions</B> 00374 * 00375 * - The same preconditions hold as for importImage(), however the 00376 * only image formats that support alpha channels are 00377 * + TIFF and 00378 * + PNG. 00379 * In particular, JPEG does <B>not</B> support alpha channels. 00380 * - The alpha channel always is scalar-valued, i.e. comprises a 00381 * single band. 00382 */ 00383 doxygen_overloaded_function(template <...> inline void importImageAlpha) 00384 00385 00386 template <class ImageIterator, class ImageAccessor, 00387 class AlphaIterator, class AlphaAccessor> 00388 inline void 00389 importImageAlpha(const ImageImportInfo& import_info, 00390 ImageIterator image_iterator, ImageAccessor image_accessor, 00391 AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor) 00392 { 00393 typedef typename ImageAccessor::value_type ImageValueType; 00394 typedef typename vigra::NumericTraits<ImageValueType>::isScalar is_scalar; 00395 00396 detail::importImageAlpha(import_info, 00397 image_iterator, image_accessor, 00398 alpha_iterator, alpha_accessor, 00399 is_scalar()); 00400 } 00401 00402 00403 template <class ImageIterator, class ImageAccessor, 00404 class AlphaIterator, class AlphaAccessor> 00405 inline void 00406 importImageAlpha(const ImageImportInfo& import_info, 00407 const vigra::pair<ImageIterator, ImageAccessor>& image, 00408 const vigra::pair<AlphaIterator, AlphaAccessor>& alpha) 00409 { 00410 importImageAlpha(import_info, 00411 image.first, image.second, 00412 alpha.first, alpha.second); 00413 } 00414 00415 00416 namespace detail 00417 { 00418 template<class ValueType, 00419 class ImageIterator, class ImageAccessor, class ImageScaler, 00420 class AlphaIterator, class AlphaAccessor, class AlphaScaler> 00421 void 00422 write_image_band_and_alpha(Encoder* encoder, 00423 ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor, 00424 const ImageScaler& image_scaler, 00425 AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor, 00426 const AlphaScaler& alpha_scaler) 00427 { 00428 typedef typename ImageIterator::row_iterator ImageRowIterator; 00429 typedef typename ImageAccessor::value_type ImageValueType; 00430 00431 typedef typename AlphaIterator::row_iterator AlphaRowIterator; 00432 typedef typename AlphaAccessor::value_type AlphaValueType; 00433 00434 typedef detail::RequiresExplicitCast<ValueType> explicit_cast; 00435 00436 vigra_precondition(image_lower_right.x >= image_upper_left.x, 00437 "vigra::detail::write_image_band_and_alpha: negative width"); 00438 vigra_precondition(image_lower_right.y >= image_upper_left.y, 00439 "vigra::detail::write_image_band_and_alpha: negative height"); 00440 00441 const unsigned width(static_cast<unsigned>(image_lower_right.x - image_upper_left.x)); 00442 const unsigned height(static_cast<unsigned>(image_lower_right.y - image_upper_left.y)); 00443 00444 encoder->setWidth(width); 00445 encoder->setHeight(height); 00446 encoder->setNumBands(1 + 1); 00447 encoder->finalizeSettings(); 00448 00449 const unsigned offset(encoder->getOffset()); // correct offset only _after_ finalizeSettings() 00450 00451 // IMPLEMENTATION NOTE: We avoid calling the default constructor 00452 // to allow classes ImageIterator and AlphaIterator that do not 00453 // define one. 00454 ImageIterator image_iterator(image_upper_left); 00455 AlphaIterator alpha_iterator(alpha_upper_left); 00456 00457 for (unsigned y = 0U; y != height; ++y) 00458 { 00459 ValueType* scanline0 = static_cast<ValueType*>(encoder->currentScanlineOfBand(0)); 00460 ValueType* scanline1 = static_cast<ValueType*>(encoder->currentScanlineOfBand(1)); 00461 00462 ImageRowIterator is(image_iterator.rowIterator()); 00463 const ImageRowIterator is_end(is + width); 00464 AlphaRowIterator as(alpha_iterator.rowIterator()); 00465 00466 while (is != is_end) 00467 { 00468 *scanline0 = explicit_cast::cast(image_scaler(image_accessor(is))); 00469 scanline0 += offset; 00470 ++is; 00471 00472 *scanline1 = explicit_cast::cast(alpha_scaler(alpha_accessor(as))); 00473 scanline1 += offset; 00474 ++as; 00475 } 00476 00477 encoder->nextScanline(); 00478 00479 ++image_iterator.y; 00480 ++alpha_iterator.y; 00481 } 00482 } 00483 00484 00485 template<class ValueType, 00486 class ImageIterator, class ImageAccessor, class ImageScaler, 00487 class AlphaIterator, class AlphaAccessor, class AlphaScaler> 00488 void 00489 write_image_bands_and_alpha(Encoder* encoder, 00490 ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor, 00491 const ImageScaler& image_scaler, 00492 AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor, 00493 const AlphaScaler& alpha_scaler) 00494 { 00495 typedef typename ImageIterator::row_iterator ImageRowIterator; 00496 typedef typename AlphaIterator::row_iterator AlphaRowIterator; 00497 typedef detail::RequiresExplicitCast<ValueType> explicit_cast; 00498 00499 vigra_precondition(image_lower_right.x >= image_upper_left.x, 00500 "vigra::detail::write_image_bands_and_alpha: negative width"); 00501 vigra_precondition(image_lower_right.y >= image_upper_left.y, 00502 "vigra::detail::write_image_bands_and_alpha: negative height"); 00503 00504 const unsigned width(static_cast<unsigned>(image_lower_right.x - image_upper_left.x)); 00505 const unsigned height(static_cast<unsigned>(image_lower_right.y - image_upper_left.y)); 00506 const unsigned accessor_size(image_accessor.size(image_upper_left)); 00507 00508 encoder->setWidth(width); 00509 encoder->setHeight(height); 00510 encoder->setNumBands(accessor_size + 1U); 00511 encoder->finalizeSettings(); 00512 00513 const unsigned offset(encoder->getOffset()); // correct offset only _after_ finalizeSettings() 00514 00515 // IMPLEMENTATION NOTE: We avoid calling the default constructor 00516 // to allow classes ImageIterator and AlphaIterator that do not 00517 // define one. 00518 ImageIterator image_iterator(image_upper_left); 00519 AlphaIterator alpha_iterator(alpha_upper_left); 00520 00521 // OPTIMIZATION: Specialization for the most common case 00522 // of an RGBA-image, i.e. three color channels plus one 00523 // alpha channel. 00524 if (accessor_size == 3U) 00525 { 00526 ValueType* scanline_0; 00527 ValueType* scanline_1; 00528 ValueType* scanline_2; 00529 ValueType* scanline_3; // alpha 00530 00531 for (unsigned y = 0U; y != height; ++y) 00532 { 00533 scanline_0 = static_cast<ValueType*>(encoder->currentScanlineOfBand(0)); 00534 scanline_1 = static_cast<ValueType*>(encoder->currentScanlineOfBand(1)); 00535 scanline_2 = static_cast<ValueType*>(encoder->currentScanlineOfBand(2)); 00536 scanline_3 = static_cast<ValueType*>(encoder->currentScanlineOfBand(3)); 00537 00538 ImageRowIterator is(image_iterator.rowIterator()); 00539 const ImageRowIterator is_end(is + width); 00540 AlphaRowIterator as(alpha_iterator.rowIterator()); 00541 00542 while (is != is_end) 00543 { 00544 *scanline_0 = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, 0))); 00545 *scanline_1 = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, 1))); 00546 *scanline_2 = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, 2))); 00547 *scanline_3 = explicit_cast::cast(alpha_scaler(alpha_accessor(as))); 00548 scanline_0 += offset; 00549 scanline_1 += offset; 00550 scanline_2 += offset; 00551 scanline_3 += offset; 00552 00553 ++is; 00554 ++as; 00555 } 00556 00557 encoder->nextScanline(); 00558 00559 ++image_iterator.y; 00560 ++alpha_iterator.y; 00561 } 00562 } 00563 else 00564 { 00565 std::vector<ValueType*> scanlines(accessor_size + 1U); 00566 00567 for (unsigned y = 0U; y != height; ++y) 00568 { 00569 for (unsigned i = 0U; i != accessor_size + 1U; ++i) 00570 { 00571 scanlines[i] = static_cast<ValueType*>(encoder->currentScanlineOfBand(i)); 00572 } 00573 00574 ImageRowIterator is(image_iterator.rowIterator()); 00575 const ImageRowIterator is_end(is + width); 00576 AlphaRowIterator as(alpha_iterator.rowIterator()); 00577 00578 while (is != is_end) 00579 { 00580 for (unsigned i = 0U; i != accessor_size; ++i) 00581 { 00582 *scanlines[i] = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, static_cast<int>(i)))); 00583 scanlines[i] += offset; 00584 } 00585 ++is; 00586 00587 *scanlines[accessor_size] = explicit_cast::cast(alpha_scaler(alpha_accessor(as))); 00588 scanlines[accessor_size] += offset; 00589 ++as; 00590 } 00591 00592 encoder->nextScanline(); 00593 00594 ++image_iterator.y; 00595 ++alpha_iterator.y; 00596 } 00597 } 00598 } 00599 00600 00601 template <class ImageIterator, class ImageAccessor, 00602 class AlphaIterator, class AlphaAccessor> 00603 void 00604 exportImageAlpha(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor, 00605 AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor, 00606 const ImageExportInfo& export_info, 00607 /* isScalar? */ VigraTrueType) 00608 { 00609 typedef typename ImageAccessor::value_type ImageValueType; 00610 00611 VIGRA_UNIQUE_PTR<Encoder> encoder(vigra::encoder(export_info)); 00612 00613 std::string pixel_type(export_info.getPixelType()); 00614 const bool downcast(negotiatePixelType(encoder->getFileType(), TypeAsString<ImageValueType>::result(), pixel_type)); 00615 const pixel_t type(pixel_t_of_string(pixel_type)); 00616 00617 encoder->setPixelType(pixel_type); 00618 00619 const range_t image_source_range(find_source_value_range(export_info, 00620 image_upper_left, image_lower_right, image_accessor)); 00621 const range_t alpha_source_range(find_source_value_range(export_info, 00622 alpha_upper_left, 00623 alpha_upper_left + (image_lower_right - image_upper_left), 00624 alpha_accessor)); 00625 const range_t destination_range(find_destination_value_range(export_info, type)); 00626 00627 if ((downcast || export_info.hasForcedRangeMapping()) && 00628 (image_source_range.first != destination_range.first || image_source_range.second != destination_range.second || 00629 alpha_source_range.first != destination_range.first || alpha_source_range.second != destination_range.second)) 00630 { 00631 const linear_transform image_rescaler(image_source_range, destination_range); 00632 const linear_transform alpha_rescaler(alpha_source_range, destination_range); 00633 00634 switch (type) 00635 { 00636 case UNSIGNED_INT_8: 00637 write_image_band_and_alpha<UInt8>(encoder.get(), 00638 image_upper_left, image_lower_right, image_accessor, image_rescaler, 00639 alpha_upper_left, alpha_accessor, alpha_rescaler); 00640 break; 00641 case UNSIGNED_INT_16: 00642 write_image_band_and_alpha<UInt16>(encoder.get(), 00643 image_upper_left, image_lower_right, image_accessor, image_rescaler, 00644 alpha_upper_left, alpha_accessor, alpha_rescaler); 00645 break; 00646 case UNSIGNED_INT_32: 00647 write_image_band_and_alpha<UInt32>(encoder.get(), 00648 image_upper_left, image_lower_right, image_accessor, image_rescaler, 00649 alpha_upper_left, alpha_accessor, alpha_rescaler); 00650 break; 00651 case SIGNED_INT_16: 00652 write_image_band_and_alpha<Int16>(encoder.get(), 00653 image_upper_left, image_lower_right, image_accessor, image_rescaler, 00654 alpha_upper_left, alpha_accessor, alpha_rescaler); 00655 break; 00656 case SIGNED_INT_32: 00657 write_image_band_and_alpha<Int32>(encoder.get(), 00658 image_upper_left, image_lower_right, image_accessor, image_rescaler, 00659 alpha_upper_left, alpha_accessor, alpha_rescaler); 00660 break; 00661 case IEEE_FLOAT_32: 00662 write_image_band_and_alpha<float>(encoder.get(), 00663 image_upper_left, image_lower_right, image_accessor, image_rescaler, 00664 alpha_upper_left, alpha_accessor, alpha_rescaler); 00665 break; 00666 case IEEE_FLOAT_64: 00667 write_image_band_and_alpha<double>(encoder.get(), 00668 image_upper_left, image_lower_right, image_accessor, image_rescaler, 00669 alpha_upper_left, alpha_accessor, alpha_rescaler); 00670 break; 00671 default: 00672 vigra_fail("vigra::detail::exportImageAlpha<scalar>: not reached"); 00673 } 00674 } 00675 else 00676 { 00677 switch (type) 00678 { 00679 case UNSIGNED_INT_8: 00680 write_image_band_and_alpha<UInt8>(encoder.get(), 00681 image_upper_left, image_lower_right, image_accessor, identity(), 00682 alpha_upper_left, alpha_accessor, identity()); 00683 break; 00684 case UNSIGNED_INT_16: 00685 write_image_band_and_alpha<UInt16>(encoder.get(), 00686 image_upper_left, image_lower_right, image_accessor, identity(), 00687 alpha_upper_left, alpha_accessor, identity()); 00688 break; 00689 case UNSIGNED_INT_32: 00690 write_image_band_and_alpha<UInt32>(encoder.get(), 00691 image_upper_left, image_lower_right, image_accessor, identity(), 00692 alpha_upper_left, alpha_accessor, identity()); 00693 break; 00694 case SIGNED_INT_16: 00695 write_image_band_and_alpha<Int16>(encoder.get(), 00696 image_upper_left, image_lower_right, image_accessor, identity(), 00697 alpha_upper_left, alpha_accessor, identity()); 00698 break; 00699 case SIGNED_INT_32: 00700 write_image_band_and_alpha<Int32>(encoder.get(), 00701 image_upper_left, image_lower_right, image_accessor, identity(), 00702 alpha_upper_left, alpha_accessor, identity()); 00703 break; 00704 case IEEE_FLOAT_32: 00705 write_image_band_and_alpha<float>(encoder.get(), 00706 image_upper_left, image_lower_right, image_accessor, identity(), 00707 alpha_upper_left, alpha_accessor, identity()); 00708 break; 00709 case IEEE_FLOAT_64: 00710 write_image_band_and_alpha<double>(encoder.get(), 00711 image_upper_left, image_lower_right, image_accessor, identity(), 00712 alpha_upper_left, alpha_accessor, identity()); 00713 break; 00714 default: 00715 vigra_fail("vigra::detail::exportImageAlpha<scalar>: not reached"); 00716 } 00717 } 00718 00719 encoder->close(); 00720 } 00721 00722 00723 template <class ImageIterator, class ImageAccessor, 00724 class AlphaIterator, class AlphaAccessor> 00725 void 00726 exportImageAlpha(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor, 00727 AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor, 00728 const ImageExportInfo& export_info, 00729 /* isScalar? */ VigraFalseType) 00730 { 00731 typedef typename ImageAccessor::value_type ImageBaseType; 00732 typedef typename ImageBaseType::value_type ImageValueType; 00733 00734 VIGRA_UNIQUE_PTR<Encoder> encoder(vigra::encoder(export_info)); 00735 00736 std::string pixel_type(export_info.getPixelType()); 00737 const bool downcast(negotiatePixelType(encoder->getFileType(), TypeAsString<ImageValueType>::result(), pixel_type)); 00738 const pixel_t type(pixel_t_of_string(pixel_type)); 00739 00740 encoder->setPixelType(pixel_type); 00741 00742 vigra_precondition(isBandNumberSupported(encoder->getFileType(), image_accessor.size(image_upper_left)), 00743 "exportImageAlpha(): file format does not support requested number of bands (color channels)"); 00744 00745 const range_t image_source_range(find_source_value_range(export_info, 00746 image_upper_left, image_lower_right, image_accessor)); 00747 const range_t alpha_source_range(find_source_value_range(export_info, 00748 alpha_upper_left, 00749 alpha_upper_left + (image_lower_right - image_upper_left), 00750 alpha_accessor)); 00751 const range_t destination_range(find_destination_value_range(export_info, pixel_t_of_string(pixel_type))); 00752 00753 if ((downcast || export_info.hasForcedRangeMapping()) && 00754 (image_source_range.first != destination_range.first || image_source_range.second != destination_range.second || 00755 alpha_source_range.first != destination_range.first || alpha_source_range.second != destination_range.second)) 00756 { 00757 const linear_transform image_rescaler(image_source_range, destination_range); 00758 const linear_transform alpha_rescaler(alpha_source_range, destination_range); 00759 00760 switch (type) 00761 { 00762 case UNSIGNED_INT_8: 00763 write_image_bands_and_alpha<UInt8>(encoder.get(), 00764 image_upper_left, image_lower_right, image_accessor, image_rescaler, 00765 alpha_upper_left, alpha_accessor, alpha_rescaler); 00766 break; 00767 case UNSIGNED_INT_16: 00768 write_image_bands_and_alpha<UInt16>(encoder.get(), 00769 image_upper_left, image_lower_right, image_accessor, image_rescaler, 00770 alpha_upper_left, alpha_accessor, alpha_rescaler); 00771 break; 00772 case UNSIGNED_INT_32: 00773 write_image_bands_and_alpha<UInt32>(encoder.get(), 00774 image_upper_left, image_lower_right, image_accessor, image_rescaler, 00775 alpha_upper_left, alpha_accessor, alpha_rescaler); 00776 break; 00777 case SIGNED_INT_16: 00778 write_image_bands_and_alpha<Int16>(encoder.get(), 00779 image_upper_left, image_lower_right, image_accessor, image_rescaler, 00780 alpha_upper_left, alpha_accessor, alpha_rescaler); 00781 break; 00782 case SIGNED_INT_32: 00783 write_image_bands_and_alpha<Int32>(encoder.get(), 00784 image_upper_left, image_lower_right, image_accessor, image_rescaler, 00785 alpha_upper_left, alpha_accessor, alpha_rescaler); 00786 break; 00787 case IEEE_FLOAT_32: 00788 write_image_bands_and_alpha<float>(encoder.get(), 00789 image_upper_left, image_lower_right, image_accessor, image_rescaler, 00790 alpha_upper_left, alpha_accessor, alpha_rescaler); 00791 break; 00792 case IEEE_FLOAT_64: 00793 write_image_bands_and_alpha<double>(encoder.get(), 00794 image_upper_left, image_lower_right, image_accessor, image_rescaler, 00795 alpha_upper_left, alpha_accessor, alpha_rescaler); 00796 break; 00797 default: 00798 vigra_fail("vigra::detail::exportImageAlpha<non-scalar>: not reached"); 00799 } 00800 } 00801 else 00802 { 00803 switch (type) 00804 { 00805 case UNSIGNED_INT_8: 00806 write_image_bands_and_alpha<UInt8>(encoder.get(), 00807 image_upper_left, image_lower_right, image_accessor, identity(), 00808 alpha_upper_left, alpha_accessor, identity()); 00809 break; 00810 case UNSIGNED_INT_16: 00811 write_image_bands_and_alpha<UInt16>(encoder.get(), 00812 image_upper_left, image_lower_right, image_accessor, identity(), 00813 alpha_upper_left, alpha_accessor, identity()); 00814 break; 00815 case UNSIGNED_INT_32: 00816 write_image_bands_and_alpha<UInt32>(encoder.get(), 00817 image_upper_left, image_lower_right, image_accessor, identity(), 00818 alpha_upper_left, alpha_accessor, identity()); 00819 break; 00820 case SIGNED_INT_16: 00821 write_image_bands_and_alpha<Int16>(encoder.get(), 00822 image_upper_left, image_lower_right, image_accessor, identity(), 00823 alpha_upper_left, alpha_accessor, identity()); 00824 break; 00825 case SIGNED_INT_32: 00826 write_image_bands_and_alpha<Int32>(encoder.get(), 00827 image_upper_left, image_lower_right, image_accessor, identity(), 00828 alpha_upper_left, alpha_accessor, identity()); 00829 break; 00830 case IEEE_FLOAT_32: 00831 write_image_bands_and_alpha<float>(encoder.get(), 00832 image_upper_left, image_lower_right, image_accessor, identity(), 00833 alpha_upper_left, alpha_accessor, identity()); 00834 break; 00835 case IEEE_FLOAT_64: 00836 write_image_bands_and_alpha<double>(encoder.get(), 00837 image_upper_left, image_lower_right, image_accessor, identity(), 00838 alpha_upper_left, alpha_accessor, identity()); 00839 break; 00840 default: 00841 vigra_fail("vigra::detail::exportImageAlpha<non-scalar>: not reached"); 00842 } 00843 } 00844 00845 encoder->close(); 00846 } 00847 } // end namespace detail 00848 00849 00850 /*! 00851 * \brief Write the image specified by the given \ref 00852 * vigra::ImageExportInfo object including an alpha channel. 00853 * 00854 * <B>Declarations</B> 00855 * 00856 * Pass arguments explicitly: 00857 * \code 00858 * namespace vigra { 00859 * template <class ImageIterator, class ImageAccessor, 00860 * class AlphaIterator, class AlphaAccessor> 00861 * void 00862 * exportImageAlpha(ImageIterator imageUpperLeft, ImageIterator imageLowerRight, ImageAccessor imageAccessor, 00863 * AlphaIterator alphaUpperLeft, AlphaAccessor alphaAccessor, 00864 * const ImageExportInfo& exportInfo) 00865 * } 00866 * \endcode 00867 * 00868 * Use argument objects in conjunction with \ref ArgumentObjectFactories : 00869 * \code 00870 * namespace vigra { 00871 * template <class ImageIterator, class ImageAccessor, 00872 * class AlphaIterator, class AlphaAccessor> 00873 * void 00874 * exportImageAlpha(const triple<ImageIterator, ImageIterator, ImageAccessor>& image, 00875 * const pair<AlphaIterator, AlphaAccessor>& alpha, 00876 * const ImageExportInfo& exportInfo) 00877 * } 00878 * \endcode 00879 * 00880 * <B>Usage</B> 00881 * 00882 * <B>\#include <vigra/impexalpha.hxx></B> 00883 * 00884 * Namespace: vigra 00885 * \code 00886 * typedef UInt8 value_t; 00887 * ImageExportInfo info("zorro.tif"); 00888 * 00889 * if (info.isGrayscale()) 00890 * { 00891 * BasicImage<value_t> alpha; 00892 * BasicImage<value_t> image; 00893 * 00894 * ... 00895 * 00896 * exportImageAlpha(image.upperLeft(), image.lowerRight(), image.accessor(), 00897 * alpha.upperLeft(), alpha.accessor(), 00898 * info); 00899 * } 00900 * else 00901 * { 00902 * BasicImage<value_t> alpha; 00903 * BasicImage<vigra::RGBValue<value_t> > image; 00904 * 00905 * ... 00906 * 00907 * exportImageAlpha(image.upperLeft(), image.lowerRight(), image.accessor(), 00908 * alpha.upperLeft(), alpha.accessor(), 00909 * info); 00910 * } 00911 * \endcode 00912 * 00913 * <B>Preconditions</B> 00914 * 00915 * - The same preconditions hold as for exportImage(), however the 00916 * only image formats that support alpha channels are 00917 * + TIFF and 00918 * + PNG. 00919 * In particular, JPEG does <B>not</B> support alpha channels. 00920 * - The alpha channel always is scalar-valued, i.e. comprises a 00921 * single band. 00922 */ 00923 doxygen_overloaded_function(template <...> inline void exportImageAlpha) 00924 00925 00926 template <class ImageIterator, class ImageAccessor, 00927 class AlphaIterator, class AlphaAccessor> 00928 inline void 00929 exportImageAlpha(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor, 00930 AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor, 00931 const ImageExportInfo& export_info) 00932 { 00933 typedef typename ImageAccessor::value_type ImageValueType; 00934 typedef typename vigra::NumericTraits<ImageValueType>::isScalar is_scalar; 00935 00936 try 00937 { 00938 detail::exportImageAlpha(image_upper_left, image_lower_right, image_accessor, 00939 alpha_upper_left, alpha_accessor, 00940 export_info, 00941 is_scalar()); 00942 } 00943 catch (Encoder::TIFFCompressionException&) 00944 { 00945 ImageExportInfo info(export_info); 00946 00947 info.setCompression(""); 00948 detail::exportImageAlpha(image_upper_left, image_lower_right, image_accessor, 00949 alpha_upper_left, alpha_accessor, 00950 info, 00951 is_scalar()); 00952 } 00953 } 00954 00955 00956 template <class ImageIterator, class ImageAccessor, 00957 class AlphaIterator, class AlphaAccessor> 00958 inline void 00959 exportImageAlpha(const vigra::triple<ImageIterator, ImageIterator, ImageAccessor>& image, 00960 const vigra::pair<AlphaIterator, AlphaAccessor>& alpha, 00961 const ImageExportInfo& export_info) 00962 { 00963 exportImageAlpha(image.first, image.second, image.third, 00964 alpha.first, alpha.second, 00965 export_info); 00966 } 00967 00968 /** @} */ 00969 00970 } // end namespace vigra 00971 00972 #endif // VIGRA_IMPEXALPHA_HXX
© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) |
html generated using doxygen and Python
|