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