00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef MLN_ACCU_TRANSFORM_LINE_HH
00028 # define MLN_ACCU_TRANSFORM_LINE_HH
00029
00038
00039 # include <mln/core/concept/image.hh>
00040 # include <mln/core/concept/meta_accumulator.hh>
00041 # include <mln/extension/adjust.hh>
00042
00043
00044
00045 namespace mln
00046 {
00047
00048 namespace accu
00049 {
00050
00051
00052 template <typename A, typename I>
00053 mln_ch_value(I, mln_result(A))
00054 transform_line(const Accumulator<A>& a,
00055 const Image<I>& input,
00056 unsigned length, unsigned dir);
00057
00058 template <typename A, typename I>
00059 mln_ch_value(I, mln_meta_accu_result(A, mln_value(I)))
00060 transform_line(const Meta_Accumulator<A>& a,
00061 const Image<I>& input,
00062 unsigned length, unsigned dir);
00063
00064
00065
00066 # ifndef MLN_INCLUDE_ONLY
00067
00068
00069
00070
00071
00072 namespace internal
00073 {
00074
00075 template <typename A, typename I>
00076 void transform_line_tests(const Accumulator<A>& a_, const Image<I>& input_)
00077 {
00078 A a = exact(a_);
00079 const I& input = exact(input_);
00080
00081 mln_precondition(input.is_valid());
00082 mln_psite(I)* p;
00083 mln_precondition(sizeof(a.take(input(*p)), 0) == sizeof(int));
00084
00085 (void) p;
00086 (void) a;
00087 (void) input;
00088 }
00089
00090 }
00091
00092
00093
00094
00095
00096
00097 namespace impl
00098 {
00099
00100 namespace generic
00101 {
00102
00103 template <typename A, typename I>
00104 inline
00105 mln_ch_value(I, mln_result(A))
00106 transform_line(const Accumulator<A>& a_,
00107 const Image<I>& input_,
00108 unsigned length, unsigned dir)
00109 {
00110 trace::entering("accu::impl::transform_line");
00111
00112 const I& input = exact(input_);
00113 A a = exact(a_);
00114
00115 internal::transform_line_tests(a, input);
00116
00117 mln_ch_value(I, mln_result(A)) output;
00118 initialize(output, input);
00119
00120 typedef mln_psite(I) P;
00121 const P
00122 pmin = input.domain().pmin(),
00123 pmax = input.domain().pmax();
00124 const def::coord
00125 pmax_dir = pmax[dir],
00126 pmin_dir = pmin[dir];
00127
00128 P p = pmin,
00129 qt, qu;
00130 def::coord& p_dir = p [dir];
00131 def::coord& qt_dir = qt[dir];
00132 def::coord& qu_dir = qu[dir];
00133
00134 do
00135 {
00136
00137
00138
00139
00140 qt = p;
00141 qt_dir = p_dir - length / 2;
00142 qu = qt;
00143 a.init();
00144
00145 for (unsigned i = 0; i < length; ++i)
00146 {
00147 if (input.has(qt))
00148 a.take(input(qt));
00149 qt_dir++;
00150 }
00151 if (input.has(p))
00152 output(p) = a.to_result();
00153
00154
00155
00156
00157 while (p_dir < pmax_dir)
00158 {
00159 ++p_dir;
00160 if (input.has(qt))
00161 a.take(input(qt));
00162 if (input.has(qu))
00163 a.untake(input(qu));
00164 if (input.has(p))
00165 output(p) = a.to_result();
00166 qt_dir++;
00167 qu_dir++;
00168 }
00169
00170 p_dir = pmin_dir;
00171
00172
00173
00174
00175
00176 for (int c = P::dim - 1; c >= 0; --c)
00177 {
00178 if (c == int(dir))
00179 continue;
00180 if (p[c] != pmax[c])
00181 {
00182 ++p[c];
00183 break;
00184 }
00185 p[c] = pmin[c];
00186 }
00187
00188 } while (p != pmin);
00189
00190 trace::exiting("accu::impl::transform_line");
00191 return output;
00192 }
00193
00194 }
00195
00196
00197
00198 template <typename A, typename I>
00199 inline
00200 mln_ch_value(I, mln_result(A))
00201 transform_line_fastest(const Accumulator<A>& a_,
00202 const Image<I>& input_,
00203 unsigned length, unsigned dir)
00204 {
00205 trace::entering("accu::impl::transform_line_fastest");
00206
00207 const I& input = exact(input_);
00208 A a = exact(a_);
00209
00210 internal::transform_line_tests(a, input);
00211
00212 mln_ch_value(I, mln_result(A)) output;
00213 initialize(output, input);
00214
00215 typedef mln_psite(I) P;
00216
00217 mln_delta(P) dp(literal::zero);
00218 dp[dir] = 1;
00219 int step = input.delta_index(dp);
00220
00221 P pmin = input.domain().pmin(),
00222 pmax = input.domain().pmax();
00223 const def::coord
00224 pmax_dir = pmax[dir],
00225 pmin_dir = pmin[dir];
00226
00227 P p = pmin;
00228 def::coord& p_dir = p[dir];
00229
00230 do
00231 {
00232 unsigned o_qu, o_qt;
00233 unsigned o_p = input.index_of_point(p);
00234
00235
00236
00237
00238 a.take_as_init(input.element(o_p));
00239 o_qu = o_p;
00240 for (unsigned i = 1; i <= length / 2; ++i)
00241 {
00242 o_qu -= step;
00243 a.take(input.element(o_qu));
00244 }
00245 o_qt = o_p;
00246 for (unsigned i = 1; i <= length / 2; ++i)
00247 {
00248 o_qt += step;
00249 a.take(input.element(o_qt));
00250 }
00251 output.element(o_p) = a.to_result();
00252
00253
00254
00255
00256 while (p_dir < pmax_dir)
00257 {
00258 ++p_dir;
00259
00260 o_p += step;
00261 o_qt += step;
00262 o_qu += step;
00263
00264 a.take(input.element(o_qt));
00265 a.untake(input.element(o_qu));
00266
00267 output.element(o_p) = a.to_result();
00268 }
00269
00270 p_dir = pmin_dir;
00271
00272
00273
00274
00275 for (int c = P::dim - 1; c >= 0; --c)
00276 {
00277 if (c == int(dir))
00278 continue;
00279 if (p[c] != pmax[c])
00280 {
00281 ++p[c];
00282 break;
00283 }
00284 p[c] = pmin[c];
00285 }
00286
00287 } while (p != pmin);
00288
00289 trace::exiting("accu::impl::transform_line_fastest");
00290 return output;
00291 }
00292
00293
00294 }
00295
00296
00297
00298
00299
00300
00301
00302 namespace internal
00303 {
00304
00305 template <typename A, typename I>
00306 inline
00307 mln_ch_value(I, mln_result(A))
00308 transform_line_dispatch(trait::image::speed::any,
00309 const Accumulator<A>& a,
00310 const Image<I>& input,
00311 unsigned length, unsigned dir)
00312 {
00313 return impl::generic::transform_line(a,
00314 input,
00315 length, dir);
00316 }
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 }
00333
00334
00335
00336
00337
00338
00339
00340 template <typename A, typename I>
00341 inline
00342 mln_ch_value(I, mln_result(A))
00343 transform_line(const Accumulator<A>& a,
00344 const Image<I>& input,
00345 unsigned length, unsigned dir)
00346 {
00347 trace::entering("accu::transform_line");
00348
00349 internal::transform_line_tests(a, input);
00350
00351 extension::adjust(input, length / 2);
00352 mln_ch_value(I, mln_result(A)) output;
00353 output = internal::transform_line_dispatch(mln_trait_image_speed(I)(),
00354 a, input, length, dir);
00355
00356 trace::exiting("accu::transform_line");
00357 return output;
00358 }
00359
00360
00361 template <typename A, typename I>
00362 inline
00363 mln_ch_value(I, mln_meta_accu_result(A, mln_value(I)))
00364 transform_line(const Meta_Accumulator<A>& a,
00365 const Image<I>& input,
00366 unsigned length, unsigned dir)
00367 {
00368 trace::entering("accu::transform_line");
00369
00370 typedef mln_accu_with(A, mln_value(I)) A_;
00371 A_ a_ = accu::unmeta(exact(a), mln_value(I)());
00372
00373 internal::transform_line_tests(a_, input);
00374
00375 extension::adjust(input, length / 2);
00376 mln_ch_value(I, mln_result(A_)) output;
00377 output = impl::generic::transform_line(a_, input, length, dir);
00378
00379 trace::exiting("accu::transform_line");
00380 return output;
00381 }
00382
00383
00384 # endif // ! MLN_INCLUDE_ONLY
00385
00386 }
00387
00388 }
00389
00390
00391 #endif // ! MLN_ACCU_TRANSFORM_LINE_HH