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

| vigra/resizeimage.hxx |
--- | --- | ---

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

© Ullrich Köthe (koethe@informatik.uni-hamburg.de) Cognitive Systems Group, University of Hamburg, Germany | html generated using doxygen and Python VIGRA 1.3.2 (27 Jan 2005)