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