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

details vigra/resizeimage.hxx VIGRA

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.3, Aug 18 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.3 (18 Aug 2005)