[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

vigra/impexalpha.hxx VIGRA

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)