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

details vigra/resizeimage.hxx VIGRA

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