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
00042
00043 # include <mln/core/concept/image.hh>
00044 # include <mln/core/concept/meta_accumulator.hh>
00045 # include <mln/extension/adjust.hh>
00046
00047
00048 namespace mln
00049 {
00050
00051 namespace accu
00052 {
00053
00054
00055 template <typename A, typename I>
00056 mln_ch_value(I, mln_result(A))
00057 transform_line(const Accumulator<A>& a,
00058 const Image<I>& input,
00059 unsigned length, unsigned dir);
00060
00061 template <typename A, typename I>
00062 mln_ch_value(I, mln_meta_accu_result(A, mln_value(I)))
00063 transform_line(const Meta_Accumulator<A>& a,
00064 const Image<I>& input,
00065 unsigned length, unsigned dir);
00066
00067
00068
00069 # ifndef MLN_INCLUDE_ONLY
00070
00071
00072
00073
00074
00075 namespace internal
00076 {
00077
00078 template <typename A, typename I>
00079 void
00080 transform_line_tests(const Accumulator<A>& a_, const Image<I>& input_)
00081 {
00082 A a = exact(a_);
00083 const I& input = exact(input_);
00084
00085 mln_precondition(input.is_valid());
00086 mln_psite(I)* p;
00087 mln_precondition(sizeof(a.take(input(*p)), 0) == sizeof(int));
00088
00089 (void) p;
00090 (void) a;
00091 (void) input;
00092 }
00093
00094 }
00095
00096
00097
00098
00099
00100
00101 namespace impl
00102 {
00103
00104 namespace generic
00105 {
00106
00107 template <typename A, typename I>
00108 inline
00109 mln_ch_value(I, mln_result(A))
00110 transform_line(const Accumulator<A>& a_,
00111 const Image<I>& input_,
00112 unsigned length, unsigned dir)
00113 {
00114 trace::entering("accu::impl::transform_line");
00115
00116 const I& input = exact(input_);
00117 A a = exact(a_);
00118
00119 internal::transform_line_tests(a, input);
00120
00121 extension::adjust(input, length / 2);
00122
00123 mln_ch_value(I, mln_result(A)) output;
00124 initialize(output, input);
00125
00126 typedef mln_psite(I) P;
00127 const P
00128 pmin = input.domain().pmin(),
00129 pmax = input.domain().pmax();
00130 const def::coord
00131 pmax_dir = pmax[dir],
00132 pmin_dir = pmin[dir];
00133
00134 P p = pmin,
00135 qt, qu;
00136 def::coord& p_dir = p [dir];
00137 def::coord& qt_dir = qt[dir];
00138 def::coord& qu_dir = qu[dir];
00139
00140 do
00141 {
00142
00143
00144
00145
00146 qt = p;
00147 qt_dir = p_dir - length / 2;
00148 qu = qt;
00149 a.init();
00150
00151 for (unsigned i = 0; i < length; ++i)
00152 {
00153 if (input.has(qt))
00154 a.take(input(qt));
00155 qt_dir++;
00156 }
00157 if (input.has(p))
00158 output(p) = a.to_result();
00159
00160
00161
00162
00163 while (p_dir < pmax_dir)
00164 {
00165 if (input.has(qt))
00166 a.take(input(qt));
00167 qt_dir++;
00168
00169 if (input.has(qu))
00170 a.untake(input(qu));
00171 qu_dir++;
00172
00173 ++p_dir;
00174 if (input.has(p))
00175 output(p) = a.to_result();
00176 }
00177
00178
00179
00180
00181 p_dir = pmin_dir;
00182
00183 for (int c = P::dim - 1; c >= 0; --c)
00184 {
00185 if (c == int(dir))
00186 continue;
00187 if (p[c] != pmax[c])
00188 {
00189 ++p[c];
00190 break;
00191 }
00192 p[c] = pmin[c];
00193 }
00194
00195 } while (p != pmin);
00196
00197 trace::exiting("accu::impl::transform_line");
00198 return output;
00199 }
00200
00201 }
00202
00203
00204 template <typename A, typename I>
00205 inline
00206 mln_ch_value(I, mln_result(A))
00207 transform_line_fastest(const Accumulator<A>& a_,
00208 const Image<I>& input_,
00209 unsigned length, unsigned dir)
00210 {
00211 trace::entering("accu::impl::transform_line_fastest");
00212
00213 const I& input = exact(input_);
00214 A a = exact(a_);
00215
00216 internal::transform_line_tests(a, input);
00217
00218 extension::adjust(input, length / 2);
00219
00220 mln_ch_value(I, mln_result(A)) output;
00221 initialize(output, input);
00222
00223 typedef mln_psite(I) P;
00224 const P
00225 pmin = input.domain().pmin(),
00226 pmax = input.domain().pmax();
00227 const def::coord
00228 pmax_dir = pmax[dir],
00229 pmin_dir = pmin[dir];
00230
00231 P p = pmin;
00232 def::coord& p_dir = p[dir];
00233
00234
00235 mln_delta(P) dp(literal::zero);
00236 dp[dir] = 1;
00237 int step = input.delta_index(dp);
00238
00239 do
00240 {
00241
00242
00243
00244 unsigned o_p = input.index_of_point(p);
00245 unsigned o_qt = o_p - (length / 2) * step;
00246 unsigned o_qu = o_qt;
00247 a.init();
00248
00249 for (unsigned i = 0; i < length; ++i)
00250
00251
00252
00253 {
00254 a.take(input.element(o_qt));
00255 o_qt += step;
00256 }
00257 output.element(o_p) = a.to_result();
00258
00259
00260
00261
00262 while (p_dir < pmax_dir)
00263
00264
00265
00266 {
00267 a.take(input.element(o_qt));
00268 o_qt += step;
00269
00270 a.untake(input.element(o_qu));
00271 o_qu += step;
00272
00273 ++p_dir;
00274 o_p += step;
00275 output.element(o_p) = a.to_result();
00276 }
00277
00278
00279
00280
00281 p_dir = pmin_dir;
00282
00283 for (int c = P::dim - 1; c >= 0; --c)
00284 {
00285 if (c == int(dir))
00286 continue;
00287 if (p[c] != pmax[c])
00288 {
00289 ++p[c];
00290 break;
00291 }
00292 p[c] = pmin[c];
00293 }
00294
00295 } while (p != pmin);
00296
00297 trace::exiting("accu::impl::transform_line_fastest");
00298 return output;
00299 }
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
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
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430 }
00431
00432
00433
00434
00435
00436
00437
00438 namespace internal
00439 {
00440
00441 template <typename A, typename I>
00442 inline
00443 mln_ch_value(I, mln_result(A))
00444 transform_line_dispatch(trait::image::speed::any,
00445 trait::accumulator::when_pix::any,
00446 const Accumulator<A>& a,
00447 const Image<I>& input,
00448 unsigned length, unsigned dir)
00449 {
00450 return impl::generic::transform_line(a,
00451 input,
00452 length, dir);
00453 }
00454
00455 template <typename A, typename I>
00456 inline
00457 mln_ch_value(I, mln_result(A))
00458 transform_line_dispatch(trait::image::speed::fastest,
00459 trait::accumulator::when_pix::use_none,
00460 const Accumulator<A>& a,
00461 const Image<I>& input,
00462 unsigned length, unsigned dir)
00463 {
00464 return impl::transform_line_fastest(a,
00465 input,
00466 length, dir);
00467 }
00468
00469 template <typename A, typename I>
00470 inline
00471 mln_ch_value(I, mln_result(A))
00472 transform_line_dispatch(trait::image::speed::fastest,
00473 trait::accumulator::when_pix::use_v,
00474 const Accumulator<A>& a,
00475 const Image<I>& input,
00476 unsigned length, unsigned dir)
00477 {
00478 return impl::transform_line_fastest(a,
00479 input,
00480 length, dir);
00481 }
00482
00483 template <typename A, typename I>
00484 inline
00485 mln_ch_value(I, mln_result(A))
00486 transform_line_dispatch(const Accumulator<A>& a,
00487 const Image<I>& input,
00488 unsigned length, unsigned dir)
00489 {
00490 return transform_line_dispatch(mln_trait_image_speed(I)(),
00491 mln_trait_accumulator_when_pix(A)(),
00492 a, input, length, dir);
00493 }
00494
00495 }
00496
00497
00498
00499
00500
00501
00502
00503 template <typename A, typename I>
00504 inline
00505 mln_ch_value(I, mln_result(A))
00506 transform_line(const Accumulator<A>& a,
00507 const Image<I>& input,
00508 unsigned length, unsigned dir)
00509 {
00510 trace::entering("accu::transform_line");
00511
00512 internal::transform_line_tests(a, input);
00513
00514 extension::adjust(input, length / 2);
00515
00516 mln_ch_value(I, mln_result(A)) output;
00517 output = internal::transform_line_dispatch(a, input, length, dir);
00518
00519 trace::exiting("accu::transform_line");
00520 return output;
00521 }
00522
00523
00524 template <typename A, typename I>
00525 inline
00526 mln_ch_value(I, mln_meta_accu_result(A, mln_value(I)))
00527 transform_line(const Meta_Accumulator<A>& a,
00528 const Image<I>& input,
00529 unsigned length, unsigned dir)
00530 {
00531 trace::entering("accu::transform_line");
00532
00533 typedef mln_accu_with(A, mln_value(I)) A_;
00534 A_ a_ = accu::unmeta(exact(a), mln_value(I)());
00535
00536 internal::transform_line_tests(a_, input);
00537
00538 mln_ch_value(I, mln_result(A_)) output;
00539 output = internal::transform_line_dispatch(a_, input, length, dir);
00540
00541 trace::exiting("accu::transform_line");
00542 return output;
00543 }
00544
00545
00546 # endif // ! MLN_INCLUDE_ONLY
00547
00548 }
00549
00550 }
00551
00552
00553 #endif // ! MLN_ACCU_TRANSFORM_LINE_HH