00001
00027 #ifndef VIGRA_EXT_INTERPOLATORS_H
00028 #define VIGRA_EXT_INTERPOLATORS_H
00029
00030 #include <iostream>
00031 #include <iomanip>
00032
00033 #include <math.h>
00034 #include <hugin_math/hugin_math.h>
00035 #include <algorithm>
00036
00037 #include <vigra/accessor.hxx>
00038 #include <vigra/diff2d.hxx>
00039
00040 using std::endl;
00041
00042 namespace vigra_ext {
00043
00044
00045
00046 static double sinc ( double x );
00047 static double cubic01 ( double x );
00048 static double cubic12 ( double x );
00049
00050 static double sinc( double x )
00051 {
00052 x *= M_PI;
00053 if(x != 0.0)
00054 return(sin(x) / x);
00055 return(1.0);
00056 }
00057
00058
00059
00060
00061
00062 static const double A(-0.75);
00063
00064
00065 static double cubic01( double x )
00066 {
00067 return (( A + 2.0 )*x - ( A + 3.0 ))*x*x +1.0;
00068 }
00069
00070
00071 static double cubic12( double x )
00072 {
00073 return (( A * x - 5.0 * A ) * x + 8.0 * A ) * x - 4.0 * A;
00074
00075 }
00076
00078 enum Interpolator {
00079 INTERP_CUBIC = 0,
00080 INTERP_SPLINE_16,
00081 INTERP_SPLINE_36,
00082 INTERP_SINC_256,
00083 INTERP_SPLINE_64,
00084 INTERP_BILINEAR,
00085 INTERP_NEAREST_NEIGHBOUR,
00086 INTERP_SINC_1024
00087 };
00088
00089
00096 struct interp_nearest
00097 {
00098
00099 static const int size = 2;
00100
00101 void calc_coeff(double x, double * w) const
00102 {
00103 w[1] = (x >= 0.5) ? 1 : 0;
00104 w[0] = (x < 0.5) ? 1 : 0;
00105 }
00106
00107 void emitGLSL(std::ostringstream& oss) const {
00108 oss << " return (i == 0.0) ? float(f < 0.5) : float(f >= 0.5);" << endl;
00109 }
00110 };
00111
00112
00114 struct interp_bilin
00115 {
00116
00117 static const int size = 2;
00118
00119 void calc_coeff(double x, double * w) const
00120 {
00121 w[1] = x;
00122 w[0] = 1.0-x;
00123 }
00124
00125 void emitGLSL(std::ostringstream& oss) const {
00126 oss << " return abs(i + f - 1.0);" << endl;
00127 }
00128 };
00129
00131 struct interp_cubic
00132 {
00133
00134 static const int size = 4;
00135
00137 void calc_coeff(double x, double * w) const
00138 {
00139 w[3] = cubic12( 2.0 - x );
00140 w[2] = cubic01( 1.0 - x );
00141 w[1] = cubic01( x );
00142 w[0] = cubic12( x + 1.0 );
00143 }
00144
00145 void emitGLSL(std::ostringstream& oss) const {
00146 oss << " float A = " << A << ";" << endl
00147 << " float c = abs(i - 1.0);" << endl
00148 << " float m = (i > 1.0) ? -1.0 : 1.0;" << endl
00149 << " float p = c + m * f;" << endl
00150 << " if (i == 1.0 || i == 2.0) {" << endl
00151 << " return (( A + 2.0 )*p - ( A + 3.0 ))*p*p + 1.0;" << endl
00152 << " } else {" << endl
00153 << " return (( A * p - 5.0 * A ) * p + 8.0 * A ) * p - 4.0 * A;" << endl
00154 << " }" << endl;
00155 }
00156 };
00157
00159 struct interp_spline16
00160 {
00161
00162 static const int size = 4;
00163
00165 void calc_coeff(double x, double * w) const
00166 {
00167 w[3] = ( ( 1.0/3.0 * x - 1.0/5.0 ) * x - 2.0/15.0 ) * x;
00168 w[2] = ( ( 6.0/5.0 - x ) * x + 4.0/5.0 ) * x;
00169 w[1] = ( ( x - 9.0/5.0 ) * x - 1.0/5.0 ) * x + 1.0;
00170 w[0] = ( ( -1.0/3.0 * x + 4.0/5.0 ) * x - 7.0/15.0 ) * x;
00171 }
00172
00173 void emitGLSL(std::ostringstream& oss) const {
00174 oss << " return (i > 1.0) ? (i == 3.0) ? (( ( 1.0/3.0 * f - 1.0/5.0 ) * f - 2.0/15.0 ) * f)" << endl
00175 << " : (( ( 6.0/5.0 - f ) * f + 4.0/5.0 ) * f)" << endl
00176 << " : (i == 1.0) ? (( ( f - 9.0/5.0 ) * f - 1.0/5.0 ) * f + 1.0)" << endl
00177 << " : (( ( -1.0/3.0 * f + 4.0/5.0 ) * f - 7.0/15.0 ) * f);" << endl;
00178 }
00179 };
00180
00182 struct interp_spline36
00183 {
00184
00185 static const int size = 6;
00186
00193 void calc_coeff(double x, double* w) const
00194 {
00195 w[5] = ( ( - 1.0/11.0 * x + 12.0/ 209.0 ) * x + 7.0/ 209.0 ) * x;
00196 w[4] = ( ( 6.0/11.0 * x - 72.0/ 209.0 ) * x - 42.0/ 209.0 ) * x;
00197 w[3] = ( ( - 13.0/11.0 * x + 288.0/ 209.0 ) * x + 168.0/ 209.0 ) * x;
00198 w[2] = ( ( 13.0/11.0 * x - 453.0/ 209.0 ) * x - 3.0/ 209.0 ) * x + 1.0;
00199 w[1] = ( ( - 6.0/11.0 * x + 270.0/ 209.0 ) * x - 156.0/ 209.0 ) * x;
00200 w[0] = ( ( 1.0/11.0 * x - 45.0/ 209.0 ) * x + 26.0/ 209.0 ) * x;
00201 }
00202
00203 void emitGLSL(std::ostringstream& oss) const {
00204 oss << " return (i > 3.0) ? (i == 5.0) ? (( ( - 1.0/11.0 * f + 12.0/ 209.0 ) * f + 7.0/ 209.0 ) * f)" << endl
00205 << " : (( ( 6.0/11.0 * f - 72.0/ 209.0 ) * f - 42.0/ 209.0 ) * f)" << endl
00206 << " : (i > 1.0) ? (i == 3.0) ? (( ( - 13.0/11.0 * f + 288.0/ 209.0 ) * f + 168.0/ 209.0 ) * f)" << endl
00207 << " : (( ( 13.0/11.0 * f - 453.0/ 209.0 ) * f - 3.0/ 209.0 ) * f + 1.0)" << endl
00208 << " : (i == 1.0) ? (( ( - 6.0/11.0 * f + 270.0/ 209.0 ) * f - 156.0/ 209.0 ) * f)" << endl
00209 << " : (( ( 1.0/11.0 * f - 45.0/ 209.0 ) * f + 26.0/ 209.0 ) * f);" << endl;
00210 }
00211 };
00212
00213
00215 struct interp_spline64
00216 {
00217
00218 static const int size = 8;
00219
00221 void calc_coeff(double x, double * w) const
00222 {
00223 w[7] = (( 1.0/41.0 * x - 45.0/2911.0) * x - 26.0/2911.0) * x;
00224 w[6] = ((- 6.0/41.0 * x + 270.0/2911.0) * x + 156.0/2911.0) * x;
00225 w[5] = (( 24.0/41.0 * x - 1080.0/2911.0) * x - 624.0/2911.0) * x;
00226 w[4] = ((-49.0/41.0 * x + 4050.0/2911.0) * x + 2340.0/2911.0) * x;
00227 w[3] = (( 49.0/41.0 * x - 6387.0/2911.0) * x - 3.0/2911.0) * x + 1.0;
00228 w[2] = ((-24.0/41.0 * x + 4032.0/2911.0) * x - 2328.0/2911.0) * x;
00229 w[1] = (( 6.0/41.0 * x - 1008.0/2911.0) * x + 582.0/2911.0) * x;
00230 w[0] = ((- 1.0/41.0 * x + 168.0/2911.0) * x - 97.0/2911.0) * x;
00231 }
00232
00233 void emitGLSL(std::ostringstream& oss) const {
00234 oss << " return (i > 3.0) ? (i > 5.0) ? (i == 7.0) ? ((( 1.0/41.0 * f - 45.0/2911.0) * f - 26.0/2911.0) * f)" << endl
00235 << " : (((- 6.0/41.0 * f + 270.0/2911.0) * f + 156.0/2911.0) * f)" << endl
00236 << " : (i == 5.0) ? ((( 24.0/41.0 * f - 1080.0/2911.0) * f - 624.0/2911.0) * f)" << endl
00237 << " : (((-49.0/41.0 * f + 4050.0/2911.0) * f + 2340.0/2911.0) * f)" << endl
00238 << " : (i > 1.0) ? (i == 3.0) ? ((( 49.0/41.0 * f - 6387.0/2911.0) * f - 3.0/2911.0) * f + 1.0)" << endl
00239 << " : (((-24.0/41.0 * f + 4032.0/2911.0) * f - 2328.0/2911.0) * f)" << endl
00240 << " : (i == 1.0) ? ((( 6.0/41.0 * f - 1008.0/2911.0) * f + 582.0/2911.0) * f)" << endl
00241 << " : (((- 1.0/41.0 * f + 168.0/2911.0) * f - 97.0/2911.0) * f);" << endl;
00242 }
00243 };
00244
00246 template <int size_>
00247 struct interp_sinc
00248 {
00249
00250 static const int size = size_;
00251
00253 void calc_coeff(double x, double * w) const
00254 {
00255 int idx;
00256 double xadd;
00257 for( idx = 0, xadd = size / 2 - 1.0 + x;
00258 idx < size / 2;
00259 xadd-=1.0)
00260 {
00261 w[idx++] = sinc( xadd ) * sinc( xadd / ( size / 2 ));
00262 }
00263 for( xadd = 1.0 - x;
00264 idx < size;
00265 xadd+=1.0)
00266 {
00267 w[idx++] = sinc( xadd ) * sinc( xadd / ( size / 2 ));
00268 }
00269 }
00270
00271 void emitGLSL(std::ostringstream& oss) const {
00272 oss << " float c = (i < " << (size/2.0) << ") ? 1.0 : -1.0;" << endl
00273 << " float x = c * (" << (size/2 - 1.0) << " - i + f);" << endl
00274 << " vec2 xpi = vec2(x, x / " << (size/2.0) << ") * " << M_PI << ";" << endl
00275 << " vec2 xsin = sin(xpi);" << endl
00276 << " vec2 result = vec2(1.0, 1.0);" << endl
00277 << " if (xpi.x != 0.0) result.x = xsin.x / xpi.x;" << endl
00278 << " if (xpi.y != 0.0) result.y = xsin.y / xpi.y;" << endl
00279 << " return result.x * result.y;" << endl;
00280 }
00281 };
00282
00283
00288 template <typename SrcImageIterator, typename SrcAccessor,
00289 typename INTERPOLATOR>
00290 class ImageInterpolator
00291 {
00292 public:
00293 typedef typename SrcAccessor::value_type PixelType;
00294
00295 typedef typename vigra::UInt8 MaskType;
00296 private:
00297 typedef typename vigra::NumericTraits<PixelType>::RealPromote RealPixelType;
00298
00299 SrcImageIterator m_sIter;
00300 SrcAccessor m_sAcc;
00301 int m_w;
00302 int m_h;
00303 bool m_warparound;
00304
00305 INTERPOLATOR m_inter;
00306
00307 public:
00309 ImageInterpolator(vigra::triple<SrcImageIterator, SrcImageIterator,SrcAccessor> const & src,
00310 INTERPOLATOR & inter,
00311 bool warparound)
00312 : m_sIter(src.first),
00313 m_sAcc(src.third),
00314 m_w(src.second.x - src.first.x),
00315 m_h(src.second.y - src.first.y),
00316 m_warparound(warparound),
00317 m_inter(inter)
00318 {
00319 }
00320
00324 ImageInterpolator(SrcImageIterator src_upperleft,
00325 SrcImageIterator src_lowerright,
00326 SrcAccessor sa,
00327 INTERPOLATOR & inter,
00328 bool warparound)
00329 : m_sIter(src_upperleft),
00330 m_sAcc(sa),
00331 m_w(src_lowerright.x - src_upperleft.x),
00332 m_h(src_lowerright.y - src_upperleft.y),
00333 m_warparound(warparound),
00334 m_inter(inter)
00335 {
00336 }
00337
00339 bool operator()(double x, double y,
00340 PixelType & result, MaskType & mask) const
00341 {
00342 mask = 255;
00343 return operator()(x,y, result);
00344 }
00345
00347 bool operator()(double x, double y,
00348 PixelType & result) const
00349 {
00350
00351
00352 if (x < -INTERPOLATOR::size/2 || x > m_w + INTERPOLATOR::size/2) return false;
00353 if (y < -INTERPOLATOR::size/2 || y > m_h + INTERPOLATOR::size/2) return false;
00354
00355 double t = floor(x);
00356 double dx = x - t;
00357 int srcx = int(t);
00358 t = floor(y);
00359 double dy = y - t;
00360 int srcy = int(t);
00361
00362 if ( srcx > INTERPOLATOR::size/2 && srcx < m_w -INTERPOLATOR::size/2 &&
00363 srcy > INTERPOLATOR::size/2 && srcy < m_h - INTERPOLATOR::size/2)
00364 {
00365 return interpolateNoMaskInside(srcx, srcy, dx, dy, result);
00366 }
00367
00368 double wx[INTERPOLATOR::size];
00369 double wy[INTERPOLATOR::size];
00370
00371
00372 m_inter.calc_coeff(dx, wx);
00373 m_inter.calc_coeff(dy, wy);
00374
00375 RealPixelType p(vigra::NumericTraits<RealPixelType>::zero());
00376 double weightsum = 0.0;
00377 for (int ky = 0; ky < INTERPOLATOR::size; ky++) {
00378 int bounded_ky = srcy + 1 + ky - INTERPOLATOR::size/2;
00379
00380
00381 if (bounded_ky < 0 || bounded_ky >= m_h) {
00382 continue;
00383 }
00384
00385 for (int kx = 0; kx < INTERPOLATOR::size; kx++) {
00386 int bounded_kx = srcx + 1 + kx - INTERPOLATOR::size/2;
00387
00388 if (m_warparound) {
00389
00390 if (bounded_kx < 0)
00391 bounded_kx += m_w;
00392 if (bounded_kx >= m_w)
00393 bounded_kx -= m_w;
00394 } else {
00395
00396
00397
00398
00399 if (bounded_kx < 0)
00400 continue;
00401 if (bounded_kx >= m_w)
00402 continue;
00403 }
00404
00405
00406 double f = wx[kx]*wy[ky];
00407 p += f * m_sAcc(m_sIter, vigra::Diff2D(bounded_kx, bounded_ky));
00408 weightsum += f;
00409 }
00410 }
00411
00412
00413 if (weightsum <= 0.2) return false;
00414
00415 if (weightsum != 1.0) p /= weightsum;
00416
00417 result = vigra::detail::RequiresExplicitCast<PixelType>::cast(p);
00418 return true;
00419 }
00420
00421
00423 bool interpolateNoMaskInside(int srcx, int srcy, double dx, double dy,
00424 PixelType & result) const
00425 {
00426 double w[INTERPOLATOR::size];
00427 RealPixelType resX[INTERPOLATOR::size];
00428
00429
00430 m_inter.calc_coeff(dx, w);
00431
00432 RealPixelType p;
00433
00434
00435 vigra::Diff2D offset(srcx - INTERPOLATOR::size/2 + 1,
00436 srcy - INTERPOLATOR::size/2 + 1);
00437 SrcImageIterator ys(m_sIter + offset);
00438 for (int ky = 0; ky < INTERPOLATOR::size; ky++, ++(ys.y)) {
00439 p = vigra::NumericTraits<RealPixelType>::zero();
00440 typename SrcImageIterator::row_iterator xs(ys.rowIterator());
00441
00442 for (int kx = 0; kx < INTERPOLATOR::size; kx++, ++xs) {
00443 p += w[kx] * m_sAcc(xs);
00444 }
00445 resX[ky] = p;
00446 }
00447
00448
00449 m_inter.calc_coeff(dy, w);
00450 p = vigra::NumericTraits<RealPixelType>::zero();
00451 for (int ky = 0; ky < INTERPOLATOR::size; ky++) {
00452 p += w[ky] * resX[ky];
00453 }
00454
00455 result = vigra::detail::RequiresExplicitCast<PixelType>::cast(p);
00456 return true;
00457 }
00458
00459 void emitGLSL(std::ostringstream& oss) const {
00460 m_inter.emitGLSL(oss);
00461 }
00462
00463 };
00464
00465
00471 template <typename SrcImageIterator, typename SrcAccessor,
00472 typename MaskIterator, typename MaskAccessor,
00473 typename INTERPOLATOR>
00474 class ImageMaskInterpolator
00475 {
00476 public:
00477 typedef typename SrcAccessor::value_type PixelType;
00478 typedef typename MaskAccessor::value_type MaskType;
00479 private:
00480 typedef typename vigra::NumericTraits<PixelType>::RealPromote RealPixelType;
00481
00482 SrcImageIterator m_sIter;
00483 SrcAccessor m_sAcc;
00484 MaskIterator m_mIter;
00485 MaskAccessor m_mAcc;
00486 int m_w;
00487 int m_h;
00488 bool m_warparound;
00489
00490 INTERPOLATOR m_inter;
00491
00492 public:
00493
00495 ImageMaskInterpolator(vigra::triple<SrcImageIterator, SrcImageIterator,SrcAccessor> const & src,
00496 std::pair<MaskIterator, MaskAccessor> mask,
00497 INTERPOLATOR & inter,
00498 bool warparound)
00499 : m_sIter(src.first),
00500 m_sAcc(src.third),
00501 m_mIter(mask.first),
00502 m_mAcc(mask.second),
00503 m_w(src.second.x - src.first.x),
00504 m_h(src.second.y - src.first.y),
00505 m_warparound(warparound),
00506 m_inter(inter)
00507 {
00508 }
00509
00513 ImageMaskInterpolator(SrcImageIterator src_upperleft,
00514 SrcImageIterator src_lowerright,
00515 SrcAccessor sa,
00516 MaskIterator mask_upperleft,
00517 MaskAccessor ma,
00518 INTERPOLATOR & inter,
00519 bool warparound)
00520 : m_sIter(src_upperleft),
00521 m_sAcc(sa),
00522 m_mIter(mask_upperleft),
00523 m_mAcc(ma),
00524 m_w(src_lowerright.x - src_upperleft.x),
00525 m_h(src_lowerright.y - src_upperleft.y),
00526 m_warparound(warparound),
00527 m_inter(inter)
00528 {
00529 }
00530 #if 0
00531
00550
00551
00552 bool interpolateSeperable(float x, float y,
00553 PixelType & result) const
00554 {
00555
00556
00557 if (x < -INTERPOLATOR::size/2 || x > m_w + INTERPOLATOR::size/2) return false;
00558 if (y < -INTERPOLATOR::size/2 || y > m_h + INTERPOLATOR::size/2) return false;
00559
00560 double t = floor(x);
00561 double dx = x - t;
00562 int srcx = int(t);
00563 t = floor(y);
00564 double dy = y - t;
00565 int srcy = int(t);
00566
00567
00568 double w[INTERPOLATOR::size];
00569
00570 double weightsX[INTERPOLATOR::size];
00571 PixelType resX[INTERPOLATOR::size];
00572
00573
00574 m_inter.calc_coeff(dx, w);
00575
00576
00577
00578 for (int ky = 0; ky < INTERPOLATOR::size; ky++) {
00579 int bounded_ky = srcy + 1 + ky - INTERPOLATOR::size/2;
00580
00581
00582
00583
00584
00585
00586 if (bounded_ky < 0 || bounded_ky >= m_h) {
00587 weightsX[ky] = 0;
00588 resX[ky] = 0;
00589 continue;
00590 }
00591
00592 RealPixelType p(vigra::NumericTraits<RealPixelType>::zero());
00593 double weightsum = 0.0;
00594
00595 for (int kx = 0; kx < INTERPOLATOR::size; kx++) {
00596 int bounded_kx = srcx + 1 + kx - INTERPOLATOR::size/2;
00597
00598 if (m_warparound) {
00599
00600 if (bounded_kx < 0)
00601 bounded_kx += m_w;
00602 if (bounded_kx >= m_w)
00603 bounded_kx -= m_w;
00604 } else {
00605
00606
00607
00608
00609 if (bounded_kx < 0)
00610 continue;
00611 if (bounded_kx >= m_w)
00612 continue;
00613 }
00614 if (m_mIter(bounded_kx, bounded_ky)) {
00615
00616 p += w[kx] * m_sIter(bounded_kx, bounded_ky);
00617 weightsum += w[kx];
00618 }
00619 }
00620 weightsX[ky] = weightsum;
00621 resX[ky] = p;
00622 }
00623
00624
00625 m_inter.calc_coeff(dy, w);
00626 RealPixelType p(vigra::NumericTraits<RealPixelType>::zero());
00627 double weightsum = 0.0;
00628 for (int ky = 0; ky < INTERPOLATOR::size; ky++) {
00629 weightsum += weightsX[ky] * w[ky];
00630 p += w[ky] * resX[ky];
00631 }
00632
00633 if (weightsum == 0.0) return false;
00634
00635 if (weightsum != 1.0) p /= weightsum;
00636
00637 result = vigra::detail::RequiresExplicitCast<PixelType>::cast(p);
00638 return true;
00639 }
00640 #endif
00641
00661 bool operator()(double x, double y,
00662 PixelType & result, MaskType & mask) const
00663 {
00664
00665
00666 if (x < -INTERPOLATOR::size/2 || x > m_w + INTERPOLATOR::size/2) return false;
00667 if (y < -INTERPOLATOR::size/2 || y > m_h + INTERPOLATOR::size/2) return false;
00668
00669 double t = floor(x);
00670 double dx = x - t;
00671 int srcx = int(t);
00672 t = floor(y);
00673 double dy = y - t;
00674 int srcy = int(t);
00675
00676 if ( srcx > INTERPOLATOR::size/2 && srcx < m_w -INTERPOLATOR::size/2 &&
00677 srcy > INTERPOLATOR::size/2 && srcy < m_h - INTERPOLATOR::size/2)
00678 {
00679 return interpolateInside(srcx, srcy, dx, dy, result, mask);
00680 }
00681
00682 double wx[INTERPOLATOR::size];
00683 double wy[INTERPOLATOR::size];
00684
00685
00686 m_inter.calc_coeff(dx, wx);
00687 m_inter.calc_coeff(dy, wy);
00688
00689
00690
00691 RealPixelType p(vigra::NumericTraits<RealPixelType>::zero());
00692 double m = 0;
00693 double weightsum = 0.0;
00694 for (int ky = 0; ky < INTERPOLATOR::size; ky++) {
00695 int bounded_ky = srcy + 1 + ky - INTERPOLATOR::size/2;
00696
00697
00698 if (bounded_ky < 0 || bounded_ky >= m_h) {
00699 continue;
00700 }
00701
00702 for (int kx = 0; kx < INTERPOLATOR::size; kx++) {
00703 int bounded_kx = srcx + 1 + kx - INTERPOLATOR::size/2;
00704
00705 if (m_warparound) {
00706
00707 if (bounded_kx < 0)
00708 bounded_kx += m_w;
00709 if (bounded_kx >= m_w)
00710 bounded_kx -= m_w;
00711 } else {
00712
00713
00714
00715
00716 if (bounded_kx < 0)
00717 continue;
00718 if (bounded_kx >= m_w)
00719 continue;
00720 }
00721
00722 MaskType cmask = m_mIter(bounded_kx, bounded_ky);
00723 if (cmask) {
00724
00725 double f = wx[kx]*wy[ky];
00726
00727 m += f * cmask;
00728 p += f * m_sAcc(m_sIter, vigra::Diff2D(bounded_kx, bounded_ky));
00729 weightsum += f;
00730 }
00731 }
00732 }
00733
00734
00735 if (weightsum <= 0.2) return false;
00736
00737 if (weightsum != 1.0) {
00738 p /= weightsum;
00739 m /= weightsum;
00740 }
00741
00742 mask = vigra::detail::RequiresExplicitCast<MaskType>::cast(m);
00743 result = vigra::detail::RequiresExplicitCast<PixelType>::cast(p);
00744 return true;
00745 }
00746
00747
00749 bool interpolateInside(int srcx, int srcy, double dx, double dy,
00750 PixelType & result, MaskType & mask) const
00751 {
00752
00753 double wx[INTERPOLATOR::size];
00754 double wy[INTERPOLATOR::size];
00755
00756
00757 m_inter.calc_coeff(dx, wx);
00758 m_inter.calc_coeff(dy, wy);
00759
00760 RealPixelType p(vigra::NumericTraits<RealPixelType>::zero());
00761 double weightsum = 0.0;
00762 double m = 0.0;
00763 vigra::Diff2D offset(srcx - INTERPOLATOR::size/2 + 1,
00764 srcy - INTERPOLATOR::size/2 + 1);
00765 SrcImageIterator ys(m_sIter + offset);
00766 MaskIterator yms(m_mIter + offset);
00767 for (int ky = 0; ky < INTERPOLATOR::size; ky++, ++(ys.y), ++(yms.y)) {
00768
00769 typename SrcImageIterator::row_iterator xs(ys.rowIterator());
00770 typename MaskIterator::row_iterator xms(yms.rowIterator());
00771 for (int kx = 0; kx < INTERPOLATOR::size; kx++, ++xs, ++xms) {
00772
00773
00774 MaskType cmask = *xms;
00775 if (cmask) {
00776
00777 double f = wx[kx]*wy[ky];
00778
00779 m += f * cmask;
00780 p += f * m_sAcc(xs);
00781 weightsum += f;
00782 }
00783 }
00784 }
00785
00786
00787 if (weightsum <= 0.2) return false;
00788
00789 if (weightsum != 1.0) {
00790 p /= weightsum;
00791 m /= weightsum;
00792 }
00793
00794 result = vigra::detail::RequiresExplicitCast<PixelType>::cast(p);
00795 mask = vigra::detail::RequiresExplicitCast<MaskType>::cast(m);
00796 return true;
00797 }
00798
00799 };
00800
00801
00802
00803
00804
00805
00806
00856 template <class ACCESSOR, class VALUETYPE, class INTERPOLATOR>
00857 class InterpolatingAccessor
00858 {
00859 public:
00862 typedef VALUETYPE value_type;
00863
00866 InterpolatingAccessor(ACCESSOR a, INTERPOLATOR inter)
00867 : a_(a), inter_x(inter), inter_y(inter)
00868 {}
00869
00886 template <class ITERATOR>
00887 value_type operator()(ITERATOR const & i, float x, float y) const
00888 {
00889 int ix = int(x);
00890 int iy = int(y);
00891 float dx = x - ix;
00892 float dy = y - iy;
00893 double wx[INTERPOLATOR::size];
00894 double wy[INTERPOLATOR::size];
00895
00896
00897 typename vigra::NumericTraits<value_type>::RealPromote
00898 ret (vigra::NumericTraits<value_type>::zero());
00899
00900
00901 inter_x.calc_coeff(dx, wx);
00902 inter_y.calc_coeff(dy, wy);
00903
00904 ITERATOR ys(i + vigra::Diff2D(ix - inter_x.size/2 + 1,
00905 iy - inter_y.size/2 + 1));
00906 for(int y = 0; y < inter_y.size; ++y, ++ys.y) {
00907 ITERATOR xs(ys);
00908 for(int x = 0; x < inter_x.size; x++, ++xs.x) {
00909 ret += wx[x] * wy[y] * a_(xs);
00910 }
00911 }
00912 return vigra::detail::RequiresExplicitCast<value_type>::cast(ret);
00913 }
00914
00936 template <class ITERATOR, class ALPHAITERATOR, class ALPHAACCESSOR>
00937 bool operator()(ITERATOR const & i, std::pair<ALPHAITERATOR, ALPHAACCESSOR> const & alpha,
00938 float x, float y, value_type & result) const
00939 {
00940 int ix = int(x);
00941 int iy = int(y);
00942 float dx = x - ix;
00943 float dy = y - iy;
00944 double wx[INTERPOLATOR::size];
00945 double wy[INTERPOLATOR::size];
00946
00947
00948 typename vigra::NumericTraits<value_type>::RealPromote
00949 ret (vigra::NumericTraits<value_type>::zero());
00950
00951
00952 inter_x.calc_coeff(dx, wx);
00953 inter_y.calc_coeff(dy, wy);
00954
00955 ITERATOR ys(i + vigra::Diff2D(ix - inter_x.size/2 + 1,
00956 iy - inter_y.size/2 + 1));
00957 ALPHAITERATOR ays(alpha.first + vigra::Diff2D(ix - inter_x.size/2 + 1,
00958 iy - inter_y.size/2 + 1));
00959 for(int y = 0; y < inter_y.size; ++y, ++ys.y, ++ays.y) {
00960 ITERATOR xs(ys);
00961 ALPHAITERATOR axs(ays);
00962 for(int x = 0; x < inter_x.size; x++, ++xs.x, ++axs.x) {
00963 if (alpha.second(axs) <= 0 ) {
00964 return false;
00965 }
00966 ret += wx[x] * wy[y] * a_(xs);
00967 }
00968 }
00969 result = vigra::detail::RequiresExplicitCast<value_type>::cast(ret);
00970 return true;
00971 }
00972
00973
00974 private:
00975 ACCESSOR a_;
00976 INTERPOLATOR inter_x, inter_y;
00977 };
00978
00979 }
00980
00981 #endif // VIGRA_EXT_INTERPOLATORS_H