VIGRA - vigra/resizeimage.hxx Source File

[ 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.5.0, Dec 07 2006 )                                    */
    00008 /*    The VIGRA Website is                                              */
    00009 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
    00010 /*    Please direct questions, bug reports, and contributions to        */
    00011 /*        koethe@informatik.uni-hamburg.de          or                  */
    00012 /*        vigra@kogs1.informatik.uni-hamburg.de                         */
    00013 /*                                                                      */
    00014 /*    Permission is hereby granted, free of charge, to any person       */
    00015 /*    obtaining a copy of this software and associated documentation    */
    00016 /*    files (the "Software"), to deal in the Software without           */
    00017 /*    restriction, including without limitation the rights to use,      */
    00018 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
    00019 /*    sell copies of the Software, and to permit persons to whom the    */
    00020 /*    Software is furnished to do so, subject to the following          */
    00021 /*    conditions:                                                       */
    00022 /*                                                                      */
    00023 /*    The above copyright notice and this permission notice shall be    */
    00024 /*    included in all copies or substantial portions of the             */
    00025 /*    Software.                                                         */
    00026 /*                                                                      */
    00027 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
    00028 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
    00029 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
    00030 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
    00031 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
    00032 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
    00033 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
    00034 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */
    00035 /*                                                                      */
    00036 /************************************************************************/
    00037
    00038
    00039 #ifndef VIGRA_RESIZEIMAGE_HXX
    00040 #define VIGRA_RESIZEIMAGE_HXX
    00041
    00042 #include <vector>
    00043 #include "utilities.hxx"
    00044 #include "numerictraits.hxx"
    00045 #include "stdimage.hxx"
    00046 #include "recursiveconvolution.hxx"
    00047 #include "separableconvolution.hxx"
    00048 #include "resampling_convolution.hxx"
    00049 #include "splines.hxx"
    00050
    00051 namespace vigra {
    00052
    00053 /*****************************************************************/
    00054 /*                                                               */
    00055 /*                         CoscotFunction                        */
    00056 /*                                                               */
    00057 /*****************************************************************/
    00058
    00059 /*! The Coscot interpolation function.
    00060
    00061     Implements the Coscot interpolation function proposed by Maria Magnusson Seger
    00062     (maria@isy.liu.se) in the context of tomographic reconstruction. It provides a fast
    00063     transition between the pass- and stop-bands and minimal ripple outside the transition
    00064     region. Both properties are important for this application and can be tuned by the parameters
    00065     <i>m</i> and </i>h</i> (with defaults 3 and 0.5). The function is defined by
    00066
    00067     \f[ f_{m,h}(x) = \left\{ \begin{array}{ll}
    00068                                    \frac{1}{2m}\sin(\pi x)\cot(\pi x / (2 m))(h + (1-h)\cos(\pi x/m)) & |x| \leq m \\
    00069                                   0 & \mbox{otherwise}
    00070                         \end{array}\right.
    00071     \f]
    00072
    00073     It can be used as a functor, and as a kernel for
    00074     \ref resamplingConvolveImage() to create a differentiable interpolant
    00075     of an image.
    00076
    00077     <b>\#include</b> "<a href="resizeimage_8hxx-source.html">vigra/resizeimage.hxx</a>"<br>
    00078     Namespace: vigra
    00079
    00080     \ingroup MathFunctions
    00081 */
    00082 template <class T>
    00083 class CoscotFunction
    00084 {
    00085   public:
    00086
    00087         /** the kernel's value type
    00088         */
    00089     typedef T            value_type;
    00090         /** the unary functor's argument type
    00091         */
    00092     typedef T            argument_type;
    00093         /** the splines polynomial order
    00094         */
    00095     typedef T            result_type;
    00096
    00097     CoscotFunction(unsigned int m = 3, double h = 0.5)
    00098     : m_(m),
    00099       h_(h)
    00100     {}
    00101
    00102         /** function (functor) call
    00103         */
    00104     result_type operator()(argument_type x) const
    00105     {
    00106         return x == 0.0 ?
    00107                     1.0
    00108                   : abs(x) < m_ ?
    00109                         VIGRA_CSTD::sin(M_PI*x) / VIGRA_CSTD::tan(M_PI * x / 2.0 / m_) *
    00110                              (h_ + (1.0 - h_) * VIGRA_CSTD::cos(M_PI * x / m_)) / 2.0 / m_
    00111                       : 0.0;
    00112     }
    00113
    00114         /** index operator -- same as operator()
    00115         */
    00116     value_type operator[](value_type x) const
    00117         { return operator()(x); }
    00118
    00119         /** Radius of the function's support.
    00120             Needed for  \ref resamplingConvolveImage(), equals m.
    00121         */
    00122     double radius() const
    00123         { return m_; }
    00124
    00125         /** Derivative order of the function: always 0.
    00126         */
    00127     unsigned int derivativeOrder() const
    00128         { return 0; }
    00129
    00130         /** Prefilter coefficients for compatibility with \ref vigra::BSpline.
    00131             (array has zero length, since prefiltering is not necessary).
    00132         */
    00133     ArrayVector<double> const & prefilterCoefficients() const
    00134     {
    00135         static ArrayVector<double> b;
    00136         return b;
    00137     }
    00138
    00139   protected:
    00140
    00141     unsigned int m_;
    00142     double h_;
    00143 };
    00144
    00145 /** \addtogroup GeometricTransformations Geometric Transformations
    00146     Zoom up and down by repeating pixels, or using various interpolation schemes.
    00147
    00148     See also: \ref resamplingConvolveImage(), \ref resampleImage()
    00149
    00150     <b>\#include</b> "<a href="stdimagefunctions_8hxx-source.html">vigra/stdimagefunctions.hxx</a>"<br>
    00151     <b>or</b><br>
    00152     <b>\#include</b> "<a href="resizeimage_8hxx-source.html">vigra/resizeimage.hxx</a>"<br>
    00153 */
    00154 //@{
    00155
    00156 /********************************************************/
    00157 /*                                                      */
    00158 /*               resizeLineNoInterpolation              */
    00159 /*                                                      */
    00160 /********************************************************/
    00161
    00162 template <class SrcIterator, class SrcAccessor,
    00163           class DestIterator, class DestAccessor>
    00164 void
    00165 resizeLineNoInterpolation(SrcIterator i1, SrcIterator iend, SrcAccessor as,
    00166                            DestIterator id, DestIterator idend, DestAccessor ad)
    00167 {
    00168     int wold = iend - i1;
    00169     int wnew = idend - id;
    00170
    00171     if((wold <= 1) || (wnew <= 1)) return; // oder error ?
    00172
    00173     ad.set(as(i1), id);
    00174     ++id;
    00175
    00176     --iend, --idend;
    00177     ad.set(as(iend), idend);
    00178
    00179     double dx = (double)(wold - 1) / (wnew - 1);
    00180     double x = dx;
    00181
    00182     for(; id != idend; ++id, x += dx)
    00183     {
    00184     if(x >= 1.0)
    00185     {
    00186         int xx = (int)x;
    00187         i1 += xx;
    00188         x -= (double)xx;
    00189     }
    00190
    00191     ad.set(as(i1), id);
    00192     }
    00193 }
    00194
    00195 /********************************************************/
    00196 /*                                                      */
    00197 /*              resizeImageNoInterpolation              */
    00198 /*                                                      */
    00199 /********************************************************/
    00200
    00201 /** \brief Resize image by repeating the nearest pixel values.
    00202
    00203     This algorithm is very fast and does not require any arithmetic on
    00204     the pixel types.
    00205
    00206     The range of both the input and output images (resp. regions) must
    00207     be given. Both images must have a size of at least 2x2 pixels. The
    00208     scaling factors are then calculated accordingly. Destination
    00209     pixels are directly copied from the appropriate source pixels.
    00210
    00211     The function uses accessors.
    00212
    00213     <b> Declarations:</b>
    00214
    00215     pass arguments explicitly:
    00216     \code
    00217     namespace vigra {
    00218         template <class SrcImageIterator, class SrcAccessor,
    00219               class DestImageIterator, class DestAccessor>
    00220         void
    00221         resizeImageNoInterpolation(
    00222               SrcImageIterator is, SrcImageIterator iend, SrcAccessor sa,
    00223           DestImageIterator id, DestImageIterator idend, DestAccessor da)
    00224     }
    00225     \endcode
    00226
    00227
    00228     use argument objects in conjunction with \ref ArgumentObjectFactories:
    00229     \code
    00230     namespace vigra {
    00231         template <class SrcImageIterator, class SrcAccessor,
    00232               class DestImageIterator, class DestAccessor>
    00233         void
    00234         resizeImageNoInterpolation(
    00235               triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    00236           triple<DestImageIterator, DestImageIterator, DestAccessor> dest)
    00237     }
    00238     \endcode
    00239
    00240     <b> Usage:</b>
    00241
    00242         <b>\#include</b> "<a href="resizeimage_8hxx-source.html">vigra/resizeimage.hxx</a>"<br>
    00243         Namespace: vigra
    00244
    00245     \code
    00246     vigra::resizeImageNoInterpolation(
    00247                src.upperLeft(), src.lowerRight(), src.accessor(),
    00248                dest.upperLeft(), dest.lowerRight(), dest.accessor());
    00249
    00250     \endcode
    00251
    00252     <b> Required Interface:</b>
    00253
    00254     \code
    00255     SrcImageIterator src_upperleft, src_lowerright;
    00256     DestImageIterator dest_upperleft, src_lowerright;
    00257
    00258     SrcAccessor src_accessor;
    00259     DestAccessor dest_accessor;
    00260
    00261     dest_accessor.set(src_accessor(src_upperleft), dest_upperleft);
    00262
    00263     \endcode
    00264
    00265     <b> Preconditions:</b>
    00266
    00267     \code
    00268     src_lowerright.x - src_upperleft.x > 1
    00269     src_lowerright.y - src_upperleft.y > 1
    00270     dest_lowerright.x - dest_upperleft.x > 1
    00271     dest_lowerright.y - dest_upperleft.y > 1
    00272     \endcode
    00273
    00274 */
    00275 template <class SrcIterator, class SrcAccessor,
    00276           class DestIterator, class DestAccessor>
    00277 void
    00278 resizeImageNoInterpolation(SrcIterator is, SrcIterator iend, SrcAccessor sa,
    00279                       DestIterator id, DestIterator idend, DestAccessor da)
    00280 {
    00281     int w = iend.x - is.x;
    00282     int h = iend.y - is.y;
    00283
    00284     int wnew = idend.x - id.x;
    00285     int hnew = idend.y - id.y;
    00286
    00287     vigra_precondition((w > 1) && (h > 1),
    00288                  "resizeImageNoInterpolation(): "
    00289                  "Source image to small.\n");
    00290     vigra_precondition((wnew > 1) && (hnew > 1),
    00291                  "resizeImageNoInterpolation(): "
    00292                  "Destination image to small.\n");
    00293
    00294     typedef BasicImage<typename SrcAccessor::value_type> TmpImage;
    00295     typedef typename TmpImage::traverser TmpImageIterator;
    00296
    00297     TmpImage tmp(w, hnew);
    00298
    00299     TmpImageIterator yt = tmp.upperLeft();
    00300
    00301     for(int x=0; x<w; ++x, ++is.x, ++yt.x)
    00302     {
    00303         typename SrcIterator::column_iterator c1 = is.columnIterator();
    00304         typename TmpImageIterator::column_iterator ct = yt.columnIterator();
    00305
    00306         resizeLineNoInterpolation(c1, c1 + h, sa, ct, ct + hnew, tmp.accessor());
    00307     }
    00308
    00309     yt = tmp.upperLeft();
    00310
    00311     for(int y=0; y < hnew; ++y, ++yt.y, ++id.y)
    00312     {
    00313         typename DestIterator::row_iterator rd = id.rowIterator();
    00314         typename TmpImageIterator::row_iterator rt = yt.rowIterator();
    00315
    00316         resizeLineNoInterpolation(rt, rt + w, tmp.accessor(), rd, rd + wnew, da);
    00317     }
    00318 }
    00319
    00320 template <class SrcIterator, class SrcAccessor,
    00321           class DestIterator, class DestAccessor>
    00322 inline
    00323 void
    00324 resizeImageNoInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00325                            triple<DestIterator, DestIterator, DestAccessor> dest)
    00326 {
    00327     resizeImageNoInterpolation(src.first, src.second, src.third,
    00328                                    dest.first, dest.second, dest.third);
    00329 }
    00330
    00331 /********************************************************/
    00332 /*                                                      */
    00333 /*             resizeLineLinearInterpolation            */
    00334 /*                                                      */
    00335 /********************************************************/
    00336
    00337 template <class SrcIterator, class SrcAccessor,
    00338           class DestIterator, class DestAccessor>
    00339 void
    00340 resizeLineLinearInterpolation(SrcIterator i1, SrcIterator iend, SrcAccessor as,
    00341                            DestIterator id, DestIterator idend, DestAccessor ad)
    00342 {
    00343     int wold = iend - i1;
    00344     int wnew = idend - id;
    00345
    00346     if((wold <= 1) || (wnew <= 1)) return; // oder error ?
    00347
    00348     typedef
    00349         NumericTraits<typename DestAccessor::value_type> DestTraits;
    00350
    00351     ad.set(DestTraits::fromRealPromote(as(i1)), id);
    00352     ++id;
    00353
    00354     --iend, --idend;
    00355     ad.set(DestTraits::fromRealPromote(as(iend)), idend);
    00356
    00357     double dx = (double)(wold - 1) / (wnew - 1);
    00358     double x = dx;
    00359
    00360     for(; id != idend; ++id, x += dx)
    00361     {
    00362         if(x >= 1.0)
    00363         {
    00364             int xx = (int)x;
    00365             i1 += xx;
    00366             x -= (double)xx;
    00367         }
    00368         double x1 = 1.0 - x;
    00369
    00370         ad.set(DestTraits::fromRealPromote(x1 * as(i1) + x * as(i1, 1)), id);
    00371     }
    00372 }
    00373
    00374 /********************************************************/
    00375 /*                                                      */
    00376 /*           resizeImageLinearInterpolation             */
    00377 /*                                                      */
    00378 /********************************************************/
    00379
    00380 /** \brief Resize image using linear interpolation.
    00381
    00382     The function uses the standard separable bilinear interpolation algorithm to
    00383     obtain a good compromize between quality and speed.
    00384
    00385     The range must of both the input and output images (resp. regions)
    00386     must be given. Both images must have a size of at
    00387     least 2x2. The scaling factors are then calculated
    00388     accordingly. If the source image is larger than the destination, it
    00389     is smoothed (band limited) using a recursive
    00390     exponential filter. The source value_type (SrcAccessor::value_type) must
    00391     be a linear space, i.e. it must support addition, multiplication
    00392     with a scalar real number and \ref NumericTraits "NumericTraits".
    00393     The function uses accessors.
    00394
    00395     <b> Declarations:</b>
    00396
    00397     pass arguments explicitly:
    00398     \code
    00399     namespace vigra {
    00400         template <class SrcImageIterator, class SrcAccessor,
    00401               class DestImageIterator, class DestAccessor>
    00402         void
    00403         resizeImageLinearInterpolation(
    00404               SrcImageIterator is, SrcImageIterator iend, SrcAccessor sa,
    00405           DestImageIterator id, DestImageIterator idend, DestAccessor da)
    00406     }
    00407     \endcode
    00408
    00409
    00410     use argument objects in conjunction with \ref ArgumentObjectFactories:
    00411     \code
    00412     namespace vigra {
    00413         template <class SrcImageIterator, class SrcAccessor,
    00414               class DestImageIterator, class DestAccessor>
    00415         void
    00416         resizeImageLinearInterpolation(
    00417               triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    00418           triple<DestImageIterator, DestImageIterator, DestAccessor> dest)
    00419     }
    00420     \endcode
    00421
    00422     <b> Usage:</b>
    00423
    00424         <b>\#include</b> "<a href="resizeimage_8hxx-source.html">vigra/resizeimage.hxx</a>"<br>
    00425         Namespace: vigra
    00426
    00427     \code
    00428     vigra::resizeImageLinearInterpolation(
    00429                src.upperLeft(), src.lowerRight(), src.accessor(),
    00430                dest.upperLeft(), dest.lowerRight(), dest.accessor());
    00431
    00432     \endcode
    00433
    00434     <b> Required Interface:</b>
    00435
    00436     \code
    00437     SrcImageIterator src_upperleft, src_lowerright;
    00438     DestImageIterator dest_upperleft, src_lowerright;
    00439
    00440     SrcAccessor src_accessor;
    00441     DestAccessor dest_accessor;
    00442
    00443     NumericTraits<SrcAccessor::value_type>::RealPromote
    00444                              u = src_accessor(src_upperleft),
    00445                  v = src_accessor(src_upperleft, 1);
    00446     double d;
    00447
    00448     u = d * v;
    00449     u = u + v;
    00450
    00451     dest_accessor.set(
    00452         NumericTraits<DestAccessor::value_type>::fromRealPromote(u),
    00453     dest_upperleft);
    00454
    00455     \endcode
    00456
    00457     <b> Preconditions:</b>
    00458
    00459     \code
    00460     src_lowerright.x - src_upperleft.x > 1
    00461     src_lowerright.y - src_upperleft.y > 1
    00462     dest_lowerright.x - dest_upperleft.x > 1
    00463     dest_lowerright.y - dest_upperleft.y > 1
    00464     \endcode
    00465
    00466 */
    00467 template <class SrcIterator, class SrcAccessor,
    00468           class DestIterator, class DestAccessor>
    00469 void
    00470 resizeImageLinearInterpolation(SrcIterator is, SrcIterator iend, SrcAccessor sa,
    00471                       DestIterator id, DestIterator idend, DestAccessor da)
    00472 {
    00473     int w = iend.x - is.x;
    00474     int h = iend.y - is.y;
    00475
    00476     int wnew = idend.x - id.x;
    00477     int hnew = idend.y - id.y;
    00478
    00479     vigra_precondition((w > 1) && (h > 1),
    00480                  "resizeImageLinearInterpolation(): "
    00481                  "Source image to small.\n");
    00482     vigra_precondition((wnew > 1) && (hnew > 1),
    00483                  "resizeImageLinearInterpolation(): "
    00484                  "Destination image to small.\n");
    00485
    00486     double const scale = 2.0;
    00487
    00488     typedef typename SrcAccessor::value_type SRCVT;
    00489     typedef typename NumericTraits<SRCVT>::RealPromote TMPTYPE;
    00490     typedef BasicImage<TMPTYPE> TmpImage;
    00491     typedef typename TmpImage::traverser TmpImageIterator;
    00492
    00493     BasicImage<TMPTYPE> tmp(w, hnew);
    00494     BasicImage<TMPTYPE> line((h > w) ? h : w, 1);
    00495
    00496     int x,y;
    00497
    00498     typename BasicImage<TMPTYPE>::Iterator yt = tmp.upperLeft();
    00499     typename TmpImageIterator::row_iterator lt = line.upperLeft().rowIterator();
    00500
    00501     for(x=0; x<w; ++x, ++is.x, ++yt.x)
    00502     {
    00503         typename SrcIterator::column_iterator c1 = is.columnIterator();
    00504         typename TmpImageIterator::column_iterator ct = yt.columnIterator();
    00505
    00506         if(hnew < h)
    00507         {
    00508             recursiveSmoothLine(c1, c1 + h, sa,
    00509                  lt, line.accessor(), (double)h/hnew/scale);
    00510
    00511             resizeLineLinearInterpolation(lt, lt + h, line.accessor(),
    00512                                           ct, ct + hnew, tmp.accessor());
    00513         }
    00514         else
    00515         {
    00516             resizeLineLinearInterpolation(c1, c1 + h, sa,
    00517                                           ct, ct + hnew, tmp.accessor());
    00518         }
    00519     }
    00520
    00521     yt = tmp.upperLeft();
    00522
    00523     for(y=0; y < hnew; ++y, ++yt.y, ++id.y)
    00524     {
    00525         typename DestIterator::row_iterator rd = id.rowIterator();
    00526         typename TmpImageIterator::row_iterator rt = yt.rowIterator();
    00527
    00528         if(wnew < w)
    00529         {
    00530             recursiveSmoothLine(rt, rt + w, tmp.accessor(),
    00531                               lt, line.accessor(), (double)w/wnew/scale);
    00532
    00533             resizeLineLinearInterpolation(lt, lt + w, line.accessor(),
    00534                                           rd, rd + wnew, da);
    00535         }
    00536         else
    00537         {
    00538             resizeLineLinearInterpolation(rt, rt + w, tmp.accessor(),
    00539                                           rd, rd + wnew, da);
    00540         }
    00541     }
    00542 }
    00543
    00544 template <class SrcIterator, class SrcAccessor,
    00545           class DestIterator, class DestAccessor>
    00546 inline
    00547 void
    00548 resizeImageLinearInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00549                                triple<DestIterator, DestIterator, DestAccessor> dest)
    00550 {
    00551     resizeImageLinearInterpolation(src.first, src.second, src.third,
    00552                                    dest.first, dest.second, dest.third);
    00553 }
    00554
    00555 /***************************************************************/
    00556 /*                                                             */
    00557 /*                resizeImageSplineInterpolation               */
    00558 /*                                                             */
    00559 /***************************************************************/
    00560
    00561 /** \brief Resize image using B-spline interpolation.
    00562
    00563     The function implements separable spline interpolation algorithm described in
    00564
    00565     M. Unser, A. Aldroubi, M. Eden, <i>"B-Spline Signal Processing"</i>
    00566     IEEE Transactions on Signal Processing, vol. 41, no. 2, pp. 821-833 (part I),
    00567     pp. 834-848 (part II), 1993.
    00568
    00569     to obtain optimal interpolation quality and speed. You may pass the funcion
    00570     a spline of arbitrary order (e.g. <TT>BSpline&lt;ORDER, double&gt;</tt> or
    00571     <TT>CatmullRomSpline&lt;double&gt;</tt>). The default is a third order spline
    00572     which gives a twice continuously differentiable interpolant.
    00573     The implementation ensures that image values are interpolated rather
    00574     than smoothed by first calling a recursive (sharpening) prefilter as
    00575     described in the above paper. Then the actual interpolation is done
    00576     using \ref resamplingConvolveLine().
    00577
    00578     The range of both the input and output images (resp. regions)
    00579     must be given. The input image must have a size of at
    00580     least 4x4, the destination of at least 2x2. The scaling factors are then calculated
    00581     accordingly. If the source image is larger than the destination, it
    00582     is smoothed (band limited) using a recursive
    00583     exponential filter. The source value_type (SrcAccessor::value_type) must
    00584     be a linear algebra, i.e. it must support addition, subtraction,
    00585     and multiplication (+, -, *), multiplication with a scalar
    00586     real number and \ref NumericTraits "NumericTraits".
    00587     The function uses accessors.
    00588
    00589     <b> Declarations:</b>
    00590
    00591     pass arguments explicitly:
    00592     \code
    00593     namespace vigra {
    00594         template <class SrcImageIterator, class SrcAccessor,
    00595               class DestImageIterator, class DestAccessor,
    00596               class SPLINE>
    00597         void
    00598         resizeImageSplineInterpolation(
    00599               SrcImageIterator is, SrcImageIterator iend, SrcAccessor sa,
    00600           DestImageIterator id, DestImageIterator idend, DestAccessor da,
    00601           SPLINE spline = BSpline<3, double>())
    00602     }
    00603     \endcode
    00604
    00605
    00606     use argument objects in conjunction with \ref ArgumentObjectFactories:
    00607     \code
    00608     namespace vigra {
    00609         template <class SrcImageIterator, class SrcAccessor,
    00610               class DestImageIterator, class DestAccessor,
    00611               class SPLINE>
    00612         void
    00613         resizeImageSplineInterpolation(
    00614               triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    00615               triple<DestImageIterator, DestImageIterator, DestAccessor> dest,
    00616               SPLINE spline = BSpline<3, double>())
    00617     }
    00618     \endcode
    00619
    00620     <b> Usage:</b>
    00621
    00622         <b>\#include</b> "<a href="resizeimage_8hxx-source.html">vigra/resizeimage.hxx</a>"<br>
    00623         Namespace: vigra
    00624
    00625     \code
    00626     vigra::resizeImageSplineInterpolation(
    00627                src.upperLeft(), src.lowerRight(), src.accessor(),
    00628                dest.upperLeft(), dest.lowerRight(), dest.accessor());
    00629
    00630     \endcode
    00631
    00632     <b> Required Interface:</b>
    00633
    00634     \code
    00635     SrcImageIterator src_upperleft, src_lowerright;
    00636     DestImageIterator dest_upperleft, src_lowerright;
    00637
    00638     SrcAccessor src_accessor;
    00639     DestAccessor dest_accessor;
    00640
    00641     NumericTraits<SrcAccessor::value_type>::RealPromote
    00642                              u = src_accessor(src_upperleft),
    00643                  v = src_accessor(src_upperleft, 1);
    00644     double d;
    00645
    00646     u = d * v;
    00647     u = u + v;
    00648     u = u - v;
    00649     u = u * v;
    00650     u += v;
    00651     u -= v;
    00652
    00653     dest_accessor.set(
    00654         NumericTraits<DestAccessor::value_type>::fromRealPromote(u),
    00655     dest_upperleft);
    00656
    00657     \endcode
    00658
    00659     <b> Preconditions:</b>
    00660
    00661     \code
    00662     src_lowerright.x - src_upperleft.x > 3
    00663     src_lowerright.y - src_upperleft.y > 3
    00664     dest_lowerright.x - dest_upperleft.x > 1
    00665     dest_lowerright.y - dest_upperleft.y > 1
    00666     \endcode
    00667
    00668 */
    00669 template <class SrcIterator, class SrcAccessor,
    00670           class DestIterator, class DestAccessor,
    00671           class SPLINE>
    00672 void
    00673 resizeImageSplineInterpolation(
    00674     SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
    00675     DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc,
    00676     SPLINE const & spline)
    00677 {
    00678
    00679     int width_old = src_iter_end.x - src_iter.x;
    00680     int height_old = src_iter_end.y - src_iter.y;
    00681
    00682     int width_new = dest_iter_end.x - dest_iter.x;
    00683     int height_new = dest_iter_end.y - dest_iter.y;
    00684
    00685     vigra_precondition((width_old > 1) && (height_old > 1),
    00686                  "resizeImageSplineInterpolation(): "
    00687                  "Source image to small.\n");
    00688
    00689     vigra_precondition((width_new > 1) && (height_new > 1),
    00690                  "resizeImageSplineInterpolation(): "
    00691                  "Destination image to small.\n");
    00692
    00693     Rational<int> xratio(width_new - 1, width_old - 1);
    00694     Rational<int> yratio(height_new - 1, height_old - 1);
    00695     Rational<int> offset(0);
    00696     resampling_detail::MapTargetToSourceCoordinate xmapCoordinate(xratio, offset);
    00697     resampling_detail::MapTargetToSourceCoordinate ymapCoordinate(yratio, offset);
    00698     int xperiod = lcm(xratio.numerator(), xratio.denominator());
    00699     int yperiod = lcm(yratio.numerator(), yratio.denominator());
    00700
    00701     double const scale = 2.0;
    00702
    00703     typedef typename SrcAccessor::value_type SRCVT;
    00704     typedef typename NumericTraits<SRCVT>::RealPromote TMPTYPE;
    00705     typedef BasicImage<TMPTYPE> TmpImage;
    00706     typedef typename TmpImage::traverser TmpImageIterator;
    00707
    00708     BasicImage<TMPTYPE> tmp(width_old, height_new);
    00709
    00710     BasicImage<TMPTYPE> line((height_old > width_old) ? height_old : width_old, 1);
    00711     typename BasicImage<TMPTYPE>::Accessor tmp_acc = tmp.accessor();
    00712     ArrayVector<double> const & prefilterCoeffs = spline.prefilterCoefficients();
    00713
    00714     int x,y;
    00715
    00716     ArrayVector<Kernel1D<double> > kernels(yperiod);
    00717     createResamplingKernels(spline, ymapCoordinate, kernels);
    00718
    00719     typename BasicImage<TMPTYPE>::Iterator y_tmp = tmp.upperLeft();
    00720     typename TmpImageIterator::row_iterator line_tmp = line.upperLeft().rowIterator();
    00721
    00722     for(x=0; x<width_old; ++x, ++src_iter.x, ++y_tmp.x)
    00723     {
    00724
    00725         typename SrcIterator::column_iterator c_src = src_iter.columnIterator();
    00726         typename TmpImageIterator::column_iterator c_tmp = y_tmp.columnIterator();
    00727
    00728         if(prefilterCoeffs.size() == 0)
    00729         {
    00730             if(height_new >= height_old)
    00731             {
    00732                 resamplingConvolveLine(c_src, c_src + height_old, src_acc,
    00733                                        c_tmp, c_tmp + height_new, tmp_acc,
    00734                                        kernels, ymapCoordinate);
    00735             }
    00736             else
    00737             {
    00738                 recursiveSmoothLine(c_src, c_src + height_old, src_acc,
    00739                      line_tmp, line.accessor(), (double)height_old/height_new/scale);
    00740                 resamplingConvolveLine(line_tmp, line_tmp + height_old, line.accessor(),
    00741                                        c_tmp, c_tmp + height_new, tmp_acc,
    00742                                        kernels, ymapCoordinate);
    00743             }
    00744         }
    00745         else
    00746         {
    00747             recursiveFilterLine(c_src, c_src + height_old, src_acc,
    00748                                 line_tmp, line.accessor(),
    00749                                 prefilterCoeffs[0], BORDER_TREATMENT_REFLECT);
    00750             for(unsigned int b = 1; b < prefilterCoeffs.size(); ++b)
    00751             {
    00752                 recursiveFilterLine(line_tmp, line_tmp + height_old, line.accessor(),
    00753                                     line_tmp, line.accessor(),
    00754                                     prefilterCoeffs[b], BORDER_TREATMENT_REFLECT);
    00755             }
    00756             if(height_new < height_old)
    00757             {
    00758                 recursiveSmoothLine(line_tmp, line_tmp + height_old, line.accessor(),
    00759                      line_tmp, line.accessor(), (double)height_old/height_new/scale);
    00760             }
    00761             resamplingConvolveLine(line_tmp, line_tmp + height_old, line.accessor(),
    00762                                    c_tmp, c_tmp + height_new, tmp_acc,
    00763                                    kernels, ymapCoordinate);
    00764         }
    00765     }
    00766
    00767     y_tmp = tmp.upperLeft();
    00768
    00769     DestIterator dest = dest_iter;
    00770
    00771     kernels.resize(xperiod);
    00772     createResamplingKernels(spline, xmapCoordinate, kernels);
    00773
    00774     for(y=0; y < height_new; ++y, ++y_tmp.y, ++dest_iter.y)
    00775     {
    00776         typename DestIterator::row_iterator r_dest = dest_iter.rowIterator();
    00777         typename TmpImageIterator::row_iterator r_tmp = y_tmp.rowIterator();
    00778
    00779         if(prefilterCoeffs.size() == 0)
    00780         {
    00781             if(width_new >= width_old)
    00782             {
    00783                 resamplingConvolveLine(r_tmp, r_tmp + width_old, tmp.accessor(),
    00784                                        r_dest, r_dest + width_new, dest_acc,
    00785                                        kernels, xmapCoordinate);
    00786             }
    00787             else
    00788             {
    00789                 recursiveSmoothLine(r_tmp, r_tmp + width_old, tmp.accessor(),
    00790                                   line_tmp, line.accessor(), (double)width_old/width_new/scale);
    00791                 resamplingConvolveLine(line_tmp, line_tmp + width_old, line.accessor(),
    00792                                        r_dest, r_dest + width_new, dest_acc,
    00793                                        kernels, xmapCoordinate);
    00794             }
    00795         }
    00796         else
    00797         {
    00798             recursiveFilterLine(r_tmp, r_tmp + width_old, tmp.accessor(),
    00799                                 line_tmp, line.accessor(),
    00800                                 prefilterCoeffs[0], BORDER_TREATMENT_REFLECT);
    00801             for(unsigned int b = 1; b < prefilterCoeffs.size(); ++b)
    00802             {
    00803                 recursiveFilterLine(line_tmp, line_tmp + width_old, line.accessor(),
    00804                                     line_tmp, line.accessor(),
    00805                                     prefilterCoeffs[b], BORDER_TREATMENT_REFLECT);
    00806             }
    00807             if(width_new < width_old)
    00808             {
    00809                 recursiveSmoothLine(line_tmp, line_tmp + width_old, line.accessor(),
    00810                                     line_tmp, line.accessor(), (double)width_old/width_new/scale);
    00811             }
    00812             resamplingConvolveLine(line_tmp, line_tmp + width_old, line.accessor(),
    00813                                    r_dest, r_dest + width_new, dest_acc,
    00814                                    kernels, xmapCoordinate);
    00815         }
    00816     }
    00817 }
    00818
    00819 template <class SrcIterator, class SrcAccessor,
    00820           class DestIterator, class DestAccessor,
    00821           class SPLINE>
    00822 inline
    00823 void
    00824 resizeImageSplineInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00825                       triple<DestIterator, DestIterator, DestAccessor> dest,
    00826                       SPLINE const & spline)
    00827 {
    00828     resizeImageSplineInterpolation(src.first, src.second, src.third,
    00829                                    dest.first, dest.second, dest.third, spline);
    00830 }
    00831
    00832 template <class SrcIterator, class SrcAccessor,
    00833           class DestIterator, class DestAccessor>
    00834 void
    00835 resizeImageSplineInterpolation(SrcIterator is, SrcIterator iend, SrcAccessor sa,
    00836                       DestIterator id, DestIterator idend, DestAccessor da)
    00837 {
    00838     resizeImageSplineInterpolation(is, iend, sa, id, idend, da, BSpline<3, double>());
    00839 }
    00840
    00841 template <class SrcIterator, class SrcAccessor,
    00842           class DestIterator, class DestAccessor>
    00843 inline
    00844 void
    00845 resizeImageSplineInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00846                       triple<DestIterator, DestIterator, DestAccessor> dest)
    00847 {
    00848     resizeImageSplineInterpolation(src.first, src.second, src.third,
    00849                                    dest.first, dest.second, dest.third);
    00850 }
    00851
    00852 /*****************************************************************/
    00853 /*                                                               */
    00854 /*              resizeImageCatmullRomInterpolation               */
    00855 /*                                                               */
    00856 /*****************************************************************/
    00857
    00858 /** \brief Resize image using the Catmull/Rom interpolation function.
    00859
    00860     The function calls like \ref resizeImageSplineInterpolation() with
    00861     \ref vigra::CatmullRomSpline as an interpolation kernel.
    00862     The interpolated function has one continuous derivative.
    00863     (See \ref resizeImageSplineInterpolation() for more documentation)
    00864
    00865     <b> Declarations:</b>
    00866
    00867     pass arguments explicitly:
    00868     \code
    00869     namespace vigra {
    00870         template <class SrcIterator, class SrcAccessor,
    00871                   class DestIterator, class DestAccessor>
    00872         void
    00873         resizeImageCatmullRomInterpolation(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
    00874                               DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc);
    00875     }
    00876     \endcode
    00877
    00878
    00879     use argument objects in conjunction with \ref ArgumentObjectFactories:
    00880     \code
    00881     namespace vigra {
    00882         template <class SrcIterator, class SrcAccessor,
    00883                   class DestIterator, class DestAccessor>
    00884         void
    00885         resizeImageCatmullRomInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00886                               triple<DestIterator, DestIterator, DestAccessor> dest);
    00887     }
    00888     \endcode
    00889
    00890
    00891     <b>\#include</b> "<a href="resizeimage_8hxx-source.html">vigra/resizeimage.hxx</a>"<br>
    00892     Namespace: vigra
    00893
    00894 */
    00895 template <class SrcIterator, class SrcAccessor,
    00896           class DestIterator, class DestAccessor>
    00897 void
    00898 resizeImageCatmullRomInterpolation(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
    00899                       DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc)
    00900 {
    00901     resizeImageSplineInterpolation(src_iter, src_iter_end, src_acc, dest_iter, dest_iter_end, dest_acc,
    00902                                   CatmullRomSpline<double>());
    00903 }
    00904
    00905 template <class SrcIterator, class SrcAccessor,
    00906           class DestIterator, class DestAccessor>
    00907 inline
    00908 void
    00909 resizeImageCatmullRomInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00910                       triple<DestIterator, DestIterator, DestAccessor> dest)
    00911 {
    00912     resizeImageCatmullRomInterpolation(src.first, src.second, src.third,
    00913                                      dest.first, dest.second, dest.third);
    00914 }
    00915
    00916 #if 0
    00917 /*****************************************************************/
    00918 /*                                                               */
    00919 /*              resizeImageCubicInterpolation                    */
    00920 /*                                                               */
    00921 /*****************************************************************/
    00922
    00923 /** \brief Resize image using the cardinal B-spline interpolation function.
    00924
    00925     The function calls like \ref resizeImageSplineInterpolation() with
    00926     \ref vigra::BSpline<3, double> and prefiltering as an interpolation kernel.
    00927     The interpolated function has two continuous derivatives.
    00928     (See \ref resizeImageSplineInterpolation() for more documentation)
    00929
    00930     <b>\#include</b> "<a href="resizeimage_8hxx-source.html">vigra/resizeimage.hxx</a>"<br>
    00931     Namespace: vigra
    00932
    00933 */
    00934 template <class SrcIterator, class SrcAccessor,
    00935           class DestIterator, class DestAccessor>
    00936 void
    00937 resizeImageCubicInterpolation(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
    00938                       DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc)
    00939 {
    00940     resizeImageSplineInterpolation(src_iter, src_iter_end, src_acc, dest_iter, dest_iter_end, dest_acc,
    00941                                   BSpline<3, double>());
    00942 }
    00943
    00944 template <class SrcIterator, class SrcAccessor,
    00945           class DestIterator, class DestAccessor>
    00946 inline
    00947 void
    00948 resizeImageCubicInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00949                       triple<DestIterator, DestIterator, DestAccessor> dest)
    00950 {
    00951     resizeImageCubicInterpolation(src.first, src.second, src.third,
    00952                                    dest.first, dest.second, dest.third);
    00953 }
    00954 #endif
    00955
    00956 /*****************************************************************/
    00957 /*                                                               */
    00958 /*              resizeImageCoscotInterpolation                   */
    00959 /*                                                               */
    00960 /*****************************************************************/
    00961
    00962 /** \brief Resize image using the Coscot interpolation function.
    00963
    00964     The function calls \ref resizeImageSplineInterpolation() with
    00965     \ref vigra::CoscotFunction as an interpolation kernel.
    00966     The interpolated function has one continuous derivative.
    00967     (See \ref resizeImageSplineInterpolation() for more documentation)
    00968
    00969     <b> Declarations:</b>
    00970
    00971     pass arguments explicitly:
    00972     \code
    00973     namespace vigra {
    00974         template <class SrcIterator, class SrcAccessor,
    00975                   class DestIterator, class DestAccessor>
    00976         void
    00977         resizeImageCoscotInterpolation(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
    00978                               DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc);
    00979     }
    00980     \endcode
    00981
    00982
    00983     use argument objects in conjunction with \ref ArgumentObjectFactories:
    00984     \code
    00985     namespace vigra {
    00986         template <class SrcIterator, class SrcAccessor,
    00987                   class DestIterator, class DestAccessor>
    00988         void
    00989         resizeImageCoscotInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00990                               triple<DestIterator, DestIterator, DestAccessor> dest);
    00991     }
    00992     \endcode
    00993
    00994
    00995     <b>\#include</b> "<a href="resizeimage_8hxx-source.html">vigra/resizeimage.hxx</a>"<br>
    00996     Namespace: vigra
    00997
    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 (koethe@informatik.uni-hamburg.de) Cognitive Systems Group, University of Hamburg, Germany | html generated using doxygen and Python VIGRA 1.5.0 (7 Dec 2006)