impexalpha.hxx

Go to the documentation of this file.
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 VIGRAEXT_IMPEXALPHA_HXX
00037 #define VIGRAEXT_IMPEXALPHA_HXX
00038 
00039 // TM: changes to impexalpha.hxx for Hugin
00040 // * fixes an off by one error which prevents to write exr images with alpha channel (already fixed upstreams for 1.11 version)
00041 // * changed conversion of alpha channel to work with Hugins notification
00042 
00043 #include <vector>
00044 
00045 #include "vigra/imageinfo.hxx"
00046 #include "vigra/impex.hxx"
00047 #include "vigra/impexbase.hxx"
00048 #include "utils.h"
00049 
00050 namespace vigra
00051 {
00055     namespace detail
00056     {
00057         template <class ValueType,
00058         class ImageIterator, class ImageAccessor,
00059         class AlphaIterator, class AlphaAccessor, class AlphaScaler>
00060             void
00061             read_image_band_and_alpha(Decoder* decoder,
00062             ImageIterator image_iterator, ImageAccessor image_accessor,
00063             AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor,
00064             const AlphaScaler& alpha_scaler)
00065         {
00066             typedef typename ImageIterator::row_iterator ImageRowIterator;
00067             typedef typename AlphaIterator::row_iterator AlphaRowIterator;
00068 
00069             vigra_precondition(decoder->getNumExtraBands() == 1,
00070                 "vigra::detail::read_image_band_and_alpha: expecting exactly one alpha band");
00071             vigra_precondition(decoder->getNumBands() - decoder->getNumExtraBands() == 1,
00072                 "vigra::detail::read_image_band_and_alpha: expecting exactly one image band");
00073 
00074             const unsigned width(decoder->getWidth());
00075             const unsigned height(decoder->getHeight());
00076             const unsigned offset(decoder->getOffset());
00077 
00078             for (unsigned y = 0U; y != height; ++y)
00079             {
00080                 decoder->nextScanline();
00081 
00082                 const ValueType* scanline0 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(0));
00083                 const ValueType* scanline1 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(1));
00084 
00085                 ImageRowIterator is(image_iterator.rowIterator());
00086                 const ImageRowIterator is_end(is + width);
00087                 AlphaRowIterator as(alpha_iterator.rowIterator());
00088 
00089                 while (is != is_end)
00090                 {
00091                     image_accessor.set(*scanline0, is);
00092                     scanline0 += offset;
00093                     ++is;
00094 
00095                     alpha_accessor.set(alpha_scaler(*scanline1), as);
00096                     scanline1 += offset;
00097                     ++as;
00098                 }
00099 
00100                 ++image_iterator.y;
00101                 ++alpha_iterator.y;
00102             }
00103         }
00104 
00105 
00106         template <class ValueType,
00107         class ImageIterator, class ImageAccessor,
00108         class AlphaIterator, class AlphaAccessor, class AlphaScaler>
00109             void
00110             read_image_bands_and_alpha(Decoder* decoder,
00111             ImageIterator image_iterator, ImageAccessor image_accessor,
00112             AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor,
00113             const AlphaScaler& alpha_scaler)
00114         {
00115             typedef typename ImageIterator::row_iterator ImageRowIterator;
00116             typedef typename AlphaIterator::row_iterator AlphaRowIterator;
00117 
00118             vigra_precondition(decoder->getNumExtraBands() == 1,
00119                 "vigra::detail::read_image_bands_and_alpha: expecting exactly one alpha band");
00120             vigra_precondition(decoder->getNumBands() - decoder->getNumExtraBands() == image_accessor.size(image_iterator),
00121                 "vigra::detail::read_image_bands_and_alpha: number of channels and image accessor do not match");
00122 
00123             const unsigned width(decoder->getWidth());
00124             const unsigned height(decoder->getHeight());
00125             const unsigned offset(decoder->getOffset());
00126             const unsigned accessor_size(image_accessor.size(image_iterator));
00127 
00128             // OPTIMIZATION: Specialization for the most common case
00129             // of an RGBA-image, i.e. three color channels plus one
00130             // alpha channel.
00131             if (accessor_size == 3U)
00132             {
00133                 const ValueType* scanline_0;
00134                 const ValueType* scanline_1;
00135                 const ValueType* scanline_2;
00136                 const ValueType* scanline_3; // alpha
00137 
00138                 for (unsigned y = 0U; y != height; ++y)
00139                 {
00140                     decoder->nextScanline();
00141 
00142                     scanline_0 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(0));
00143                     scanline_1 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(1));
00144                     scanline_2 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(2));
00145                     scanline_3 = static_cast<const ValueType*>(decoder->currentScanlineOfBand(3));
00146 
00147                     ImageRowIterator is(image_iterator.rowIterator());
00148                     const ImageRowIterator is_end(is + width);
00149                     AlphaRowIterator as(alpha_iterator.rowIterator());
00150 
00151                     while (is != is_end)
00152                     {
00153                         image_accessor.setComponent(*scanline_0, is, 0);
00154                         image_accessor.setComponent(*scanline_1, is, 1);
00155                         image_accessor.setComponent(*scanline_2, is, 2);
00156                         alpha_accessor.set(alpha_scaler(*scanline_3), as);
00157                         scanline_0 += offset;
00158                         scanline_1 += offset;
00159                         scanline_2 += offset;
00160                         scanline_3 += offset;
00161 
00162                         ++is;
00163                         ++as;
00164                     }
00165 
00166                     ++image_iterator.y;
00167                     ++alpha_iterator.y;
00168                 }
00169             }
00170             else
00171             {
00172                 std::vector<const ValueType*> scanlines(accessor_size + 1U);
00173 
00174                 for (unsigned y = 0U; y != height; ++y)
00175                 {
00176                     decoder->nextScanline();
00177 
00178                     for (unsigned i = 0U; i != accessor_size + 1U; ++i)
00179                     {
00180                         scanlines[i] = static_cast<const ValueType*>(decoder->currentScanlineOfBand(i));
00181                     }
00182 
00183                     ImageRowIterator is(image_iterator.rowIterator());
00184                     const ImageRowIterator is_end(is + width);
00185                     AlphaRowIterator as(alpha_iterator.rowIterator());
00186 
00187                     while (is != is_end)
00188                     {
00189                         for (unsigned i = 0U; i != accessor_size; ++i)
00190                         {
00191                             image_accessor.setComponent(*scanlines[i], is, static_cast<int>(i));
00192                             scanlines[i] += offset;
00193                         }
00194                         ++is;
00195 
00196                         alpha_accessor.set(*scanlines[accessor_size], as);
00197                         scanlines[accessor_size] += offset;
00198                         ++as;
00199                     }
00200 
00201                     ++image_iterator.y;
00202                     ++alpha_iterator.y;
00203                 }
00204             }
00205         }
00206 
00207 
00208         template <class ImageIterator, class ImageAccessor,
00209         class AlphaIterator, class AlphaAccessor>
00210             void
00211             importImageAlpha(const ImageImportInfo& import_info,
00212             ImageIterator image_iterator, ImageAccessor image_accessor,
00213             AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor,
00214             /* isScalar? */ VigraTrueType)
00215         {
00216             typedef typename ImageAccessor::value_type ImageValueType;
00217             typedef typename AlphaAccessor::value_type AlphaValueType;
00218 
00219             VIGRA_UNIQUE_PTR<Decoder> decoder(vigra::decoder(import_info));
00220 
00221             const range_t alpha_source_range(vigra_ext::LUTTraits<ImageValueType>::min(), vigra_ext::LUTTraits<ImageValueType>::max());
00222             const range_t mask_destination_range(vigra_ext::LUTTraits<AlphaValueType>::min(), vigra_ext::LUTTraits<AlphaValueType>::max());
00223             if (alpha_source_range.first != mask_destination_range.first || alpha_source_range.second != mask_destination_range.second)
00224             {
00225                 // we need to scale the alpha channel
00226                 const linear_transform alpha_rescaler(alpha_source_range, mask_destination_range);
00227                 switch (pixel_t_of_string(decoder->getPixelType()))
00228                 {
00229                     case UNSIGNED_INT_8:
00230                         read_image_band_and_alpha<UInt8>(decoder.get(),
00231                             image_iterator, image_accessor,
00232                             alpha_iterator, alpha_accessor, alpha_rescaler);
00233                         break;
00234                     case UNSIGNED_INT_16:
00235                         read_image_band_and_alpha<UInt16>(decoder.get(),
00236                             image_iterator, image_accessor,
00237                             alpha_iterator, alpha_accessor, alpha_rescaler);
00238                         break;
00239                     case UNSIGNED_INT_32:
00240                         read_image_band_and_alpha<UInt32>(decoder.get(),
00241                             image_iterator, image_accessor,
00242                             alpha_iterator, alpha_accessor, alpha_rescaler);
00243                         break;
00244                     case SIGNED_INT_16:
00245                         read_image_band_and_alpha<Int16>(decoder.get(),
00246                             image_iterator, image_accessor,
00247                             alpha_iterator, alpha_accessor, alpha_rescaler);
00248                         break;
00249                     case SIGNED_INT_32:
00250                         read_image_band_and_alpha<Int32>(decoder.get(),
00251                             image_iterator, image_accessor,
00252                             alpha_iterator, alpha_accessor, alpha_rescaler);
00253                         break;
00254                     case IEEE_FLOAT_32:
00255                         read_image_band_and_alpha<float>(decoder.get(),
00256                             image_iterator, image_accessor,
00257                             alpha_iterator, alpha_accessor, alpha_rescaler);
00258                         break;
00259                     case IEEE_FLOAT_64:
00260                         read_image_band_and_alpha<double>(decoder.get(),
00261                             image_iterator, image_accessor,
00262                             alpha_iterator, alpha_accessor, alpha_rescaler);
00263                         break;
00264                     default:
00265                         vigra_fail("vigra::detail::importImageAlpha<scalar>: not reached");
00266                 }
00267             }
00268             else
00269             {
00270                 switch (pixel_t_of_string(decoder->getPixelType()))
00271                 {
00272                     case UNSIGNED_INT_8:
00273                         read_image_band_and_alpha<UInt8>(decoder.get(),
00274                             image_iterator, image_accessor,
00275                             alpha_iterator, alpha_accessor, identity());
00276                         break;
00277                     case UNSIGNED_INT_16:
00278                         read_image_band_and_alpha<UInt16>(decoder.get(),
00279                             image_iterator, image_accessor,
00280                             alpha_iterator, alpha_accessor, identity());
00281                         break;
00282                     case UNSIGNED_INT_32:
00283                         read_image_band_and_alpha<UInt32>(decoder.get(),
00284                             image_iterator, image_accessor,
00285                             alpha_iterator, alpha_accessor, identity());
00286                         break;
00287                     case SIGNED_INT_16:
00288                         read_image_band_and_alpha<Int16>(decoder.get(),
00289                             image_iterator, image_accessor,
00290                             alpha_iterator, alpha_accessor, identity());
00291                         break;
00292                     case SIGNED_INT_32:
00293                         read_image_band_and_alpha<Int32>(decoder.get(),
00294                             image_iterator, image_accessor,
00295                             alpha_iterator, alpha_accessor, identity());
00296                         break;
00297                     case IEEE_FLOAT_32:
00298                         read_image_band_and_alpha<float>(decoder.get(),
00299                             image_iterator, image_accessor,
00300                             alpha_iterator, alpha_accessor, identity());
00301                         break;
00302                     case IEEE_FLOAT_64:
00303                         read_image_band_and_alpha<double>(decoder.get(),
00304                             image_iterator, image_accessor,
00305                             alpha_iterator, alpha_accessor, identity());
00306                         break;
00307                     default:
00308                         vigra_fail("vigra::detail::importImageAlpha<scalar>: not reached");
00309                 }
00310             }
00311 
00312             decoder->close();
00313         }
00314 
00315 
00316         template <class ImageIterator, class ImageAccessor,
00317         class AlphaIterator, class AlphaAccessor>
00318             void
00319             importImageAlpha(const ImageImportInfo& import_info,
00320             ImageIterator image_iterator, ImageAccessor image_accessor,
00321             AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor,
00322             /* isScalar? */ VigraFalseType)
00323         {
00324             typedef typename ImageAccessor::value_type ImageValueType;
00325             typedef typename AlphaAccessor::value_type AlphaValueType;
00326 
00327             VIGRA_UNIQUE_PTR<Decoder> decoder(vigra::decoder(import_info));
00328 
00329             const range_t alpha_source_range(vigra_ext::LUTTraits<ImageValueType>::min(), vigra_ext::LUTTraits<ImageValueType>::max());
00330             const range_t mask_destination_range(vigra_ext::LUTTraits<AlphaValueType>::min(), vigra_ext::LUTTraits<AlphaValueType>::max());
00331             if (alpha_source_range.first != mask_destination_range.first || alpha_source_range.second != mask_destination_range.second)
00332             {
00333                 // we need to scale the alpha channel
00334                 const linear_transform alpha_rescaler(alpha_source_range, mask_destination_range);
00335                 switch (pixel_t_of_string(decoder->getPixelType()))
00336                 {
00337                     case UNSIGNED_INT_8:
00338                         read_image_bands_and_alpha<UInt8>(decoder.get(),
00339                             image_iterator, image_accessor,
00340                             alpha_iterator, alpha_accessor, alpha_rescaler);
00341                         break;
00342                     case UNSIGNED_INT_16:
00343                         read_image_bands_and_alpha<UInt16>(decoder.get(),
00344                             image_iterator, image_accessor,
00345                             alpha_iterator, alpha_accessor, alpha_rescaler);
00346                         break;
00347                     case UNSIGNED_INT_32:
00348                         read_image_bands_and_alpha<UInt32>(decoder.get(),
00349                             image_iterator, image_accessor,
00350                             alpha_iterator, alpha_accessor, alpha_rescaler);
00351                         break;
00352                     case SIGNED_INT_16:
00353                         read_image_bands_and_alpha<Int16>(decoder.get(),
00354                             image_iterator, image_accessor,
00355                             alpha_iterator, alpha_accessor, alpha_rescaler);
00356                         break;
00357                     case SIGNED_INT_32:
00358                         read_image_bands_and_alpha<Int32>(decoder.get(),
00359                             image_iterator, image_accessor,
00360                             alpha_iterator, alpha_accessor, alpha_rescaler);
00361                         break;
00362                     case IEEE_FLOAT_32:
00363                         read_image_bands_and_alpha<float>(decoder.get(),
00364                             image_iterator, image_accessor,
00365                             alpha_iterator, alpha_accessor, alpha_rescaler);
00366                         break;
00367                     case IEEE_FLOAT_64:
00368                         read_image_bands_and_alpha<double>(decoder.get(),
00369                             image_iterator, image_accessor,
00370                             alpha_iterator, alpha_accessor, alpha_rescaler);
00371                         break;
00372                     default:
00373                         vigra_fail("vigra::detail::importImageAlpha<scalar>: not reached");
00374                 }
00375             }
00376             else
00377             {
00378                 switch (pixel_t_of_string(decoder->getPixelType()))
00379                 {
00380                     case UNSIGNED_INT_8:
00381                         read_image_bands_and_alpha<UInt8>(decoder.get(),
00382                             image_iterator, image_accessor,
00383                             alpha_iterator, alpha_accessor, identity());
00384                         break;
00385                     case UNSIGNED_INT_16:
00386                         read_image_bands_and_alpha<UInt16>(decoder.get(),
00387                             image_iterator, image_accessor,
00388                             alpha_iterator, alpha_accessor, identity());
00389                         break;
00390                     case UNSIGNED_INT_32:
00391                         read_image_bands_and_alpha<UInt32>(decoder.get(),
00392                             image_iterator, image_accessor,
00393                             alpha_iterator, alpha_accessor, identity());
00394                         break;
00395                     case SIGNED_INT_16:
00396                         read_image_bands_and_alpha<Int16>(decoder.get(),
00397                             image_iterator, image_accessor,
00398                             alpha_iterator, alpha_accessor, identity());
00399                         break;
00400                     case SIGNED_INT_32:
00401                         read_image_bands_and_alpha<Int32>(decoder.get(),
00402                             image_iterator, image_accessor,
00403                             alpha_iterator, alpha_accessor, identity());
00404                         break;
00405                     case IEEE_FLOAT_32:
00406                         read_image_bands_and_alpha<float>(decoder.get(),
00407                             image_iterator, image_accessor,
00408                             alpha_iterator, alpha_accessor, identity());
00409                         break;
00410                     case IEEE_FLOAT_64:
00411                         read_image_bands_and_alpha<double>(decoder.get(),
00412                             image_iterator, image_accessor,
00413                             alpha_iterator, alpha_accessor, identity());
00414                         break;
00415                     default:
00416                         vigra_fail("vigra::detail::importImageAlpha<scalar>: not reached");
00417                 }
00418             }
00419 
00420             decoder->close();
00421         }
00422     } // end namespace detail
00423 
00424 
00536     doxygen_overloaded_function(template <...> void importImageAlpha)
00537 
00538 
00539         template <class ImageIterator, class ImageAccessor,
00540     class AlphaIterator, class AlphaAccessor>
00541         inline void
00542         importImageAlpha(const ImageImportInfo& import_info,
00543         ImageIterator image_iterator, ImageAccessor image_accessor,
00544         AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor)
00545     {
00546         typedef typename ImageAccessor::value_type ImageValueType;
00547         typedef typename vigra::NumericTraits<ImageValueType>::isScalar is_scalar;
00548 
00549         detail::importImageAlpha(import_info,
00550             image_iterator, image_accessor,
00551             alpha_iterator, alpha_accessor,
00552             is_scalar());
00553     }
00554 
00555 
00556     template <class ImageIterator, class ImageAccessor,
00557     class AlphaIterator, class AlphaAccessor>
00558         inline void
00559         importImageAlpha(ImageImportInfo const & import_info,
00560         pair<ImageIterator, ImageAccessor> image,
00561         pair<AlphaIterator, AlphaAccessor> alpha)
00562     {
00563         importImageAlpha(import_info,
00564             image.first, image.second,
00565             alpha.first, alpha.second);
00566     }
00567 
00568     namespace detail
00569     {
00570         template<class ValueType,
00571         class ImageIterator, class ImageAccessor, class ImageScaler,
00572         class AlphaIterator, class AlphaAccessor, class AlphaScaler>
00573             void
00574             write_image_band_and_alpha(Encoder* encoder,
00575             ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
00576             const ImageScaler& image_scaler,
00577             AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor,
00578             const AlphaScaler& alpha_scaler)
00579         {
00580             typedef typename ImageIterator::row_iterator ImageRowIterator;
00581             typedef typename AlphaIterator::row_iterator AlphaRowIterator;
00582 
00583             typedef detail::RequiresExplicitCast<ValueType> explicit_cast;
00584 
00585             vigra_precondition(image_lower_right.x >= image_upper_left.x,
00586                 "vigra::detail::write_image_band_and_alpha: negative width");
00587             vigra_precondition(image_lower_right.y >= image_upper_left.y,
00588                 "vigra::detail::write_image_band_and_alpha: negative height");
00589 
00590             const unsigned width(static_cast<unsigned>(image_lower_right.x - image_upper_left.x));
00591             const unsigned height(static_cast<unsigned>(image_lower_right.y - image_upper_left.y));
00592 
00593             encoder->setWidth(width);
00594             encoder->setHeight(height);
00595             encoder->setNumBands(1 + 1);
00596             encoder->finalizeSettings();
00597 
00598             const unsigned offset(encoder->getOffset()); // correct offset only _after_ finalizeSettings()
00599 
00600             // IMPLEMENTATION NOTE: We avoid calling the default constructor
00601             // to allow classes ImageIterator and AlphaIterator that do not
00602             // define one.
00603             ImageIterator image_iterator(image_upper_left);
00604             AlphaIterator alpha_iterator(alpha_upper_left);
00605 
00606             for (unsigned y = 0U; y != height; ++y)
00607             {
00608                 ValueType* scanline0 = static_cast<ValueType*>(encoder->currentScanlineOfBand(0));
00609                 ValueType* scanline1 = static_cast<ValueType*>(encoder->currentScanlineOfBand(1));
00610 
00611                 ImageRowIterator is(image_iterator.rowIterator());
00612                 const ImageRowIterator is_end(is + width);
00613                 AlphaRowIterator as(alpha_iterator.rowIterator());
00614 
00615                 while (is != is_end)
00616                 {
00617                     *scanline0 = explicit_cast::cast(image_scaler(image_accessor(is)));
00618                     scanline0 += offset;
00619                     ++is;
00620 
00621                     *scanline1 = explicit_cast::cast(alpha_scaler(alpha_accessor(as)));
00622                     scanline1 += offset;
00623                     ++as;
00624                 }
00625 
00626                 encoder->nextScanline();
00627 
00628                 ++image_iterator.y;
00629                 ++alpha_iterator.y;
00630             }
00631         }
00632 
00633 
00634         template<class ValueType,
00635         class ImageIterator, class ImageAccessor, class ImageScaler,
00636         class AlphaIterator, class AlphaAccessor, class AlphaScaler>
00637             void
00638             write_image_bands_and_alpha(Encoder* encoder,
00639             ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
00640             const ImageScaler& image_scaler,
00641             AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor,
00642             const AlphaScaler& alpha_scaler)
00643         {
00644             typedef typename ImageIterator::row_iterator ImageRowIterator;
00645             typedef typename AlphaIterator::row_iterator AlphaRowIterator;
00646             typedef detail::RequiresExplicitCast<ValueType> explicit_cast;
00647 
00648             vigra_precondition(image_lower_right.x >= image_upper_left.x,
00649                 "vigra::detail::write_image_bands_and_alpha: negative width");
00650             vigra_precondition(image_lower_right.y >= image_upper_left.y,
00651                 "vigra::detail::write_image_bands_and_alpha: negative height");
00652 
00653             const unsigned width(static_cast<unsigned>(image_lower_right.x - image_upper_left.x));
00654             const unsigned height(static_cast<unsigned>(image_lower_right.y - image_upper_left.y));
00655             const unsigned accessor_size(image_accessor.size(image_upper_left));
00656 
00657             encoder->setWidth(width);
00658             encoder->setHeight(height);
00659             encoder->setNumBands(accessor_size + 1U);
00660             encoder->finalizeSettings();
00661 
00662             const unsigned offset(encoder->getOffset()); // correct offset only _after_ finalizeSettings()
00663 
00664             // IMPLEMENTATION NOTE: We avoid calling the default constructor
00665             // to allow classes ImageIterator and AlphaIterator that do not
00666             // define one.
00667             ImageIterator image_iterator(image_upper_left);
00668             AlphaIterator alpha_iterator(alpha_upper_left);
00669 
00670             // OPTIMIZATION: Specialization for the most common case
00671             // of an RGBA-image, i.e. three color channels plus one
00672             // alpha channel.
00673             if (accessor_size == 3U)
00674             {
00675                 ValueType* scanline_0;
00676                 ValueType* scanline_1;
00677                 ValueType* scanline_2;
00678                 ValueType* scanline_3; // alpha
00679 
00680                 for (unsigned y = 0U; y != height; ++y)
00681                 {
00682                     scanline_0 = static_cast<ValueType*>(encoder->currentScanlineOfBand(0));
00683                     scanline_1 = static_cast<ValueType*>(encoder->currentScanlineOfBand(1));
00684                     scanline_2 = static_cast<ValueType*>(encoder->currentScanlineOfBand(2));
00685                     scanline_3 = static_cast<ValueType*>(encoder->currentScanlineOfBand(3));
00686 
00687                     ImageRowIterator is(image_iterator.rowIterator());
00688                     const ImageRowIterator is_end(is + width);
00689                     AlphaRowIterator as(alpha_iterator.rowIterator());
00690 
00691                     while (is != is_end)
00692                     {
00693                         *scanline_0 = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, 0)));
00694                         *scanline_1 = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, 1)));
00695                         *scanline_2 = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, 2)));
00696                         *scanline_3 = explicit_cast::cast(alpha_scaler(alpha_accessor(as)));
00697                         scanline_0 += offset;
00698                         scanline_1 += offset;
00699                         scanline_2 += offset;
00700                         scanline_3 += offset;
00701 
00702                         ++is;
00703                         ++as;
00704                     }
00705 
00706                     encoder->nextScanline();
00707 
00708                     ++image_iterator.y;
00709                     ++alpha_iterator.y;
00710                 }
00711             }
00712             else
00713             {
00714                 std::vector<ValueType*> scanlines(accessor_size + 1U);
00715 
00716                 for (unsigned y = 0U; y != height; ++y)
00717                 {
00718                     for (unsigned i = 0U; i != accessor_size + 1U; ++i)
00719                     {
00720                         scanlines[i] = static_cast<ValueType*>(encoder->currentScanlineOfBand(i));
00721                     }
00722 
00723                     ImageRowIterator is(image_iterator.rowIterator());
00724                     const ImageRowIterator is_end(is + width);
00725                     AlphaRowIterator as(alpha_iterator.rowIterator());
00726 
00727                     while (is != is_end)
00728                     {
00729                         for (unsigned i = 0U; i != accessor_size; ++i)
00730                         {
00731                             *scanlines[i] = explicit_cast::cast(image_scaler(image_accessor.getComponent(is, static_cast<int>(i))));
00732                             scanlines[i] += offset;
00733                         }
00734                         ++is;
00735 
00736                         *scanlines[accessor_size] = explicit_cast::cast(alpha_scaler(alpha_accessor(as)));
00737                         scanlines[accessor_size] += offset;
00738                         ++as;
00739                     }
00740 
00741                     encoder->nextScanline();
00742 
00743                     ++image_iterator.y;
00744                     ++alpha_iterator.y;
00745                 }
00746             }
00747         }
00748 
00749 
00750         template <class ImageIterator, class ImageAccessor,
00751         class AlphaIterator, class AlphaAccessor>
00752             void
00753             exportImageAlpha(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
00754             AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor,
00755             const ImageExportInfo& export_info,
00756             /* isScalar? */ VigraTrueType)
00757         {
00758             typedef typename AlphaAccessor::value_type AlphaValueType;
00759 
00760             VIGRA_UNIQUE_PTR<Encoder> encoder(vigra::encoder(export_info));
00761 
00762             const std::string pixel_type(export_info.getPixelType());
00763             const pixel_t type(pixel_t_of_string(pixel_type));
00764             // TM: no explicit downcast, when needed this should be done by specialed code
00765             // before calling exportImageAlpha
00766             encoder->setPixelType(pixel_type);
00767 
00768             const range_t alpha_source_range(vigra_ext::LUTTraits<AlphaValueType>::min(), vigra_ext::LUTTraits<AlphaValueType>::max());
00769             const range_t mask_destination_range(0.0f, vigra_ext::getMaxValForPixelType(pixel_type));
00770 
00771             // now check if alpha channel matches
00772             if (alpha_source_range.first != mask_destination_range.first || alpha_source_range.second != mask_destination_range.second)
00773             {
00774                 const linear_transform alpha_rescaler(alpha_source_range, mask_destination_range);
00775                 switch (type)
00776                 {
00777                     case UNSIGNED_INT_8:
00778                         write_image_band_and_alpha<UInt8>(encoder.get(),
00779                             image_upper_left, image_lower_right, image_accessor, identity(),
00780                             alpha_upper_left, alpha_accessor, alpha_rescaler);
00781                         break;
00782                     case UNSIGNED_INT_16:
00783                         write_image_band_and_alpha<UInt16>(encoder.get(),
00784                             image_upper_left, image_lower_right, image_accessor, identity(),
00785                             alpha_upper_left, alpha_accessor, alpha_rescaler);
00786                         break;
00787                     case UNSIGNED_INT_32:
00788                         write_image_band_and_alpha<UInt32>(encoder.get(),
00789                             image_upper_left, image_lower_right, image_accessor, identity(),
00790                             alpha_upper_left, alpha_accessor, alpha_rescaler);
00791                         break;
00792                     case SIGNED_INT_16:
00793                         write_image_band_and_alpha<Int16>(encoder.get(),
00794                             image_upper_left, image_lower_right, image_accessor, identity(),
00795                             alpha_upper_left, alpha_accessor, alpha_rescaler);
00796                         break;
00797                     case SIGNED_INT_32:
00798                         write_image_band_and_alpha<Int32>(encoder.get(),
00799                             image_upper_left, image_lower_right, image_accessor, identity(),
00800                             alpha_upper_left, alpha_accessor, alpha_rescaler);
00801                         break;
00802                     case IEEE_FLOAT_32:
00803                         write_image_band_and_alpha<float>(encoder.get(),
00804                             image_upper_left, image_lower_right, image_accessor, identity(),
00805                             alpha_upper_left, alpha_accessor, alpha_rescaler);
00806                         break;
00807                     case IEEE_FLOAT_64:
00808                         write_image_band_and_alpha<double>(encoder.get(),
00809                             image_upper_left, image_lower_right, image_accessor, identity(),
00810                             alpha_upper_left, alpha_accessor, alpha_rescaler);
00811                         break;
00812                     default:
00813                         vigra_fail("vigra::detail::exportImageAlpha<scalar>: not reached");
00814                 }
00815             }
00816             else
00817             {
00818                 switch (type)
00819                 {
00820                     case UNSIGNED_INT_8:
00821                         write_image_band_and_alpha<UInt8>(encoder.get(),
00822                             image_upper_left, image_lower_right, image_accessor, identity(),
00823                             alpha_upper_left, alpha_accessor, identity());
00824                         break;
00825                     case UNSIGNED_INT_16:
00826                         write_image_band_and_alpha<UInt16>(encoder.get(),
00827                             image_upper_left, image_lower_right, image_accessor, identity(),
00828                             alpha_upper_left, alpha_accessor, identity());
00829                         break;
00830                     case UNSIGNED_INT_32:
00831                         write_image_band_and_alpha<UInt32>(encoder.get(),
00832                             image_upper_left, image_lower_right, image_accessor, identity(),
00833                             alpha_upper_left, alpha_accessor, identity());
00834                         break;
00835                     case SIGNED_INT_16:
00836                         write_image_band_and_alpha<Int16>(encoder.get(),
00837                             image_upper_left, image_lower_right, image_accessor, identity(),
00838                             alpha_upper_left, alpha_accessor, identity());
00839                         break;
00840                     case SIGNED_INT_32:
00841                         write_image_band_and_alpha<Int32>(encoder.get(),
00842                             image_upper_left, image_lower_right, image_accessor, identity(),
00843                             alpha_upper_left, alpha_accessor, identity());
00844                         break;
00845                     case IEEE_FLOAT_32:
00846                         write_image_band_and_alpha<float>(encoder.get(),
00847                             image_upper_left, image_lower_right, image_accessor, identity(),
00848                             alpha_upper_left, alpha_accessor, identity());
00849                         break;
00850                     case IEEE_FLOAT_64:
00851                         write_image_band_and_alpha<double>(encoder.get(),
00852                             image_upper_left, image_lower_right, image_accessor, identity(),
00853                             alpha_upper_left, alpha_accessor, identity());
00854                         break;
00855                     default:
00856                         vigra_fail("vigra::detail::exportImageAlpha<scalar>: not reached");
00857                 }
00858             }
00859 
00860             encoder->close();
00861         }
00862 
00863 
00864         template <class ImageIterator, class ImageAccessor,
00865         class AlphaIterator, class AlphaAccessor>
00866             void
00867             exportImageAlpha(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
00868             AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor,
00869             const ImageExportInfo& export_info,
00870             /* isScalar? */ VigraFalseType)
00871         {
00872             typedef typename ImageAccessor::value_type ImageBaseType;
00873             typedef typename ImageBaseType::value_type ImageValueType;
00874             typedef typename AlphaAccessor::value_type AlphaValueType;
00875 
00876             VIGRA_UNIQUE_PTR<Encoder> encoder(vigra::encoder(export_info));
00877 
00878             const std::string pixel_type(export_info.getPixelType());
00879             const pixel_t type(pixel_t_of_string(pixel_type));
00880             encoder->setPixelType(pixel_type);
00881 
00882             vigra_precondition(isBandNumberSupported(encoder->getFileType(), image_accessor.size(image_upper_left) + 1U),
00883                 "exportImageAlpha(): file format does not support requested number of bands (color channels)");
00884 
00885             // TM: no explicit downcast, when needed this should be done by specialed code
00886             // before calling exportImageAlpha
00887             const range_t alpha_source_range(vigra_ext::LUTTraits<AlphaValueType>::min(), vigra_ext::LUTTraits<AlphaValueType>::max());
00888             const range_t mask_destination_range(0.0f, vigra_ext::getMaxValForPixelType(pixel_type));
00889 
00890             // check if alpha channel matches
00891             if (alpha_source_range.first != mask_destination_range.first || alpha_source_range.second != mask_destination_range.second)
00892             {
00893                 const linear_transform alpha_rescaler(alpha_source_range, mask_destination_range);
00894                 switch (type)
00895                 {
00896                     case UNSIGNED_INT_8:
00897                         write_image_bands_and_alpha<UInt8>(encoder.get(),
00898                             image_upper_left, image_lower_right, image_accessor, identity(),
00899                             alpha_upper_left, alpha_accessor, alpha_rescaler);
00900                         break;
00901                     case UNSIGNED_INT_16:
00902                         write_image_bands_and_alpha<UInt16>(encoder.get(),
00903                             image_upper_left, image_lower_right, image_accessor, identity(),
00904                             alpha_upper_left, alpha_accessor, alpha_rescaler);
00905                         break;
00906                     case UNSIGNED_INT_32:
00907                         write_image_bands_and_alpha<UInt32>(encoder.get(),
00908                             image_upper_left, image_lower_right, image_accessor, identity(),
00909                             alpha_upper_left, alpha_accessor, alpha_rescaler);
00910                         break;
00911                     case SIGNED_INT_16:
00912                         write_image_bands_and_alpha<Int16>(encoder.get(),
00913                             image_upper_left, image_lower_right, image_accessor, identity(),
00914                             alpha_upper_left, alpha_accessor, alpha_rescaler);
00915                         break;
00916                     case SIGNED_INT_32:
00917                         write_image_bands_and_alpha<Int32>(encoder.get(),
00918                             image_upper_left, image_lower_right, image_accessor, identity(),
00919                             alpha_upper_left, alpha_accessor, alpha_rescaler);
00920                         break;
00921                     case IEEE_FLOAT_32:
00922                         write_image_bands_and_alpha<float>(encoder.get(),
00923                             image_upper_left, image_lower_right, image_accessor, identity(),
00924                             alpha_upper_left, alpha_accessor, alpha_rescaler);
00925                         break;
00926                     case IEEE_FLOAT_64:
00927                         write_image_bands_and_alpha<double>(encoder.get(),
00928                             image_upper_left, image_lower_right, image_accessor, identity(),
00929                             alpha_upper_left, alpha_accessor, alpha_rescaler);
00930                         break;
00931                     default:
00932                         vigra_fail("vigra::detail::exportImageAlpha<scalar>: not reached");
00933                 }
00934             }
00935             else
00936             {
00937                 switch (type)
00938                 {
00939                     case UNSIGNED_INT_8:
00940                         write_image_bands_and_alpha<UInt8>(encoder.get(),
00941                             image_upper_left, image_lower_right, image_accessor, identity(),
00942                             alpha_upper_left, alpha_accessor, identity());
00943                         break;
00944                     case UNSIGNED_INT_16:
00945                         write_image_bands_and_alpha<UInt16>(encoder.get(),
00946                             image_upper_left, image_lower_right, image_accessor, identity(),
00947                             alpha_upper_left, alpha_accessor, identity());
00948                         break;
00949                     case UNSIGNED_INT_32:
00950                         write_image_bands_and_alpha<UInt32>(encoder.get(),
00951                             image_upper_left, image_lower_right, image_accessor, identity(),
00952                             alpha_upper_left, alpha_accessor, identity());
00953                         break;
00954                     case SIGNED_INT_16:
00955                         write_image_bands_and_alpha<Int16>(encoder.get(),
00956                             image_upper_left, image_lower_right, image_accessor, identity(),
00957                             alpha_upper_left, alpha_accessor, identity());
00958                         break;
00959                     case SIGNED_INT_32:
00960                         write_image_bands_and_alpha<Int32>(encoder.get(),
00961                             image_upper_left, image_lower_right, image_accessor, identity(),
00962                             alpha_upper_left, alpha_accessor, identity());
00963                         break;
00964                     case IEEE_FLOAT_32:
00965                         write_image_bands_and_alpha<float>(encoder.get(),
00966                             image_upper_left, image_lower_right, image_accessor, identity(),
00967                             alpha_upper_left, alpha_accessor, identity());
00968                         break;
00969                     case IEEE_FLOAT_64:
00970                         write_image_bands_and_alpha<double>(encoder.get(),
00971                             image_upper_left, image_lower_right, image_accessor, identity(),
00972                             alpha_upper_left, alpha_accessor, identity());
00973                         break;
00974                     default:
00975                         vigra_fail("vigra::detail::exportImageAlpha<non-scalar>: not reached");
00976                 }
00977             }
00978 
00979             encoder->close();
00980         }
00981     } // end namespace detail
00982 
00983 
01102     doxygen_overloaded_function(template <...> void exportImageAlpha)
01103 
01104 
01105         template <class ImageIterator, class ImageAccessor,
01106     class AlphaIterator, class AlphaAccessor>
01107         inline void
01108         exportImageAlpha(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor,
01109         AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor,
01110         const ImageExportInfo& export_info)
01111     {
01112         typedef typename ImageAccessor::value_type ImageValueType;
01113         typedef typename vigra::NumericTraits<ImageValueType>::isScalar is_scalar;
01114 
01115         try
01116         {
01117             detail::exportImageAlpha(image_upper_left, image_lower_right, image_accessor,
01118                 alpha_upper_left, alpha_accessor,
01119                 export_info,
01120                 is_scalar());
01121         }
01122         catch (Encoder::TIFFCompressionException&)
01123         {
01124             ImageExportInfo info(export_info);
01125 
01126             info.setCompression("");
01127             detail::exportImageAlpha(image_upper_left, image_lower_right, image_accessor,
01128                 alpha_upper_left, alpha_accessor,
01129                 info,
01130                 is_scalar());
01131         }
01132     }
01133 
01134 
01135     template <class ImageIterator, class ImageAccessor,
01136     class AlphaIterator, class AlphaAccessor>
01137         inline void
01138         exportImageAlpha(triple<ImageIterator, ImageIterator, ImageAccessor> image,
01139         pair<AlphaIterator, AlphaAccessor> alpha,
01140         ImageExportInfo const & export_info)
01141     {
01142         exportImageAlpha(image.first, image.second, image.third,
01143             alpha.first, alpha.second,
01144             export_info);
01145     }
01146 
01149 } // end namespace vigra
01150 
01151 #endif // VIGRAEXT_IMPEXALPHA_HXX

Generated on 1 Aug 2015 for Hugintrunk by  doxygen 1.4.7