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

vigra/resizeimage.hxx |

    00001 /************************************************************************/
    00002 /*                                                                      */
    00003 /*               Copyright 1998-2004 by Ullrich Koethe                  */
    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
    00037 #ifndef VIGRA_RESIZEIMAGE_HXX
    00038 #define VIGRA_RESIZEIMAGE_HXX
    00039
    00040 #include <vector>
    00041 #include "utilities.hxx"
    00042 #include "numerictraits.hxx"
    00043 #include "stdimage.hxx"
    00044 #include "recursiveconvolution.hxx"
    00045 #include "separableconvolution.hxx"
    00046 #include "resampling_convolution.hxx"
    00047 #include "splines.hxx"
    00048
    00049 namespace vigra {
    00050
    00051 /*****************************************************************/
    00052 /*                                                               */
    00053 /*                         CoscotFunction                        */
    00054 /*                                                               */
    00055 /*****************************************************************/
    00056
    00057 /*! The Coscot interpolation function.
    00058
    00059     Implements the Coscot interpolation function proposed by Maria Magnusson Seger
    00060     (maria@isy.liu.se) in the context of tomographic reconstruction. It provides a fast
    00061     transition between the pass- and stop-bands and minimal ripple outside the transition
    00062     region. Both properties are important for this application and can be tuned by the parameters
    00063     <i>m</i> and <i>h</i> (with defaults 3 and 0.5). The function is defined by
    00064
    00065     \f[ f_{m,h}(x) = \left\{ \begin{array}{ll}
    00066                                    \frac{1}{2m}\sin(\pi x)\cot(\pi x / (2 m))(h + (1-h)\cos(\pi x/m)) & |x| \leq m \\
    00067                                   0 & \mbox{otherwise}
    00068                         \end{array}\right.
    00069     \f]
    00070
    00071     It can be used as a functor, and as a kernel for
    00072     \ref resamplingConvolveImage() to create a differentiable interpolant
    00073     of an image.
    00074
    00075     <b>\#include</b> <<a href="resizeimage_8hxx-source.html">vigra/resizeimage.hxx</a>><br>
    00076     Namespace: vigra
    00077
    00078     \ingroup MathFunctions
    00079 */
    00080 template <class T>
    00081 class CoscotFunction
    00082 {
    00083   public:
    00084
    00085         /** the kernel's value type
    00086         */
    00087     typedef T            value_type;
    00088         /** the unary functor's argument type
    00089         */
    00090     typedef T            argument_type;
    00091         /** the splines polynomial order
    00092         */
    00093     typedef T            result_type;
    00094
    00095     CoscotFunction(unsigned int m = 3, double h = 0.5)
    00096     : m_(m),
    00097       h_(h)
    00098     {}
    00099
    00100         /** function (functor) call
    00101         */
    00102     result_type operator()(argument_type x) const
    00103     {
    00104         return x == 0.0 ?
    00105                     1.0
    00106                   : abs(x) < m_ ?
    00107                         VIGRA_CSTD::sin(M_PI*x) / VIGRA_CSTD::tan(M_PI * x / 2.0 / m_) *
    00108                              (h_ + (1.0 - h_) * VIGRA_CSTD::cos(M_PI * x / m_)) / 2.0 / m_
    00109                       : 0.0;
    00110     }
    00111
    00112         /** index operator -- same as operator()
    00113         */
    00114     value_type operator[](value_type x) const
    00115         { return operator()(x); }
    00116
    00117         /** Radius of the function's support.
    00118             Needed for  \ref resamplingConvolveImage(), equals m.
    00119         */
    00120     double radius() const
    00121         { return m_; }
    00122
    00123         /** Derivative order of the function: always 0.
    00124         */
    00125     unsigned int derivativeOrder() const
    00126         { return 0; }
    00127
    00128         /** Prefilter coefficients for compatibility with \ref vigra::BSpline.
    00129             (array has zero length, since prefiltering is not necessary).
    00130         */
    00131     ArrayVector<double> const & prefilterCoefficients() const
    00132     {
    00133         static ArrayVector<double> b;
    00134         return b;
    00135     }
    00136
    00137   protected:
    00138
    00139     unsigned int m_;
    00140     double h_;
    00141 };
    00142
    00143 /** \addtogroup GeometricTransformations Geometric Transformations
    00144     Zoom up and down by repeating pixels, or using various interpolation schemes.
    00145
    00146     See also: \ref resamplingConvolveImage(), \ref resampleImage(), \ref resizeMultiArraySplineInterpolation()
    00147
    00148     <b>\#include</b> <<a href="stdimagefunctions_8hxx-source.html">vigra/stdimagefunctions.hxx</a>><br>
    00149     <b>or</b><br>
    00150     <b>\#include</b> <<a href="resizeimage_8hxx-source.html">vigra/resizeimage.hxx</a>><br>
    00151 */
    00152 //@{
    00153
    00154 /********************************************************/
    00155 /*                                                      */
    00156 /*               resizeLineNoInterpolation              */
    00157 /*                                                      */
    00158 /********************************************************/
    00159
    00160 template <class SrcIterator, class SrcAccessor,
    00161           class DestIterator, class DestAccessor>
    00162 void
    00163 resizeLineNoInterpolation(SrcIterator i1, SrcIterator iend, SrcAccessor as,
    00164                            DestIterator id, DestIterator idend, DestAccessor ad)
    00165 {
    00166     int wold = iend - i1;
    00167     int wnew = idend - id;
    00168
    00169     if(wnew == 1)
    00170     {
    00171         ad.set(as(i1), id);
    00172         return;
    00173     }
    00174
    00175     double dx = (double)(wold - 1) / (wnew - 1);
    00176     double x = 0.5;
    00177     for(; id != idend; ++id, x += dx)
    00178     {
    00179         int ix = (int)x;
    00180         ad.set(as(i1, ix), id);
    00181     }
    00182 }
    00183
    00184 /********************************************************/
    00185 /*                                                      */
    00186 /*              resizeImageNoInterpolation              */
    00187 /*                                                      */
    00188 /********************************************************/
    00189
    00190 /** \brief Resize image by repeating the nearest pixel values.
    00191
    00192     This algorithm is very fast and does not require any arithmetic on
    00193     the pixel types.
    00194
    00195     The range of both the input and output images (resp. regions) must
    00196     be given. Both images must have a size of at least 2x2 pixels. The
    00197     scaling factors are then calculated accordingly. Destination
    00198     pixels are directly copied from the appropriate source pixels.
    00199
    00200     The function uses accessors.
    00201
    00202     <b> Declarations:</b>
    00203
    00204     pass arguments explicitly:
    00205     \code
    00206     namespace vigra {
    00207         template <class SrcImageIterator, class SrcAccessor,
    00208                   class DestImageIterator, class DestAccessor>
    00209         void
    00210         resizeImageNoInterpolation(
    00211               SrcImageIterator is, SrcImageIterator iend, SrcAccessor sa,
    00212               DestImageIterator id, DestImageIterator idend, DestAccessor da)
    00213     }
    00214     \endcode
    00215
    00216
    00217     use argument objects in conjunction with \ref ArgumentObjectFactories :
    00218     \code
    00219     namespace vigra {
    00220         template <class SrcImageIterator, class SrcAccessor,
    00221                   class DestImageIterator, class DestAccessor>
    00222         void
    00223         resizeImageNoInterpolation(
    00224               triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    00225               triple<DestImageIterator, DestImageIterator, DestAccessor> dest)
    00226     }
    00227     \endcode
    00228
    00229     <b> Usage:</b>
    00230
    00231         <b>\#include</b> <<a href="resizeimage_8hxx-source.html">vigra/resizeimage.hxx</a>><br>
    00232         Namespace: vigra
    00233
    00234     \code
    00235     vigra::resizeImageNoInterpolation(
    00236                src.upperLeft(), src.lowerRight(), src.accessor(),
    00237                dest.upperLeft(), dest.lowerRight(), dest.accessor());
    00238
    00239     \endcode
    00240
    00241     <b> Required Interface:</b>
    00242
    00243     \code
    00244     SrcImageIterator src_upperleft, src_lowerright;
    00245     DestImageIterator dest_upperleft, src_lowerright;
    00246
    00247     SrcAccessor src_accessor;
    00248     DestAccessor dest_accessor;
    00249
    00250     dest_accessor.set(src_accessor(src_upperleft), dest_upperleft);
    00251
    00252     \endcode
    00253
    00254     <b> Preconditions:</b>
    00255
    00256     \code
    00257     src_lowerright.x - src_upperleft.x > 1
    00258     src_lowerright.y - src_upperleft.y > 1
    00259     dest_lowerright.x - dest_upperleft.x > 1
    00260     dest_lowerright.y - dest_upperleft.y > 1
    00261     \endcode
    00262
    00263 */
    00264 doxygen_overloaded_function(template <...> void resizeImageNoInterpolation)
    00265
    00266 template <class SrcIterator, class SrcAccessor,
    00267           class DestIterator, class DestAccessor>
    00268 void
    00269 resizeImageNoInterpolation(SrcIterator is, SrcIterator iend, SrcAccessor sa,
    00270                       DestIterator id, DestIterator idend, DestAccessor da)
    00271 {
    00272     int w = iend.x - is.x;
    00273     int h = iend.y - is.y;
    00274
    00275     int wnew = idend.x - id.x;
    00276     int hnew = idend.y - id.y;
    00277
    00278     vigra_precondition((w > 1) && (h > 1),
    00279                  "resizeImageNoInterpolation(): "
    00280                  "Source image to small.\n");
    00281     vigra_precondition((wnew > 1) && (hnew > 1),
    00282                  "resizeImageNoInterpolation(): "
    00283                  "Destination image to small.\n");
    00284
    00285     typedef BasicImage<typename SrcAccessor::value_type> TmpImage;
    00286     typedef typename TmpImage::traverser TmpImageIterator;
    00287
    00288     TmpImage tmp(w, hnew);
    00289
    00290     TmpImageIterator yt = tmp.upperLeft();
    00291
    00292     for(int x=0; x<w; ++x, ++is.x, ++yt.x)
    00293     {
    00294         typename SrcIterator::column_iterator c1 = is.columnIterator();
    00295         typename TmpImageIterator::column_iterator ct = yt.columnIterator();
    00296
    00297         resizeLineNoInterpolation(c1, c1 + h, sa, ct, ct + hnew, tmp.accessor());
    00298     }
    00299
    00300     yt = tmp.upperLeft();
    00301
    00302     for(int y=0; y < hnew; ++y, ++yt.y, ++id.y)
    00303     {
    00304         typename DestIterator::row_iterator rd = id.rowIterator();
    00305         typename TmpImageIterator::row_iterator rt = yt.rowIterator();
    00306
    00307         resizeLineNoInterpolation(rt, rt + w, tmp.accessor(), rd, rd + wnew, da);
    00308     }
    00309 }
    00310
    00311 template <class SrcIterator, class SrcAccessor,
    00312           class DestIterator, class DestAccessor>
    00313 inline
    00314 void
    00315 resizeImageNoInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00316                            triple<DestIterator, DestIterator, DestAccessor> dest)
    00317 {
    00318     resizeImageNoInterpolation(src.first, src.second, src.third,
    00319                                    dest.first, dest.second, dest.third);
    00320 }
    00321
    00322 /********************************************************/
    00323 /*                                                      */
    00324 /*             resizeLineLinearInterpolation            */
    00325 /*                                                      */
    00326 /********************************************************/
    00327
    00328 template <class SrcIterator, class SrcAccessor,
    00329           class DestIterator, class DestAccessor>
    00330 void
    00331 resizeLineLinearInterpolation(SrcIterator i1, SrcIterator iend, SrcAccessor as,
    00332                            DestIterator id, DestIterator idend, DestAccessor ad)
    00333 {
    00334     int wold = iend - i1;
    00335     int wnew = idend - id;
    00336
    00337     if((wold <= 1) || (wnew <= 1)) return; // oder error ?
    00338
    00339     typedef
    00340         NumericTraits<typename DestAccessor::value_type> DestTraits;
    00341     typedef typename DestTraits::RealPromote RealPromote;
    00342
    00343     ad.set(DestTraits::fromRealPromote(as(i1)), id);
    00344     ++id;
    00345
    00346     --iend, --idend;
    00347     ad.set(DestTraits::fromRealPromote(as(iend)), idend);
    00348
    00349     double dx = (double)(wold - 1) / (wnew - 1);
    00350     double x = dx;
    00351
    00352     for(; id != idend; ++id, x += dx)
    00353     {
    00354         if(x >= 1.0)
    00355         {
    00356             int xx = (int)x;
    00357             i1 += xx;
    00358             x -= (double)xx;
    00359         }
    00360         double x1 = 1.0 - x;
    00361
    00362         ad.set(DestTraits::fromRealPromote(RealPromote(x1 * as(i1) + x * as(i1, 1))), id);
    00363     }
    00364 }
    00365
    00366 /********************************************************/
    00367 /*                                                      */
    00368 /*           resizeImageLinearInterpolation             */
    00369 /*                                                      */
    00370 /********************************************************/
    00371
    00372 /** \brief Resize image using linear interpolation.
    00373
    00374     The function uses the standard separable bilinear interpolation algorithm to
    00375     obtain a good compromize between quality and speed.
    00376
    00377     The range must of both the input and output images (resp. regions)
    00378     must be given. Both images must have a size of at
    00379     least 2x2. The scaling factors are then calculated
    00380     accordingly. If the source image is larger than the destination, it
    00381     is smoothed (band limited) using a recursive
    00382     exponential filter. The source value_type (SrcAccessor::value_type) must
    00383     be a linear space, i.e. it must support addition, multiplication
    00384     with a scalar real number and \ref NumericTraits "NumericTraits".
    00385     The function uses accessors.
    00386
    00387     <b> Declarations:</b>
    00388
    00389     pass arguments explicitly:
    00390     \code
    00391     namespace vigra {
    00392         template <class SrcImageIterator, class SrcAccessor,
    00393                   class DestImageIterator, class DestAccessor>
    00394         void
    00395         resizeImageLinearInterpolation(
    00396               SrcImageIterator is, SrcImageIterator iend, SrcAccessor sa,
    00397               DestImageIterator id, DestImageIterator idend, DestAccessor da)
    00398     }
    00399     \endcode
    00400
    00401
    00402     use argument objects in conjunction with \ref ArgumentObjectFactories :
    00403     \code
    00404     namespace vigra {
    00405         template <class SrcImageIterator, class SrcAccessor,
    00406                   class DestImageIterator, class DestAccessor>
    00407         void
    00408         resizeImageLinearInterpolation(
    00409               triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    00410               triple<DestImageIterator, DestImageIterator, DestAccessor> dest)
    00411     }
    00412     \endcode
    00413
    00414     <b> Usage:</b>
    00415
    00416         <b>\#include</b> <<a href="resizeimage_8hxx-source.html">vigra/resizeimage.hxx</a>><br>
    00417         Namespace: vigra
    00418
    00419     \code
    00420     vigra::resizeImageLinearInterpolation(
    00421                src.upperLeft(), src.lowerRight(), src.accessor(),
    00422                dest.upperLeft(), dest.lowerRight(), dest.accessor());
    00423
    00424     \endcode
    00425
    00426     <b> Required Interface:</b>
    00427
    00428     \code
    00429     SrcImageIterator src_upperleft, src_lowerright;
    00430     DestImageIterator dest_upperleft, src_lowerright;
    00431
    00432     SrcAccessor src_accessor;
    00433     DestAccessor dest_accessor;
    00434
    00435     NumericTraits<SrcAccessor::value_type>::RealPromote
    00436                              u = src_accessor(src_upperleft),
    00437                  v = src_accessor(src_upperleft, 1);
    00438     double d;
    00439
    00440     u = d * v;
    00441     u = u + v;
    00442
    00443     dest_accessor.set(
    00444         NumericTraits<DestAccessor::value_type>::fromRealPromote(u),
    00445     dest_upperleft);
    00446
    00447     \endcode
    00448
    00449     <b> Preconditions:</b>
    00450
    00451     \code
    00452     src_lowerright.x - src_upperleft.x > 1
    00453     src_lowerright.y - src_upperleft.y > 1
    00454     dest_lowerright.x - dest_upperleft.x > 1
    00455     dest_lowerright.y - dest_upperleft.y > 1
    00456     \endcode
    00457
    00458 */
    00459 doxygen_overloaded_function(template <...> void resizeImageLinearInterpolation)
    00460
    00461 template <class SrcIterator, class SrcAccessor,
    00462           class DestIterator, class DestAccessor>
    00463 void
    00464 resizeImageLinearInterpolation(SrcIterator is, SrcIterator iend, SrcAccessor sa,
    00465                       DestIterator id, DestIterator idend, DestAccessor da)
    00466 {
    00467     int w = iend.x - is.x;
    00468     int h = iend.y - is.y;
    00469
    00470     int wnew = idend.x - id.x;
    00471     int hnew = idend.y - id.y;
    00472
    00473     vigra_precondition((w > 1) && (h > 1),
    00474                  "resizeImageLinearInterpolation(): "
    00475                  "Source image to small.\n");
    00476     vigra_precondition((wnew > 1) && (hnew > 1),
    00477                  "resizeImageLinearInterpolation(): "
    00478                  "Destination image to small.\n");
    00479
    00480     double const scale = 2.0;
    00481
    00482     typedef typename SrcAccessor::value_type SRCVT;
    00483     typedef typename NumericTraits<SRCVT>::RealPromote TMPTYPE;
    00484     typedef BasicImage<TMPTYPE> TmpImage;
    00485     typedef typename TmpImage::traverser TmpImageIterator;
    00486
    00487     BasicImage<TMPTYPE> tmp(w, hnew);
    00488     BasicImage<TMPTYPE> line((h > w) ? h : w, 1);
    00489
    00490     int x,y;
    00491
    00492     typename BasicImage<TMPTYPE>::Iterator yt = tmp.upperLeft();
    00493     typename TmpImageIterator::row_iterator lt = line.upperLeft().rowIterator();
    00494
    00495     for(x=0; x<w; ++x, ++is.x, ++yt.x)
    00496     {
    00497         typename SrcIterator::column_iterator c1 = is.columnIterator();
    00498         typename TmpImageIterator::column_iterator ct = yt.columnIterator();
    00499
    00500         if(hnew < h)
    00501         {
    00502             recursiveSmoothLine(c1, c1 + h, sa,
    00503                  lt, line.accessor(), (double)h/hnew/scale);
    00504
    00505             resizeLineLinearInterpolation(lt, lt + h, line.accessor(),
    00506                                           ct, ct + hnew, tmp.accessor());
    00507         }
    00508         else
    00509         {
    00510             resizeLineLinearInterpolation(c1, c1 + h, sa,
    00511                                           ct, ct + hnew, tmp.accessor());
    00512         }
    00513     }
    00514
    00515     yt = tmp.upperLeft();
    00516
    00517     for(y=0; y < hnew; ++y, ++yt.y, ++id.y)
    00518     {
    00519         typename DestIterator::row_iterator rd = id.rowIterator();
    00520         typename TmpImageIterator::row_iterator rt = yt.rowIterator();
    00521
    00522         if(wnew < w)
    00523         {
    00524             recursiveSmoothLine(rt, rt + w, tmp.accessor(),
    00525                               lt, line.accessor(), (double)w/wnew/scale);
    00526
    00527             resizeLineLinearInterpolation(lt, lt + w, line.accessor(),
    00528                                           rd, rd + wnew, da);
    00529         }
    00530         else
    00531         {
    00532             resizeLineLinearInterpolation(rt, rt + w, tmp.accessor(),
    00533                                           rd, rd + wnew, da);
    00534         }
    00535     }
    00536 }
    00537
    00538 template <class SrcIterator, class SrcAccessor,
    00539           class DestIterator, class DestAccessor>
    00540 inline
    00541 void
    00542 resizeImageLinearInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00543                                triple<DestIterator, DestIterator, DestAccessor> dest)
    00544 {
    00545     resizeImageLinearInterpolation(src.first, src.second, src.third,
    00546                                    dest.first, dest.second, dest.third);
    00547 }
    00548
    00549 /***************************************************************/
    00550 /*                                                             */
    00551 /*                resizeImageSplineInterpolation               */
    00552 /*                                                             */
    00553 /***************************************************************/
    00554
    00555 /** \brief Resize image using B-spline interpolation.
    00556
    00557     The function implements separable spline interpolation algorithm described in
    00558
    00559     M. Unser, A. Aldroubi, M. Eden, <i>"B-Spline Signal Processing"</i>
    00560     IEEE Transactions on Signal Processing, vol. 41, no. 2, pp. 821-833 (part I),
    00561     pp. 834-848 (part II), 1993.
    00562
    00563     to obtain optimal interpolation quality and speed. You may pass the funcion
    00564     a spline of arbitrary order (e.g. <TT>BSpline<ORDER, double></tt> or
    00565     <TT>CatmullRomSpline<double></tt>). The default is a third order spline
    00566     which gives a twice continuously differentiable interpolant.
    00567     The implementation ensures that image values are interpolated rather
    00568     than smoothed by first calling a recursive (sharpening) prefilter as
    00569     described in the above paper. Then the actual interpolation is done
    00570     using \ref resamplingConvolveLine().
    00571
    00572     The range of both the input and output images (resp. regions)
    00573     must be given. The input image must have a size of at
    00574     least 4x4, the destination of at least 2x2. The scaling factors are then calculated
    00575     accordingly. If the source image is larger than the destination, it
    00576     is smoothed (band limited) using a recursive
    00577     exponential filter. The source value_type (SrcAccessor::value_type) must
    00578     be a linear algebra, i.e. it must support addition, subtraction,
    00579     and multiplication (+, -, *), multiplication with a scalar
    00580     real number and \ref NumericTraits "NumericTraits".
    00581     The function uses accessors.
    00582
    00583     <b> Declarations:</b>
    00584
    00585     pass arguments explicitly:
    00586     \code
    00587     namespace vigra {
    00588         template <class SrcImageIterator, class SrcAccessor,
    00589                   class DestImageIterator, class DestAccessor,
    00590                   class SPLINE>
    00591         void
    00592         resizeImageSplineInterpolation(
    00593               SrcImageIterator is, SrcImageIterator iend, SrcAccessor sa,
    00594               DestImageIterator id, DestImageIterator idend, DestAccessor da,
    00595               SPLINE spline = BSpline<3, double>())
    00596     }
    00597     \endcode
    00598
    00599
    00600     use argument objects in conjunction with \ref ArgumentObjectFactories :
    00601     \code
    00602     namespace vigra {
    00603         template <class SrcImageIterator, class SrcAccessor,
    00604                   class DestImageIterator, class DestAccessor,
    00605                   class SPLINE>
    00606         void
    00607         resizeImageSplineInterpolation(
    00608               triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    00609               triple<DestImageIterator, DestImageIterator, DestAccessor> dest,
    00610               SPLINE spline = BSpline<3, double>())
    00611     }
    00612     \endcode
    00613
    00614     <b> Usage:</b>
    00615
    00616         <b>\#include</b> <<a href="resizeimage_8hxx-source.html">vigra/resizeimage.hxx</a>><br>
    00617         Namespace: vigra
    00618
    00619     \code
    00620     vigra::resizeImageSplineInterpolation(
    00621                src.upperLeft(), src.lowerRight(), src.accessor(),
    00622                dest.upperLeft(), dest.lowerRight(), dest.accessor());
    00623
    00624     \endcode
    00625
    00626     <b> Required Interface:</b>
    00627
    00628     \code
    00629     SrcImageIterator src_upperleft, src_lowerright;
    00630     DestImageIterator dest_upperleft, src_lowerright;
    00631
    00632     SrcAccessor src_accessor;
    00633     DestAccessor dest_accessor;
    00634
    00635     NumericTraits<SrcAccessor::value_type>::RealPromote
    00636                              u = src_accessor(src_upperleft),
    00637                  v = src_accessor(src_upperleft, 1);
    00638     double d;
    00639
    00640     u = d * v;
    00641     u = u + v;
    00642     u = u - v;
    00643     u = u * v;
    00644     u += v;
    00645     u -= v;
    00646
    00647     dest_accessor.set(
    00648         NumericTraits<DestAccessor::value_type>::fromRealPromote(u),
    00649     dest_upperleft);
    00650
    00651     \endcode
    00652
    00653     <b> Preconditions:</b>
    00654
    00655     \code
    00656     src_lowerright.x - src_upperleft.x > 3
    00657     src_lowerright.y - src_upperleft.y > 3
    00658     dest_lowerright.x - dest_upperleft.x > 1
    00659     dest_lowerright.y - dest_upperleft.y > 1
    00660     \endcode
    00661
    00662 */
    00663 doxygen_overloaded_function(template <...> void resizeImageSplineInterpolation)
    00664
    00665 template <class SrcIterator, class SrcAccessor,
    00666           class DestIterator, class DestAccessor,
    00667           class SPLINE>
    00668 void
    00669 resizeImageSplineInterpolation(
    00670     SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
    00671     DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc,
    00672     SPLINE const & spline)
    00673 {
    00674
    00675     int width_old = src_iter_end.x - src_iter.x;
    00676     int height_old = src_iter_end.y - src_iter.y;
    00677
    00678     int width_new = dest_iter_end.x - dest_iter.x;
    00679     int height_new = dest_iter_end.y - dest_iter.y;
    00680
    00681     vigra_precondition((width_old > 1) && (height_old > 1),
    00682                  "resizeImageSplineInterpolation(): "
    00683                  "Source image to small.\n");
    00684
    00685     vigra_precondition((width_new > 1) && (height_new > 1),
    00686                  "resizeImageSplineInterpolation(): "
    00687                  "Destination image to small.\n");
    00688
    00689     Rational<int> xratio(width_new - 1, width_old - 1);
    00690     Rational<int> yratio(height_new - 1, height_old - 1);
    00691     Rational<int> offset(0);
    00692     resampling_detail::MapTargetToSourceCoordinate xmapCoordinate(xratio, offset);
    00693     resampling_detail::MapTargetToSourceCoordinate ymapCoordinate(yratio, offset);
    00694     int xperiod = lcm(xratio.numerator(), xratio.denominator());
    00695     int yperiod = lcm(yratio.numerator(), yratio.denominator());
    00696
    00697     double const scale = 2.0;
    00698
    00699     typedef typename SrcAccessor::value_type SRCVT;
    00700     typedef typename NumericTraits<SRCVT>::RealPromote TMPTYPE;
    00701     typedef BasicImage<TMPTYPE> TmpImage;
    00702     typedef typename TmpImage::traverser TmpImageIterator;
    00703
    00704     BasicImage<TMPTYPE> tmp(width_old, height_new);
    00705
    00706     BasicImage<TMPTYPE> line((height_old > width_old) ? height_old : width_old, 1);
    00707     typename BasicImage<TMPTYPE>::Accessor tmp_acc = tmp.accessor();
    00708     ArrayVector<double> const & prefilterCoeffs = spline.prefilterCoefficients();
    00709
    00710     int x,y;
    00711
    00712     ArrayVector<Kernel1D<double> > kernels(yperiod);
    00713     createResamplingKernels(spline, ymapCoordinate, kernels);
    00714
    00715     typename BasicImage<TMPTYPE>::Iterator y_tmp = tmp.upperLeft();
    00716     typename TmpImageIterator::row_iterator line_tmp = line.upperLeft().rowIterator();
    00717
    00718     for(x=0; x<width_old; ++x, ++src_iter.x, ++y_tmp.x)
    00719     {
    00720
    00721         typename SrcIterator::column_iterator c_src = src_iter.columnIterator();
    00722         typename TmpImageIterator::column_iterator c_tmp = y_tmp.columnIterator();
    00723
    00724         if(prefilterCoeffs.size() == 0)
    00725         {
    00726             if(height_new >= height_old)
    00727             {
    00728                 resamplingConvolveLine(c_src, c_src + height_old, src_acc,
    00729                                        c_tmp, c_tmp + height_new, tmp_acc,
    00730                                        kernels, ymapCoordinate);
    00731             }
    00732             else
    00733             {
    00734                 recursiveSmoothLine(c_src, c_src + height_old, src_acc,
    00735                      line_tmp, line.accessor(), (double)height_old/height_new/scale);
    00736                 resamplingConvolveLine(line_tmp, line_tmp + height_old, line.accessor(),
    00737                                        c_tmp, c_tmp + height_new, tmp_acc,
    00738                                        kernels, ymapCoordinate);
    00739             }
    00740         }
    00741         else
    00742         {
    00743             recursiveFilterLine(c_src, c_src + height_old, src_acc,
    00744                                 line_tmp, line.accessor(),
    00745                                 prefilterCoeffs[0], BORDER_TREATMENT_REFLECT);
    00746             for(unsigned int b = 1; b < prefilterCoeffs.size(); ++b)
    00747             {
    00748                 recursiveFilterLine(line_tmp, line_tmp + height_old, line.accessor(),
    00749                                     line_tmp, line.accessor(),
    00750                                     prefilterCoeffs[b], BORDER_TREATMENT_REFLECT);
    00751             }
    00752             if(height_new < height_old)
    00753             {
    00754                 recursiveSmoothLine(line_tmp, line_tmp + height_old, line.accessor(),
    00755                      line_tmp, line.accessor(), (double)height_old/height_new/scale);
    00756             }
    00757             resamplingConvolveLine(line_tmp, line_tmp + height_old, line.accessor(),
    00758                                    c_tmp, c_tmp + height_new, tmp_acc,
    00759                                    kernels, ymapCoordinate);
    00760         }
    00761     }
    00762
    00763     y_tmp = tmp.upperLeft();
    00764
    00765     DestIterator dest = dest_iter;
    00766
    00767     kernels.resize(xperiod);
    00768     createResamplingKernels(spline, xmapCoordinate, kernels);
    00769
    00770     for(y=0; y < height_new; ++y, ++y_tmp.y, ++dest_iter.y)
    00771     {
    00772         typename DestIterator::row_iterator r_dest = dest_iter.rowIterator();
    00773         typename TmpImageIterator::row_iterator r_tmp = y_tmp.rowIterator();
    00774
    00775         if(prefilterCoeffs.size() == 0)
    00776         {
    00777             if(width_new >= width_old)
    00778             {
    00779                 resamplingConvolveLine(r_tmp, r_tmp + width_old, tmp.accessor(),
    00780                                        r_dest, r_dest + width_new, dest_acc,
    00781                                        kernels, xmapCoordinate);
    00782             }
    00783             else
    00784             {
    00785                 recursiveSmoothLine(r_tmp, r_tmp + width_old, tmp.accessor(),
    00786                                   line_tmp, line.accessor(), (double)width_old/width_new/scale);
    00787                 resamplingConvolveLine(line_tmp, line_tmp + width_old, line.accessor(),
    00788                                        r_dest, r_dest + width_new, dest_acc,
    00789                                        kernels, xmapCoordinate);
    00790             }
    00791         }
    00792         else
    00793         {
    00794             recursiveFilterLine(r_tmp, r_tmp + width_old, tmp.accessor(),
    00795                                 line_tmp, line.accessor(),
    00796                                 prefilterCoeffs[0], BORDER_TREATMENT_REFLECT);
    00797             for(unsigned int b = 1; b < prefilterCoeffs.size(); ++b)
    00798             {
    00799                 recursiveFilterLine(line_tmp, line_tmp + width_old, line.accessor(),
    00800                                     line_tmp, line.accessor(),
    00801                                     prefilterCoeffs[b], BORDER_TREATMENT_REFLECT);
    00802             }
    00803             if(width_new < width_old)
    00804             {
    00805                 recursiveSmoothLine(line_tmp, line_tmp + width_old, line.accessor(),
    00806                                     line_tmp, line.accessor(), (double)width_old/width_new/scale);
    00807             }
    00808             resamplingConvolveLine(line_tmp, line_tmp + width_old, line.accessor(),
    00809                                    r_dest, r_dest + width_new, dest_acc,
    00810                                    kernels, xmapCoordinate);
    00811         }
    00812     }
    00813 }
    00814
    00815 template <class SrcIterator, class SrcAccessor,
    00816           class DestIterator, class DestAccessor,
    00817           class SPLINE>
    00818 inline
    00819 void
    00820 resizeImageSplineInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00821                       triple<DestIterator, DestIterator, DestAccessor> dest,
    00822                       SPLINE const & spline)
    00823 {
    00824     resizeImageSplineInterpolation(src.first, src.second, src.third,
    00825                                    dest.first, dest.second, dest.third, spline);
    00826 }
    00827
    00828 template <class SrcIterator, class SrcAccessor,
    00829           class DestIterator, class DestAccessor>
    00830 void
    00831 resizeImageSplineInterpolation(SrcIterator is, SrcIterator iend, SrcAccessor sa,
    00832                       DestIterator id, DestIterator idend, DestAccessor da)
    00833 {
    00834     resizeImageSplineInterpolation(is, iend, sa, id, idend, da, BSpline<3, double>());
    00835 }
    00836
    00837 template <class SrcIterator, class SrcAccessor,
    00838           class DestIterator, class DestAccessor>
    00839 inline
    00840 void
    00841 resizeImageSplineInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00842                       triple<DestIterator, DestIterator, DestAccessor> dest)
    00843 {
    00844     resizeImageSplineInterpolation(src.first, src.second, src.third,
    00845                                    dest.first, dest.second, dest.third);
    00846 }
    00847
    00848 /*****************************************************************/
    00849 /*                                                               */
    00850 /*              resizeImageCatmullRomInterpolation               */
    00851 /*                                                               */
    00852 /*****************************************************************/
    00853
    00854 /** \brief Resize image using the Catmull/Rom interpolation function.
    00855
    00856     The function calls like \ref resizeImageSplineInterpolation() with
    00857     \ref vigra::CatmullRomSpline as an interpolation kernel.
    00858     The interpolated function has one continuous derivative.
    00859     (See \ref resizeImageSplineInterpolation() for more documentation)
    00860
    00861     <b> Declarations:</b>
    00862
    00863     pass arguments explicitly:
    00864     \code
    00865     namespace vigra {
    00866         template <class SrcIterator, class SrcAccessor,
    00867                   class DestIterator, class DestAccessor>
    00868         void
    00869         resizeImageCatmullRomInterpolation(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
    00870                               DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc);
    00871     }
    00872     \endcode
    00873
    00874
    00875     use argument objects in conjunction with \ref ArgumentObjectFactories :
    00876     \code
    00877     namespace vigra {
    00878         template <class SrcIterator, class SrcAccessor,
    00879                   class DestIterator, class DestAccessor>
    00880         void
    00881         resizeImageCatmullRomInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00882                               triple<DestIterator, DestIterator, DestAccessor> dest);
    00883     }
    00884     \endcode
    00885
    00886
    00887     <b>\#include</b> <<a href="resizeimage_8hxx-source.html">vigra/resizeimage.hxx</a>><br>
    00888     Namespace: vigra
    00889
    00890 */
    00891 doxygen_overloaded_function(template <...> void resizeImageCatmullRomInterpolation)
    00892
    00893 template <class SrcIterator, class SrcAccessor,
    00894           class DestIterator, class DestAccessor>
    00895 inline void
    00896 resizeImageCatmullRomInterpolation(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
    00897                       DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc)
    00898 {
    00899     resizeImageSplineInterpolation(src_iter, src_iter_end, src_acc, dest_iter, dest_iter_end, dest_acc,
    00900                                   CatmullRomSpline<double>());
    00901 }
    00902
    00903 template <class SrcIterator, class SrcAccessor,
    00904           class DestIterator, class DestAccessor>
    00905 inline
    00906 void
    00907 resizeImageCatmullRomInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00908                       triple<DestIterator, DestIterator, DestAccessor> dest)
    00909 {
    00910     resizeImageCatmullRomInterpolation(src.first, src.second, src.third,
    00911                                      dest.first, dest.second, dest.third);
    00912 }
    00913
    00914 #if 0
    00915 /*****************************************************************/
    00916 /*                                                               */
    00917 /*              resizeImageCubicInterpolation                    */
    00918 /*                                                               */
    00919 /*****************************************************************/
    00920
    00921 /** \brief Resize image using the cardinal B-spline interpolation function.
    00922
    00923     The function calls like \ref resizeImageSplineInterpolation() with
    00924     \ref vigra::BSpline<3, double> and prefiltering as an interpolation kernel.
    00925     The interpolated function has two continuous derivatives.
    00926     (See \ref resizeImageSplineInterpolation() for more documentation)
    00927
    00928     <b>\#include</b> <<a href="resizeimage_8hxx-source.html">vigra/resizeimage.hxx</a>><br>
    00929     Namespace: vigra
    00930
    00931 */
    00932 template <class SrcIterator, class SrcAccessor,
    00933           class DestIterator, class DestAccessor>
    00934 void
    00935 resizeImageCubicInterpolation(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
    00936                       DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc)
    00937 {
    00938     resizeImageSplineInterpolation(src_iter, src_iter_end, src_acc, dest_iter, dest_iter_end, dest_acc,
    00939                                   BSpline<3, double>());
    00940 }
    00941
    00942 template <class SrcIterator, class SrcAccessor,
    00943           class DestIterator, class DestAccessor>
    00944 inline
    00945 void
    00946 resizeImageCubicInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00947                       triple<DestIterator, DestIterator, DestAccessor> dest)
    00948 {
    00949     resizeImageCubicInterpolation(src.first, src.second, src.third,
    00950                                    dest.first, dest.second, dest.third);
    00951 }
    00952 #endif
    00953
    00954 /*****************************************************************/
    00955 /*                                                               */
    00956 /*              resizeImageCoscotInterpolation                   */
    00957 /*                                                               */
    00958 /*****************************************************************/
    00959
    00960 /** \brief Resize image using the Coscot interpolation function.
    00961
    00962     The function calls \ref resizeImageSplineInterpolation() with
    00963     \ref vigra::CoscotFunction as an interpolation kernel.
    00964     The interpolated function has one continuous derivative.
    00965     (See \ref resizeImageSplineInterpolation() for more documentation)
    00966
    00967     <b> Declarations:</b>
    00968
    00969     pass arguments explicitly:
    00970     \code
    00971     namespace vigra {
    00972         template <class SrcIterator, class SrcAccessor,
    00973                   class DestIterator, class DestAccessor>
    00974         void
    00975         resizeImageCoscotInterpolation(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
    00976                               DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc);
    00977     }
    00978     \endcode
    00979
    00980
    00981     use argument objects in conjunction with \ref ArgumentObjectFactories :
    00982     \code
    00983     namespace vigra {
    00984         template <class SrcIterator, class SrcAccessor,
    00985                   class DestIterator, class DestAccessor>
    00986         void
    00987         resizeImageCoscotInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00988                               triple<DestIterator, DestIterator, DestAccessor> dest);
    00989     }
    00990     \endcode
    00991
    00992
    00993     <b>\#include</b> <<a href="resizeimage_8hxx-source.html">vigra/resizeimage.hxx</a>><br>
    00994     Namespace: vigra
    00995
    00996 */
    00997 doxygen_overloaded_function(template <...> void resizeImageCoscotInterpolation)
    00998
    00999 template <class SrcIterator, class SrcAccessor,
    01000           class DestIterator, class DestAccessor>
    01001 void
    01002 resizeImageCoscotInterpolation(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
    01003                       DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc)
    01004 {
    01005     resizeImageSplineInterpolation(src_iter, src_iter_end, src_acc, dest_iter, dest_iter_end, dest_acc,
    01006                                    CoscotFunction<double>());
    01007 }
    01008
    01009 template <class SrcIterator, class SrcAccessor,
    01010           class DestIterator, class DestAccessor>
    01011 inline
    01012 void
    01013 resizeImageCoscotInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    01014                       triple<DestIterator, DestIterator, DestAccessor> dest)
    01015 {
    01016     resizeImageCoscotInterpolation(src.first, src.second, src.third,
    01017                                    dest.first, dest.second, dest.third);
    01018 }
    01019
    01020
    01021 #if 0 // old version of the spline interpolation algorithm
    01022
    01023 /********************************************************/
    01024 /*                                                      */
    01025 /*           resizeCalculateSplineCoefficients          */
    01026 /*         (internally used by resize functions)        */
    01027 /*                                                      */
    01028 /********************************************************/
    01029
    01030 template <class SrcIterator, class SrcAccessor, class VALUETYPE>
    01031 void
    01032 resizeCalculateSplineCoefficients(SrcIterator i1, SrcIterator iend,
    01033                 SrcAccessor a, VALUETYPE * i2)
    01034 {
    01035     int n = iend - i1;
    01036
    01037     if(n <= 0) return;
    01038
    01039     VALUETYPE zero = NumericTraits<VALUETYPE>::zero();
    01040     VALUETYPE two = 2.0 * NumericTraits<VALUETYPE>::one();
    01041     VALUETYPE half = 0.5 * NumericTraits<VALUETYPE>::one();
    01042
    01043     *i2 = zero;
    01044     if(n == 1) return;
    01045
    01046     std::vector<VALUETYPE> vec(n);
    01047     typename std::vector<VALUETYPE>::iterator u = vec.begin();
    01048
    01049     *u = zero;
    01050
    01051     for(++i1, ++i2, ++u, --iend; i1 != iend; ++i1, ++i2, ++u)
    01052     {
    01053         VALUETYPE p = 0.5 * i2[-1] + two;
    01054         *i2 = half / p;
    01055         *u = 3.0 *(a(i1,1) - 2.0 * a(i1) + a(i1, -1)) - 0.5 * u[-1] / p;
    01056     }
    01057
    01058     *i2 = zero;
    01059
    01060     for(--i2, --u; u != vec; --u, --i2)
    01061     {
    01062         *i2 = *i2 * i2[1] + *u;
    01063     }
    01064 }
    01065
    01066 /********************************************************/
    01067 /*                                                      */
    01068 /*         resizeImageInternalSplineGradient            */
    01069 /*                                                      */
    01070 /********************************************************/
    01071
    01072 template <class SrcIterator, class SrcAccessor,
    01073           class DoubleIterator, class TempIterator, class DestIterator>
    01074 void
    01075 resizeImageInternalSplineGradient(SrcIterator in, SrcIterator inend, SrcAccessor sa,
    01076                          DoubleIterator tmp, TempIterator r, DestIterator id)
    01077 {
    01078     int w = inend - in;
    01079
    01080     int x;
    01081
    01082     typedef typename SrcAccessor::value_type SRCVT;
    01083     typedef typename NumericTraits<SRCVT>::RealPromote TMPTYPE;
    01084
    01085     // calculate border derivatives
    01086     SrcIterator xs = in;
    01087     TMPTYPE p0 = -11.0/6.0 * sa(xs);  ++xs;
    01088             p0 += 3.0 * sa(xs);  ++xs;
    01089             p0 += -1.5 * sa(xs);  ++xs;
    01090             p0 += 1.0/3.0 * sa(xs);
    01091
    01092     xs = in + w-1;
    01093     TMPTYPE pw = 11.0/6.0 * sa(xs);  --xs;
    01094             pw += -3.0 * sa(xs);  --xs;
    01095             pw +=  1.5 * sa(xs);  --xs;
    01096             pw += -1.0/3.0 * sa(xs);
    01097
    01098     xs = in + 2;
    01099     SrcIterator xs1 = in;
    01100
    01101     for(x=1; x<w-1; ++x, ++xs, ++xs1)
    01102     {
    01103         r[x] = 3.0 * (sa(xs) - sa(xs1));
    01104     }
    01105
    01106     r[1] -= p0;
    01107     r[w-2] -= pw;
    01108
    01109     double q = 0.25;
    01110
    01111     id[0] = p0;
    01112     id[w-1] = pw;
    01113     id[1] = 0.25 * r[1];
    01114
    01115     for(x=2; x<w-1; ++x)
    01116     {
    01117         tmp[x] = q;
    01118         q = 1.0 / (4.0 - q);
    01119         id[x] = q * (r[x] - id[x-1]);
    01120     }
    01121
    01122     for(x=w-3; x>=1; --x)
    01123     {
    01124         id[x] -= tmp[x+1]*id[x+1];
    01125     }
    01126 }
    01127
    01128 /********************************************************/
    01129 /*                                                      */
    01130 /*         resizeImageInternalSplineInterpolation       */
    01131 /*                                                      */
    01132 /********************************************************/
    01133
    01134 template <class SrcIterator, class SrcAccessor,
    01135           class DestIterator, class DestAccessor>
    01136 void
    01137 resizeImageInternalSplineInterpolation(SrcIterator is, SrcIterator iend, SrcAccessor sa,
    01138                       DestIterator id, DestIterator idend, DestAccessor da)
    01139 {
    01140     int w = iend.x - is.x;
    01141     int h = iend.y - is.y;
    01142
    01143     int wnew = idend.x - id.x;
    01144     int hnew = idend.y - id.y;
    01145
    01146     typedef typename SrcAccessor::value_type SRCVT;
    01147     typedef typename NumericTraits<SRCVT>::RealPromote TMPTYPE;
    01148     typedef typename BasicImage<TMPTYPE>::Iterator TMPITER;
    01149     typedef
    01150         NumericTraits<typename DestAccessor::value_type> DestTraits;
    01151
    01152     BasicImage<TMPTYPE> dx(w,h);
    01153     BasicImage<TMPTYPE> dy(w,h);
    01154     BasicImage<TMPTYPE> dxy(w,h);
    01155     BasicImage<TMPTYPE> W(4,4), W1(4,4);
    01156     std::vector<TMPTYPE> R(w > h ? w : h);
    01157     std::vector<double> tmp(w > h ? w : h);
    01158
    01159     typename BasicImage<TMPTYPE>::Accessor ta;
    01160
    01161     SrcIterator in = is;
    01162
    01163     TMPITER idx = dx.upperLeft();
    01164     TMPITER idy = dy.upperLeft();
    01165     TMPITER idxy = dxy.upperLeft();
    01166     typename std::vector<TMPTYPE>::iterator r = R.begin();
    01167     typename std::vector<double>::iterator it = tmp.begin();
    01168
    01169     double ig[] = { 1.0, 0.0, -3.0,  2.0,
    01170                     0.0, 1.0, -2.0,  1.0,
    01171                     0.0, 0.0,  3.0, -2.0,
    01172                     0.0, 0.0, -1.0,  1.0 };
    01173
    01174     int x, y, i, j, k;
    01175
    01176
    01177     // calculate x derivatives
    01178     for(y=0; y<h; ++y, ++in.y, ++idx.y)
    01179     {
    01180         typename SrcIterator::row_iterator sr = in.rowIterator();
    01181         typename TMPITER::row_iterator dr = idx.rowIterator();
    01182         resizeImageInternalSplineGradient(sr, sr+w, sa,
    01183                                           it, r, dr);
    01184     }
    01185
    01186     in = is;
    01187
    01188     // calculate y derivatives
    01189     for(x=0; x<w; ++x, ++in.x, ++idy.x)
    01190     {
    01191         typename SrcIterator::column_iterator sc = in.columnIterator();
    01192         typename TMPITER::column_iterator dc = idy.columnIterator();
    01193         resizeImageInternalSplineGradient(sc, sc+h, sa,
    01194                                           it, r, dc);
    01195     }
    01196
    01197     in = is;
    01198     idy = dy.upperLeft();
    01199
    01200     // calculate mixed derivatives
    01201     for(y=0; y<h; ++y, ++idy.y, ++idxy.y)
    01202     {
    01203         typename TMPITER::row_iterator sr = idy.rowIterator();
    01204         typename TMPITER::row_iterator dr = idxy.rowIterator();
    01205         resizeImageInternalSplineGradient(sr, sr+w, ta,
    01206                                           it, r, dr);
    01207     }
    01208
    01209     double du = (double)(w-1) / (wnew-1);
    01210     double dv = (double)(h-1) / (hnew-1);
    01211     double ov = 0.0;
    01212     int oy = 0;
    01213     int yy = oy;
    01214
    01215     DestIterator xxd = id, yyd = id;
    01216
    01217     static Diff2D down(0,1), right(1,0), downright(1,1);
    01218
    01219     for(y=0; y<h-1; ++y, ++in.y, ov -= 1.0)
    01220     {
    01221         if(y < h-2 && ov >= 1.0) continue;
    01222         int y1 = y+1;
    01223         double v = ov;
    01224         double ou = 0.0;
    01225         int ox = 0;
    01226         int xx = ox;
    01227
    01228         SrcIterator xs = in;
    01229         for(x=0; x<w-1; ++x, ++xs.x, ou -= 1.0)
    01230         {
    01231             if(x < w-2 && ou >= 1.0) continue;
    01232             int x1 = x+1;
    01233             double u = ou;
    01234
    01235             DestIterator xd = id + Diff2D(ox,oy);
    01236             W[0][0] = sa(xs);
    01237             W[0][1] = dy(x, y);
    01238             W[0][2] = sa(xs, down);
    01239             W[0][3] = dy(x, y1);
    01240             W[1][0] = dx(x, y);
    01241             W[1][1] = dxy(x, y);
    01242             W[1][2] = dx(x, y1);
    01243             W[1][3] = dxy(x, y1);
    01244             W[2][0] = sa(xs, right);
    01245             W[2][1] = dy(x1,y);
    01246             W[2][2] = sa(xs, downright);
    01247             W[2][3] = dy(x1, y1);
    01248             W[3][0] = dx(x1, y);
    01249             W[3][1] = dxy(x1, y);
    01250             W[3][2] = dx(x1, y1);
    01251             W[3][3] = dxy(x1, y1);
    01252
    01253             for(i=0; i<4; ++i)
    01254             {
    01255                 for(j=0; j<4; ++j)
    01256                 {
    01257                     W1[j][i] = ig[j] * W[0][i];
    01258                     for(k=1; k<4; ++k)
    01259                     {
    01260                         W1[j][i] += ig[j+4*k] * W[k][i];
    01261                     }
    01262                 }
    01263             }
    01264             for(i=0; i<4; ++i)
    01265             {
    01266                 for(j=0; j<4; ++j)
    01267                 {
    01268                     W[j][i] = ig[i] * W1[j][0];
    01269                     for(k=1; k<4; ++k)
    01270                     {
    01271                        W[j][i] += ig[4*k+i] * W1[j][k];
    01272                     }
    01273                 }
    01274             }
    01275
    01276             TMPTYPE a1,a2,a3,a4;
    01277
    01278             yyd = xd;
    01279             for(v=ov, yy=oy; v<1.0; v+=dv, ++yyd.y, ++yy)
    01280             {
    01281                 a1 = W[0][0] + v * (W[0][1] +
    01282                                v * (W[0][2] + v * W[0][3]));
    01283                 a2 = W[1][0] + v * (W[1][1] +
    01284                                v * (W[1][2] + v * W[1][3]));
    01285                 a3 = W[2][0] + v * (W[2][1] +
    01286                                v * (W[2][2] + v * W[2][3]));
    01287                 a4 = W[3][0] + v * (W[3][1] +
    01288                                v * (W[3][2] + v * W[3][3]));
    01289
    01290                 xxd = yyd;
    01291                 for(u=ou, xx=ox; u<1.0; u+=du, ++xxd.x, ++xx)
    01292                 {
    01293                     da.set(DestTraits::fromRealPromote(a1 + u * (a2 + u * (a3 + u * a4))), xxd);
    01294                 }
    01295
    01296                 if(xx == wnew-1)
    01297                 {
    01298                     da.set(DestTraits::fromRealPromote(a1 + a2 + a3 + a4), xxd);
    01299                 }
    01300             }
    01301
    01302             if(yy == hnew-1)
    01303             {
    01304                 a1 = W[0][0] + W[0][1] + W[0][2] + W[0][3];
    01305                 a2 = W[1][0] + W[1][1] + W[1][2] + W[1][3];
    01306                 a3 = W[2][0] + W[2][1] + W[2][2] + W[2][3];
    01307                 a4 = W[3][0] + W[3][1] + W[3][2] + W[3][3];
    01308
    01309                 DestIterator xxd = yyd;
    01310                 for(u=ou, xx=ox; u<1.0; u+=du, ++xxd.x, ++xx)
    01311                 {
    01312                     da.set(DestTraits::fromRealPromote(a1 + u * (a2 + u * (a3 + u * a4))), xxd);
    01313                 }
    01314
    01315                 if(xx == wnew-1)
    01316                 {
    01317                     da.set(DestTraits::fromRealPromote(a1 + a2 + a3 + a4), xxd);
    01318                 }
    01319             }
    01320
    01321             ou = u;
    01322             ox = xx;
    01323         }
    01324         ov = v;
    01325         oy = yy;
    01326     }
    01327 }
    01328
    01329 template <class SrcIterator, class SrcAccessor,
    01330           class DestIterator, class DestAccessor>
    01331 void
    01332 resizeImageSplineInterpolation(SrcIterator is, SrcIterator iend, SrcAccessor sa,
    01333                       DestIterator id, DestIterator idend, DestAccessor da)
    01334 {
    01335     int w = iend.x - is.x;
    01336     int h = iend.y - is.y;
    01337
    01338     int wnew = idend.x - id.x;
    01339     int hnew = idend.y - id.y;
    01340
    01341     vigra_precondition((w > 3) && (h > 3),
    01342                  "resizeImageSplineInterpolation(): "
    01343                  "Source image to small.\n");
    01344     vigra_precondition((wnew > 1) && (hnew > 1),
    01345                  "resizeImageSplineInterpolation(): "
    01346                  "Destination image to small.\n");
    01347
    01348     double scale = 2.0;
    01349
    01350     if(wnew < w || hnew < h)
    01351     {
    01352         typedef typename SrcAccessor::value_type SRCVT;
    01353         typedef typename NumericTraits<SRCVT>::RealPromote TMPTYPE;
    01354         typedef typename BasicImage<TMPTYPE>::Iterator TMPITER;
    01355
    01356         BasicImage<TMPTYPE> t(w,h);
    01357         TMPITER it = t.upperLeft();
    01358
    01359         if(wnew < w)
    01360         {
    01361             recursiveSmoothX(is, iend, sa,
    01362                     it, t.accessor(), (double)w/wnew/scale);
    01363
    01364             if(hnew < h)
    01365             {
    01366                recursiveSmoothY(it, t.lowerRight(), t.accessor(),
    01367                     it, t.accessor(), (double)h/hnew/scale);
    01368             }
    01369         }
    01370         else
    01371         {
    01372            recursiveSmoothY(is, iend, sa,
    01373                     it, t.accessor(), (double)h/hnew/scale);
    01374         }
    01375
    01376         resizeImageInternalSplineInterpolation(it, t.lowerRight(), t.accessor(),
    01377                                                id, idend, da);
    01378     }
    01379     else
    01380     {
    01381         resizeImageInternalSplineInterpolation(is, iend, sa, id, idend, da);
    01382     }
    01383 }
    01384
    01385 template <class SrcIterator, class SrcAccessor,
    01386           class DestIterator, class DestAccessor>
    01387 inline
    01388 void
    01389 resizeImageSplineInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    01390                       triple<DestIterator, DestIterator, DestAccessor> dest)
    01391 {
    01392     resizeImageSplineInterpolation(src.first, src.second, src.third,
    01393                                    dest.first, dest.second, dest.third);
    01394 }
    01395 #endif  // old alghorithm version
    01396
    01397 //@}
    01398
    01399 } // namespace vigra
    01400
    01401 #endif // VIGRA_RESIZEIMAGE_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.7.1 (3 Dec 2010)