[ 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) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python vigra 1.9.0 (Tue Nov 6 2012)