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