37 #ifndef VIGRA_STDCONVOLUTION_HXX
38 #define VIGRA_STDCONVOLUTION_HXX
41 #include "stdimage.hxx"
42 #include "bordertreatment.hxx"
43 #include "separableconvolution.hxx"
44 #include "utilities.hxx"
45 #include "sized_int.hxx"
49 template <
class SrcIterator,
class SrcAccessor,
50 class DestIterator,
class DestAccessor,
51 class KernelIterator,
class KernelAccessor,
53 void internalPixelEvaluationByClip(
int x,
int y,
int w,
int h, SrcIterator xs,
54 SrcAccessor src_acc, DestIterator xd, DestAccessor dest_acc,
55 KernelIterator ki, Diff2D kul, Diff2D klr, KernelAccessor ak,
59 PromoteTraits<
typename SrcAccessor::value_type,
60 typename KernelAccessor::value_type>::Promote SumType;
61 typedef typename DestAccessor::value_type DestType;
64 int kernel_width = klr.x - kul.x + 1;
65 int kernel_height = klr.y - kul.y + 1;
67 SumType sum = NumericTraits<SumType>::zero();
71 y0 = (y<klr.y) ? -y : -klr.y;
72 y1 = (h-y-1<-kul.y) ? h-y-1 : -kul.y;
74 x0 = (x<klr.x) ? -x : -klr.x;
75 x1 = (w-x-1<-kul.x) ? w-x-1 : -kul.x;
77 SrcIterator yys = xs + Diff2D(x0, y0);
78 KernelIterator yk = ki - Diff2D(x0, y0);
80 KSumType ksum = NumericTraits<KSumType>::zero();
81 kernel_width = x1 - x0 + 1;
82 kernel_height = y1 - y0 + 1;
86 for(yy=0; yy<kernel_height; ++yy, ++yys.y, --yk.y)
88 SrcIterator xxs = yys;
89 KernelIterator xk = yk;
91 for(xx=0; xx<kernel_width; ++xx, ++xxs.x, --xk.x)
93 sum += ak(xk) * src_acc(xxs);
99 dest_acc.set(detail::RequiresExplicitCast<DestType>::cast((norm / ksum) * sum), xd);
105 template <
class SrcIterator,
class SrcAccessor,
106 class DestIterator,
class DestAccessor,
107 class KernelIterator,
class KernelAccessor>
108 void internalPixelEvaluationByWrapReflectRepeat(
int x,
int y,
int src_width,
int src_height, SrcIterator xs,
109 SrcAccessor src_acc, DestIterator xd, DestAccessor dest_acc,
110 KernelIterator ki, Diff2D kul, Diff2D klr, KernelAccessor ak,
111 BorderTreatmentMode border)
115 NumericTraits<typename SrcAccessor::value_type>::RealPromote SumType;
117 NumericTraits<typename DestAccessor::value_type> DestTraits;
119 SumType sum = NumericTraits<SumType>::zero();
121 SrcIterator src_ul = xs - Diff2D(x, y);
122 SrcIterator src_lr = src_ul + Diff2D(src_width, src_height);
124 SrcIterator yys = xs;
125 KernelIterator yk = ki;
128 int kernel_width = klr.x - kul.x + 1;
129 int kernel_height = klr.y - kul.y + 1;
132 bool top_to_much = (y<klr.y) ?
true :
false;
133 bool down_to_much = (src_height-y-1<-kul.y)?
true :
false;
134 bool left_to_much = (x<klr.x)?
true :
false;
135 bool right_to_much = (src_width-x-1<-kul.x)?
true :
false;
139 Diff2D way_increment;
150 tuple4<int, int, int, int> border_increment;
151 if (border == BORDER_TREATMENT_REPEAT){
152 border_increment = tuple4<int, int, int, int>(1, 1, 0, 0);
153 }
else if (border == BORDER_TREATMENT_REFLECT){
154 border_increment = tuple4<int, int, int, int>(2, 2, -1, -1);
156 border_increment = tuple4<int, int, int, int>(src_width, src_height, 1, 1);
159 pair<int, int> valid_step_count;
161 if(left_to_much && !top_to_much && !down_to_much)
165 way_increment = Diff2D(-1, -1);
166 border_increment.third = -border_increment.third;
167 border_increment.fourth = -border_increment.fourth;
168 valid_step_count = std::make_pair((yys - src_ul).x + 1, kernel_height);
170 else if(top_to_much && !left_to_much && !right_to_much)
174 way_increment = Diff2D(-1, -1);
175 border_increment.third = -border_increment.third;
176 border_increment.fourth = -border_increment.fourth;
177 valid_step_count = std::make_pair(kernel_width, (yys - src_ul).y + 1);
179 else if(right_to_much && !top_to_much && !down_to_much)
183 way_increment = Diff2D(1, 1);
184 border_increment.first = -border_increment.first;
185 border_increment.second = -border_increment.second;
186 valid_step_count = std::make_pair((src_lr - yys).x, kernel_height);
188 else if(down_to_much && !left_to_much && !right_to_much)
192 way_increment = Diff2D(1, 1);
193 border_increment.first = -border_increment.first;
194 border_increment.second = -border_increment.second;
195 valid_step_count = std::make_pair(kernel_width, (src_lr - yys).y);
197 else if(down_to_much && left_to_much)
199 yys += kul + Diff2D(kernel_width - 1, 0);
200 yk += kul + Diff2D(0, kernel_height - 1);
201 way_increment = Diff2D(-1, 1);
202 border_increment.second = -border_increment.second;
203 border_increment.third = -border_increment.third;
204 valid_step_count = std::make_pair((yys - src_ul).x + 1, (src_lr - yys).y);
206 else if(down_to_much && right_to_much)
210 way_increment = Diff2D(1, 1);
211 border_increment.first = -border_increment.first;
212 border_increment.second = -border_increment.second;
213 valid_step_count = std::make_pair((src_lr - yys).x, (src_lr - yys).y);
215 else if(top_to_much && left_to_much)
219 way_increment = Diff2D(-1, -1);
220 border_increment.third = -border_increment.third;
221 border_increment.fourth = -border_increment.fourth;
222 valid_step_count = std::make_pair((yys - src_ul).x + 1, (yys - src_ul).y + 1);
226 yys += kul + Diff2D(0, kernel_height - 1);
227 yk += kul + Diff2D(kernel_width - 1, 0);
228 way_increment = Diff2D(1, -1);
229 border_increment.first = -border_increment.first;
230 border_increment.fourth = -border_increment.fourth;
231 valid_step_count = std::make_pair((src_lr - yys).x, (yys - src_ul).y + 1);
237 for(; yy < valid_step_count.second; ++yy, yys.y += way_increment.y, yk.y -= way_increment.y )
239 SrcIterator xxs = yys;
240 KernelIterator xk = yk;
243 for(xx = 0; xx < valid_step_count.first; ++xx, xxs.x += way_increment.x, xk.x -= way_increment.x)
245 sum += ak(xk) * src_acc(xxs);
250 xxs.x += border_increment.first;
252 for( ; xx < kernel_width; ++xx, xxs.x += border_increment.third, xk.x -= way_increment.x )
254 sum += ak(xk) * src_acc(xxs);
260 yys.y += border_increment.second;
262 for( ; yy < kernel_height; ++yy, yys.y += border_increment.third, yk.y -= way_increment.y)
264 SrcIterator xxs = yys;
265 KernelIterator xk = yk;
267 for(xx=0; xx < valid_step_count.first; ++xx, xxs.x += way_increment.x, xk.x -= way_increment.x)
269 sum += ak(xk) * src_acc(xxs);
273 xxs.x += border_increment.first;
275 for( ; xx < kernel_width; ++xx, xxs.x += border_increment.third, xk.x -= way_increment.x )
277 sum += ak(xk) * src_acc(xxs);
282 dest_acc.set(DestTraits::fromRealPromote(sum), xd);
288 template <
class SrcIterator,
class SrcAccessor,
289 class KernelIterator,
class KernelAccessor,
292 internalPixelEvaluationByWrapReflectRepeat(SrcIterator xs, SrcAccessor src_acc,
293 KernelIterator xk, KernelAccessor ak,
294 int left,
int right,
int kleft,
int kright,
295 int borderskipx,
int borderinc, SumType & sum)
297 SrcIterator xxs = xs + left;
298 KernelIterator xxk = xk - left;
300 for(
int xx = left; xx <= right; ++xx, ++xxs, --xxk)
302 sum += ak(xxk) * src_acc(xxs);
305 xxs = xs + left - borderskipx;
307 for(
int xx = left - 1; xx >= -kright; --xx, xxs -= borderinc, ++xxk)
309 sum += ak(xxk) * src_acc(xxs);
312 xxs = xs + right + borderskipx;
313 xxk = xk - right - 1;
314 for(
int xx = right + 1; xx <= -kleft; ++xx, xxs += borderinc, --xxk)
316 sum += ak(xxk) * src_acc(xxs);
451 template <
class SrcIterator,
class SrcAccessor,
452 class DestIterator,
class DestAccessor,
453 class KernelIterator,
class KernelAccessor>
454 void convolveImage(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc,
455 DestIterator dest_ul, DestAccessor dest_acc,
456 KernelIterator ki, KernelAccessor ak,
459 vigra_precondition((border == BORDER_TREATMENT_CLIP ||
460 border == BORDER_TREATMENT_AVOID ||
461 border == BORDER_TREATMENT_REFLECT ||
462 border == BORDER_TREATMENT_REPEAT ||
463 border == BORDER_TREATMENT_WRAP),
465 " Border treatment must be one of follow treatments:\n"
466 " - BORDER_TREATMENT_CLIP\n"
467 " - BORDER_TREATMENT_AVOID\n"
468 " - BORDER_TREATMENT_REFLECT\n"
469 " - BORDER_TREATMENT_REPEAT\n"
470 " - BORDER_TREATMENT_WRAP\n");
472 vigra_precondition(kul.
x <= 0 && kul.
y <= 0,
473 "convolveImage(): coordinates of "
474 "kernel's upper left must be <= 0.");
475 vigra_precondition(klr.
x >= 0 && klr.
y >= 0,
476 "convolveImage(): coordinates of "
477 "kernel's lower right must be >= 0.");
481 PromoteTraits<
typename SrcAccessor::value_type,
482 typename KernelAccessor::value_type>::Promote SumType;
484 NumericTraits<typename KernelAccessor::value_type>::RealPromote KernelSumType;
485 typedef typename DestAccessor::value_type DestType;
488 int w = src_lr.x - src_ul.x;
489 int h = src_lr.y - src_ul.y;
492 int kernel_width = klr.
x - kul.
x + 1;
493 int kernel_height = klr.
y - kul.
y + 1;
495 vigra_precondition(w >= kernel_width && h >= kernel_height,
496 "convolveImage(): kernel larger than image.");
498 KernelSumType norm = NumericTraits<KernelSumType>::zero();
499 if(border == BORDER_TREATMENT_CLIP)
502 KernelIterator yk = ki + klr;
505 for(
int y = 0; y < kernel_height; ++y, --yk.y)
507 KernelIterator xk = yk;
508 for(
int x = 0; x < kernel_width; ++x, --xk.x)
513 vigra_precondition(norm != NumericTraits<KernelSumType>::zero(),
514 "convolveImage(): Cannot use BORDER_TREATMENT_CLIP with a DC-free kernel");
518 DestIterator yd = dest_ul +
Diff2D(klr.
x, klr.
y);
519 SrcIterator ys = src_ul + Diff2D(klr.
x, klr.
y);
520 SrcIterator send = src_lr + Diff2D(kul.
x, kul.
y);
523 for(; ys.y < send.y; ++ys.y, ++yd.y)
529 for(; xs.x < send.x; ++xs.x, ++xd.x)
532 SumType sum = NumericTraits<SumType>::zero();
534 SrcIterator yys = xs - klr;
535 SrcIterator yyend = xs - kul;
536 KernelIterator yk = ki + klr;
538 for(; yys.y <= yyend.y; ++yys.y, --yk.y)
540 typename SrcIterator::row_iterator xxs = yys.
rowIterator();
541 typename SrcIterator::row_iterator xxe = xxs + kernel_width;
542 typename KernelIterator::row_iterator xk = yk.rowIterator();
544 for(; xxs < xxe; ++xxs, --xk)
546 sum += ak(xk) * src_acc(xxs);
551 dest_acc.set(detail::RequiresExplicitCast<DestType>::cast(sum), xd);
555 if(border == BORDER_TREATMENT_AVOID)
558 int interiorskip = w + kul.
x - klr.
x - 1;
562 if(border == BORDER_TREATMENT_REPEAT)
568 else if(border == BORDER_TREATMENT_REFLECT)
574 else if(border == BORDER_TREATMENT_WRAP)
586 for(
int y = 0; y < h; ++y, ++ys.y, ++yd.y)
588 int top = int(std::max(static_cast<IntBiggest>(-klr.
y),
589 static_cast<IntBiggest>(src_ul.y - ys.y)));
590 int bottom = int(std::min(static_cast<IntBiggest>(-kul.
y),
591 static_cast<IntBiggest>(src_lr.y - ys.y - 1)));
597 for(
int x = 0; x < w; ++x, ++xs.x, ++xd.x)
600 if(y >= klr.
y && y < h+kul.
y && x == klr.
x)
604 xs.x += interiorskip;
605 xd.x += interiorskip;
608 if (border == BORDER_TREATMENT_CLIP)
610 internalPixelEvaluationByClip(x, y, w, h, xs, src_acc, xd, dest_acc, ki, kul, klr, ak, norm);
614 int left = std::max(-klr.
x, src_ul.x - xs.x);
615 int right = std::min(-kul.
x, src_lr.x - xs.x - 1);
618 SumType sum = NumericTraits<SumType>::zero();
621 SrcIterator yys = xs +
Size2D(0, top);
622 KernelIterator yk = ki - Size2D(0, top);
625 for(yy = top; yy <= bottom; ++yy, ++yys.y, --yk.y)
627 internalPixelEvaluationByWrapReflectRepeat(yys.rowIterator(), src_acc, yk.rowIterator(), ak,
628 left, right, kul.
x, klr.
x, borderskipx, borderinc, sum);
630 yys = xs + Size2D(0, top - borderskipy);
631 yk = ki - Size2D(0, top - 1);
632 for(yy = top - 1; yy >= -klr.
y; --yy, yys.y -= borderinc, ++yk.y)
634 internalPixelEvaluationByWrapReflectRepeat(yys.rowIterator(), src_acc, yk.rowIterator(), ak,
635 left, right, kul.
x, klr.
x, borderskipx, borderinc, sum);
637 yys = xs + Size2D(0, bottom + borderskipy);
638 yk = ki - Size2D(0, bottom + 1);
639 for(yy = bottom + 1; yy <= -kul.
y; ++yy, yys.y += borderinc, --yk.y)
641 internalPixelEvaluationByWrapReflectRepeat(yys.rowIterator(), src_acc, yk.rowIterator(), ak,
642 left, right, kul.
x, klr.
x, borderskipx, borderinc, sum);
646 dest_acc.set(detail::RequiresExplicitCast<DestType>::cast(sum), xd);
655 template <
class SrcIterator,
class SrcAccessor,
656 class DestIterator,
class DestAccessor,
657 class KernelIterator,
class KernelAccessor>
660 triple<SrcIterator, SrcIterator, SrcAccessor> src,
661 pair<DestIterator, DestAccessor> dest,
662 tuple5<KernelIterator, KernelAccessor, Diff2D, Diff2D,
663 BorderTreatmentMode> kernel)
666 dest.first, dest.second,
667 kernel.first, kernel.second, kernel.third,
668 kernel.fourth, kernel.fifth);
813 template <
class SrcIterator,
class SrcAccessor,
814 class DestIterator,
class DestAccessor,
815 class MaskIterator,
class MaskAccessor,
816 class KernelIterator,
class KernelAccessor>
819 MaskIterator
mul, MaskAccessor am,
820 DestIterator dest_ul, DestAccessor dest_acc,
821 KernelIterator ki, KernelAccessor ak,
822 Diff2D kul, Diff2D klr, BorderTreatmentMode border)
824 vigra_precondition((border == BORDER_TREATMENT_CLIP ||
825 border == BORDER_TREATMENT_AVOID),
826 "normalizedConvolveImage(): "
827 "Border treatment must be BORDER_TREATMENT_CLIP or BORDER_TREATMENT_AVOID.");
829 vigra_precondition(kul.x <= 0 && kul.y <= 0,
830 "normalizedConvolveImage(): left borders must be <= 0.");
831 vigra_precondition(klr.x >= 0 && klr.y >= 0,
832 "normalizedConvolveImage(): right borders must be >= 0.");
836 NumericTraits<typename SrcAccessor::value_type>::RealPromote SumType;
838 NumericTraits<typename KernelAccessor::value_type>::RealPromote KSumType;
840 NumericTraits<typename DestAccessor::value_type> DestTraits;
843 int w = src_lr.x - src_ul.x;
844 int h = src_lr.y - src_ul.y;
845 int kernel_width = klr.x - kul.x + 1;
846 int kernel_height = klr.y - kul.y + 1;
849 int ystart = (border == BORDER_TREATMENT_AVOID) ? klr.y : 0;
850 int yend = (border == BORDER_TREATMENT_AVOID) ? h+kul.y : h;
851 int xstart = (border == BORDER_TREATMENT_AVOID) ? klr.x : 0;
852 int xend = (border == BORDER_TREATMENT_AVOID) ? w+kul.x : w;
855 DestIterator yd = dest_ul + Diff2D(xstart, ystart);
856 SrcIterator ys = src_ul + Diff2D(xstart, ystart);
857 MaskIterator ym = mul + Diff2D(xstart, ystart);
859 KSumType norm = ak(ki);
861 KernelIterator yk = ki + klr;
862 for(yy=0; yy<kernel_height; ++yy, --yk.y)
864 KernelIterator xk = yk;
866 for(xx=0; xx<kernel_width; ++xx, --xk.x)
874 for(y=ystart; y < yend; ++y, ++ys.y, ++yd.y, ++ym.y)
881 for(x=xstart; x < xend; ++x, ++xs.x, ++xd.x, ++xm.x)
886 y0 = (y<klr.y) ? -y : -klr.y;
887 y1 = (h-y-1<-kul.y) ? h-y-1 : -kul.y;
888 x0 = (x<klr.x) ? -x : -klr.x;
889 x1 = (w-x-1<-kul.x) ? w-x-1 : -kul.x;
896 SrcIterator yys = xs + Diff2D(x0, y0);
897 MaskIterator yym = xm + Diff2D(x0, y0);
898 KernelIterator yk = ki - Diff2D(x0, y0);
900 int xx, kernel_width, kernel_height;
901 kernel_width = x1 - x0 + 1;
902 kernel_height = y1 - y0 + 1;
903 for(yy=0; yy<kernel_height; ++yy, ++yys.y, --yk.y, ++yym.y)
905 typename SrcIterator::row_iterator xxs = yys.rowIterator();
906 typename SrcIterator::row_iterator xxend = xxs + kernel_width;
907 typename MaskIterator::row_iterator xxm = yym.rowIterator();
908 typename KernelIterator::row_iterator xk = yk.rowIterator();
910 for(xx=0; xxs < xxend; ++xxs, --xk, ++xxm)
912 if(!am(xxm))
continue;
916 sum = detail::RequiresExplicitCast<SumType>::cast(ak(xk) * src_acc(xxs));
922 sum = detail::RequiresExplicitCast<SumType>::cast(sum + ak(xk) * src_acc(xxs));
929 ksum != NumericTraits<KSumType>::zero())
931 dest_acc.set(DestTraits::fromRealPromote(
932 detail::RequiresExplicitCast<SumType>::cast((norm / ksum) * sum)), xd);
939 template <
class SrcIterator,
class SrcAccessor,
940 class DestIterator,
class DestAccessor,
941 class MaskIterator,
class MaskAccessor,
942 class KernelIterator,
class KernelAccessor>
945 triple<SrcIterator, SrcIterator, SrcAccessor> src,
946 pair<MaskIterator, MaskAccessor> mask,
947 pair<DestIterator, DestAccessor> dest,
948 tuple5<KernelIterator, KernelAccessor, Diff2D, Diff2D,
949 BorderTreatmentMode> kernel)
952 mask.first, mask.second,
953 dest.first, dest.second,
954 kernel.first, kernel.second, kernel.third,
955 kernel.fourth, kernel.fifth);
998 template <
class SrcIterator,
class SrcAccessor,
999 class DestIterator,
class DestAccessor,
1000 class MaskIterator,
class MaskAccessor,
1001 class KernelIterator,
class KernelAccessor>
1004 MaskIterator mul, MaskAccessor am,
1005 DestIterator dest_ul, DestAccessor dest_acc,
1006 KernelIterator ki, KernelAccessor ak,
1007 Diff2D kul, Diff2D klr, BorderTreatmentMode border)
1012 ki, ak, kul, klr, border);
1015 template <
class SrcIterator,
class SrcAccessor,
1016 class DestIterator,
class DestAccessor,
1017 class MaskIterator,
class MaskAccessor,
1018 class KernelIterator,
class KernelAccessor>
1021 triple<SrcIterator, SrcIterator, SrcAccessor> src,
1022 pair<MaskIterator, MaskAccessor> mask,
1023 pair<DestIterator, DestAccessor> dest,
1024 tuple5<KernelIterator, KernelAccessor, Diff2D, Diff2D,
1025 BorderTreatmentMode> kernel)
1028 mask.first, mask.second,
1029 dest.first, dest.second,
1030 kernel.first, kernel.second, kernel.third,
1031 kernel.fourth, kernel.fifth);
1090 template <
class ARITHTYPE>
1120 : iter_(i), base_(i),
1121 count_(count), sum_(count),
1127 vigra_precondition(count_ == 1 || count_ == sum_,
1128 "Kernel2D::initExplicitly(): "
1129 "Too few init values.");
1134 if(count_ == sum_) norm_ = *iter_;
1137 vigra_precondition(count_ > 0,
1138 "Kernel2D::initExplicitly(): "
1139 "Too many init values.");
1154 static value_type one() {
return NumericTraits<value_type>::one(); }
1161 : kernel_(1, 1, one()),
1165 border_treatment_(BORDER_TREATMENT_CLIP)
1171 : kernel_(k.kernel_),
1175 border_treatment_(k.border_treatment_)
1184 kernel_ = k.kernel_;
1188 border_treatment_ = k.border_treatment_;
1214 int size = (right_.
x - left_.
x + 1) *
1215 (right_.
y - left_.
y + 1);
1217 norm_ = (double)size*v;
1219 return InitProxy(kernel_.
begin(), size, norm_);
1245 int w = right_.
x - left_.
x + 1;
1246 int h = right_.
y - left_.
y + 1;
1254 KIter kiy = ky.
center() + left_.
y;
1257 for(
int y=left_.
y; y<=right_.
y; ++y, ++kiy, ++iy.y)
1259 KIter kix = kx.
center() + left_.
x;
1261 for(
int x=left_.
x; x<=right_.
x; ++x, ++kix, ++ix.x)
1263 *ix = ka(kix) * ka(kiy);
1291 template <
class KernelIterator>
1293 KernelIterator kycenter,
int yleft,
int yright)
1295 vigra_precondition(xleft <= 0 && yleft <= 0,
1296 "Kernel2D::initSeparable(): left borders must be <= 0.");
1297 vigra_precondition(xright >= 0 && yright >= 0,
1298 "Kernel2D::initSeparable(): right borders must be >= 0.");
1300 left_ =
Point2D(xleft, yleft);
1301 right_ =
Point2D(xright, yright);
1303 int w = right_.
x - left_.
x + 1;
1304 int h = right_.
y - left_.
y + 1;
1307 KernelIterator kiy = kycenter + left_.
y;
1310 for(
int y=left_.
y; y<=right_.
y; ++y, ++kiy, ++iy.y)
1312 KernelIterator kix = kxcenter + left_.
x;
1314 for(
int x=left_.
x; x<=right_.
x; ++x, ++kix, ++ix.x)
1325 for(; i!= iend; ++i)
1344 initGaussian(std_dev, NumericTraits<value_type>::one());
1369 vigra_precondition(radius > 0,
1370 "Kernel2D::initDisk(): radius must be > 0.");
1372 left_ =
Point2D(-radius, -radius);
1373 right_ =
Point2D(radius, radius);
1374 int w = right_.
x - left_.
x + 1;
1375 int h = right_.
y - left_.
y + 1;
1377 norm_ = NumericTraits<value_type>::one();
1379 kernel_ = NumericTraits<value_type>::zero();
1383 double r2 = (double)radius*radius;
1386 for(i=0; i<= radius; ++i)
1388 double r = (double) i - 0.5;
1390 for(
int j=-w; j<=w; ++j)
1392 k(j, i) = NumericTraits<value_type>::one();
1393 k(j, -i) = NumericTraits<value_type>::one();
1394 count += (i != 0) ? 2.0 : 1.0;
1398 count = 1.0 / count;
1400 for(
int y=-radius; y<=radius; ++y)
1402 for(
int x=-radius; x<=radius; ++x)
1404 k(x,y) = count * k(x,y);
1449 vigra_precondition(upperleft.
x <= 0 && upperleft.
y <= 0,
1450 "Kernel2D::initExplicitly(): left borders must be <= 0.");
1451 vigra_precondition(lowerright.
x >= 0 && lowerright.
y >= 0,
1452 "Kernel2D::initExplicitly(): right borders must be >= 0.");
1457 int w = right_.
x - left_.
x + 1;
1458 int h = right_.
y - left_.
y + 1;
1474 int width()
const {
return right_.
x - left_.
x + 1; }
1491 {
return kernel_[
Diff2D(x,y) - left_]; }
1496 {
return kernel_[
Diff2D(x,y) - left_]; }
1501 {
return kernel_[d - left_]; }
1506 {
return kernel_[d - left_]; }
1539 typename NumericTraits<value_type>::RealPromote sum = *i;
1542 for(; i!= iend; ++i)
1548 i = kernel_.
begin();
1549 for(; i != iend; ++i)
1567 {
return border_treatment_; }
1575 vigra_precondition((new_mode == BORDER_TREATMENT_CLIP ||
1576 new_mode == BORDER_TREATMENT_AVOID ||
1577 new_mode == BORDER_TREATMENT_REFLECT ||
1578 new_mode == BORDER_TREATMENT_REPEAT ||
1579 new_mode == BORDER_TREATMENT_WRAP),
1580 "convolveImage():\n"
1581 " Border treatment must be one of follow treatments:\n"
1582 " - BORDER_TREATMENT_CLIP\n"
1583 " - BORDER_TREATMENT_AVOID\n"
1584 " - BORDER_TREATMENT_REFLECT\n"
1585 " - BORDER_TREATMENT_REPEAT\n"
1586 " - BORDER_TREATMENT_WRAP\n");
1588 border_treatment_ = new_mode;
1596 BorderTreatmentMode border_treatment_;
1607 template <
class KernelIterator,
class KernelAccessor>
1609 tuple5<KernelIterator, KernelAccessor, Diff2D, Diff2D, BorderTreatmentMode>
1610 kernel2d(KernelIterator ik, KernelAccessor ak, Diff2D kul, Diff2D klr,
1611 BorderTreatmentMode border)
1615 tuple5<KernelIterator, KernelAccessor, Diff2D, Diff2D, BorderTreatmentMode> (
1616 ik, ak, kul, klr, border);
1621 tuple5<typename Kernel2D<T>::ConstIterator,
1622 typename Kernel2D<T>::ConstAccessor,
1623 Diff2D, Diff2D, BorderTreatmentMode>
1624 kernel2d(Kernel2D<T>
const & k)
1628 tuple5<typename Kernel2D<T>::ConstIterator,
1629 typename Kernel2D<T>::ConstAccessor,
1630 Diff2D, Diff2D, BorderTreatmentMode>(
1633 k.upperLeft(), k.lowerRight(),
1634 k.borderTreatment());
1639 tuple5<typename Kernel2D<T>::ConstIterator,
1640 typename Kernel2D<T>::ConstAccessor,
1641 Diff2D, Diff2D, BorderTreatmentMode>
1642 kernel2d(Kernel2D<T>
const & k, BorderTreatmentMode border)
1646 tuple5<typename Kernel2D<T>::ConstIterator,
1647 typename Kernel2D<T>::ConstAccessor,
1648 Diff2D, Diff2D, BorderTreatmentMode>(
1651 k.upperLeft(), k.lowerRight(),
1658 #endif // VIGRA_STDCONVOLUTION_HXX