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