[ 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.4.0, Dec 21 2005 )                                    */
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 "vigra/utilities.hxx"
00044 #include "vigra/numerictraits.hxx"
00045 #include "vigra/stdimage.hxx"
00046 #include "vigra/recursiveconvolution.hxx"
00047 #include "vigra/separableconvolution.hxx"
00048 #include "vigra/resampling_convolution.hxx"
00049 #include "vigra/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.4.0 (21 Dec 2005)