Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
transform_line.hh
1 // Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
2 // (LRDE)
3 //
4 // This file is part of Olena.
5 //
6 // Olena is free software: you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free
8 // Software Foundation, version 2 of the License.
9 //
10 // Olena is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // As a special exception, you may use this file as part of a free
19 // software project without restriction. Specifically, if other files
20 // instantiate templates or use macros or inline functions from this
21 // file, or you compile this file and link it with other files to produce
22 // an executable, this file does not by itself cause the resulting
23 // executable to be covered by the GNU General Public License. This
24 // exception does not however invalidate any other reasons why the
25 // executable file might be covered by the GNU General Public License.
26 
27 #ifndef MLN_ACCU_TRANSFORM_LINE_HH
28 # define MLN_ACCU_TRANSFORM_LINE_HH
29 
42 
43 # include <mln/core/concept/image.hh>
44 # include <mln/core/concept/meta_accumulator.hh>
45 # include <mln/extension/adjust.hh>
46 
47 
48 namespace mln
49 {
50 
51  namespace accu
52  {
53 
54 
55  template <typename A, typename I>
56  mln_ch_value(I, mln_result(A))
57  transform_line(const Accumulator<A>& a,
58  const Image<I>& input,
59  unsigned length, unsigned dir);
60 
61  template <typename A, typename I>
62  mln_ch_value(I, mln_meta_accu_result(A, mln_value(I)))
63  transform_line(const Meta_Accumulator<A>& a,
64  const Image<I>& input,
65  unsigned length, unsigned dir);
66 
67 
68 
69 # ifndef MLN_INCLUDE_ONLY
70 
71 
72  // Tests.
73 
74 
75  namespace internal
76  {
77 
78  template <typename A, typename I>
79  void
80  transform_line_tests(const Accumulator<A>& a_, const Image<I>& input_)
81  {
82  A a = exact(a_);
83  const I& input = exact(input_);
84 
85  mln_precondition(input.is_valid());
86  mln_psite(I)* p;
87  mln_precondition(sizeof(a.take(input(*p)), 0) == sizeof(int));
88 
89  (void) p;
90  (void) a;
91  (void) input;
92  }
93 
94  } // end of namespace mln::accu::internal
95 
96 
97 
98  // Implementations.
99 
100 
101  namespace impl
102  {
103 
104  namespace generic
105  {
106 
107  template <typename A, typename I>
108  inline
109  mln_ch_value(I, mln_result(A))
110  transform_line(const Accumulator<A>& a_,
111  const Image<I>& input_,
112  unsigned length, unsigned dir)
113  {
114  trace::entering("accu::impl::transform_line");
115 
116  const I& input = exact(input_);
117  A a = exact(a_);
118 
119  internal::transform_line_tests(a, input);
120 
121  extension::adjust(input, length / 2); // Safety.
122 
123  mln_ch_value(I, mln_result(A)) output;
124  initialize(output, input);
125 
126  typedef mln_psite(I) P;
127  const P
128  pmin = input.domain().pmin(),
129  pmax = input.domain().pmax();
130  const def::coord
131  pmax_dir = pmax[dir],
132  pmin_dir = pmin[dir];
133 
134  P p = pmin, // Starting point.
135  qt, qu;
136  def::coord& p_dir = p [dir];
137  def::coord& qt_dir = qt[dir];
138  def::coord& qu_dir = qu[dir];
139 
140  do
141  {
142 
143  // Start the line.
144  // ---------------
145 
146  qt = p;
147  qt_dir = p_dir - length / 2;
148  qu = qt;
149  a.init();
150 
151  for (unsigned i = 0; i < length; ++i)
152  {
153  if (input.has(qt))
154  a.take(input(qt));
155  qt_dir++;
156  }
157  if (input.has(p))
158  output(p) = a.to_result();
159 
160  // Browse the line.
161  // ----------------
162 
163  while (p_dir < pmax_dir)
164  {
165  if (input.has(qt))
166  a.take(input(qt));
167  qt_dir++;
168 
169  if (input.has(qu))
170  a.untake(input(qu));
171  qu_dir++;
172 
173  ++p_dir;
174  if (input.has(p))
175  output(p) = a.to_result();
176  }
177 
178  // Go to the next line.
179  // --------------------
180 
181  p_dir = pmin_dir;
182 
183  for (int c = P::dim - 1; c >= 0; --c)
184  {
185  if (c == int(dir))
186  continue;
187  if (p[c] != pmax[c])
188  {
189  ++p[c];
190  break;
191  }
192  p[c] = pmin[c];
193  }
194 
195  } while (p != pmin);
196 
197  trace::exiting("accu::impl::transform_line");
198  return output;
199  }
200 
201  } // end of namespace mln::accu::impl::generic
202 
203 
204  template <typename A, typename I>
205  inline
206  mln_ch_value(I, mln_result(A))
207  transform_line_fastest(const Accumulator<A>& a_,
208  const Image<I>& input_,
209  unsigned length, unsigned dir)
210  {
211  trace::entering("accu::impl::transform_line_fastest");
212 
213  const I& input = exact(input_);
214  A a = exact(a_);
215 
216  internal::transform_line_tests(a, input);
217 
218  extension::adjust(input, length / 2); // Safety.
219 
220  mln_ch_value(I, mln_result(A)) output;
221  initialize(output, input);
222 
223  typedef mln_psite(I) P;
224  const P
225  pmin = input.domain().pmin(),
226  pmax = input.domain().pmax();
227  const def::coord
228  pmax_dir = pmax[dir],
229  pmin_dir = pmin[dir];
230 
231  P p = pmin; // Starting point.
232  def::coord& p_dir = p[dir];
233 
234  // Step.
235  mln_delta(P) dp(literal::zero);
236  dp[dir] = 1;
237  int step = input.delta_index(dp);
238 
239  do
240  {
241  // Start the line.
242  // ---------------
243 
244  unsigned o_p = input.index_of_point(p);
245  unsigned o_qt = o_p - (length / 2) * step;
246  unsigned o_qu = o_qt;
247  a.init();
248 
249  for (unsigned i = 0; i < length; ++i)
250  // t o | x o o
251  // ...
252  // o o | x o t
253  {
254  a.take(input.element(o_qt));
255  o_qt += step;
256  }
257  output.element(o_p) = a.to_result();
258 
259  // Browse the line.
260  // ----------------
261 
262  while (p_dir < pmax_dir)
263  // u o | o x o t
264  // ...
265  // u o o x | o t
266  {
267  a.take(input.element(o_qt));
268  o_qt += step;
269 
270  a.untake(input.element(o_qu));
271  o_qu += step;
272 
273  ++p_dir;
274  o_p += step;
275  output.element(o_p) = a.to_result();
276  }
277 
278  // Go to the next line.
279  // --------------------
280 
281  p_dir = pmin_dir;
282 
283  for (int c = P::dim - 1; c >= 0; --c)
284  {
285  if (c == int(dir))
286  continue;
287  if (p[c] != pmax[c])
288  {
289  ++p[c];
290  break;
291  }
292  p[c] = pmin[c];
293  }
294 
295  } while (p != pmin);
296 
297  trace::exiting("accu::impl::transform_line_fastest");
298  return output;
299  }
300 
301  /*
302 
303  template <typename A, typename I>
304  inline
305  mln_ch_value(I, mln_result(A))
306  transform_line_fastest_without_border(const Accumulator<A>& a_,
307  const Image<I>& input_,
308  unsigned length, unsigned dir)
309  {
310  trace::entering("accu::impl::transform_line_fastest_without_border");
311 
312  const I& input = exact(input_);
313  A a = exact(a_);
314 
315  internal::transform_line_tests(a, input);
316 
317  mln_ch_value(I, mln_result(A)) output;
318  initialize(output, input);
319 
320  typedef mln_psite(I) P;
321  const P
322  pmin = input.domain().pmin(),
323  pmax = input.domain().pmax();
324  const def::coord
325  pmax_dir = pmax[dir] - length / 2,
326  pmin_dir = pmin[dir];
327 
328  P p = pmin; // Starting point.
329  def::coord& p_dir = p [dir];
330 
331  // Step.
332  mln_delta(P) dp(literal::zero);
333  dp[dir] = 1;
334  int step = input.delta_index(dp);
335 
336  do
337  {
338  // Start the line.
339  // ---------------
340 
341  unsigned o_p = input.index_of_point(p);
342  unsigned o_qt = o_p;
343  unsigned o_qu = o_p;
344 
345  a.init();
346 
347  // Causal part.
348  for (unsigned i = 0; i <= length / 2; ++i)
349  // | t
350  // | x t
351  // | x o t
352  {
353  a.take(input.element(o_qt));
354  o_qt += step;
355  }
356  output.element(o_p) = a.to_result();
357 
358  // Non-causal part.
359  for (unsigned i = 0; i < length / 2; ++i)
360  // | x o o <- end of previous loop
361  // | o x o t
362  // | o o x o t
363  {
364  a.take(input.element(o_qt));
365  o_qt += step;
366 
367  ++p_dir;
368  o_p += step;
369  output.element(o_p) = a.to_result();
370  }
371 
372  // Browse the line.
373  // ----------------
374 
375  while (p_dir < pmax_dir)
376  // from .. o o x o o ..
377  // to .. u o o x o t ..
378  {
379  a.take(input.element(o_qt));
380  o_qt += step;
381 
382  a.untake(input.element(o_qu));
383  o_qu += step;
384 
385  ++p_dir;
386  o_p += step;
387  output.element(o_p) = a.to_result();
388  }
389 
390  // Finalize.
391  // ---------
392 
393  for (unsigned i = 0; i < length / 2; ++i)
394  // o o x o o | <- end of previous loop
395  // u o o x o |
396  // u o o x |
397  {
398  a.untake(input.element(o_qu));
399  o_qu += step;
400 
401  o_p += step;
402  output.element(o_p) = a.to_result();
403  }
404 
405  // Go to the next line.
406  // --------------------
407 
408  p_dir = pmin_dir;
409 
410  for (int c = P::dim - 1; c >= 0; --c)
411  {
412  if (c == int(dir))
413  continue;
414  if (p[c] != pmax[c])
415  {
416  ++p[c];
417  break;
418  }
419  p[c] = pmin[c];
420  }
421 
422  } while (p != pmin);
423 
424  trace::exiting("accu::impl::transform_line_fastest_without_border");
425  return output;
426  }
427 
428  */
429 
430  } // end of namespace mln::accu::impl
431 
432 
433 
434 
435  // Dispatch.
436 
437 
438  namespace internal
439  {
440 
441  template <typename A, typename I>
442  inline
443  mln_ch_value(I, mln_result(A))
444  transform_line_dispatch(trait::image::speed::any,
445  trait::accumulator::when_pix::any,
446  const Accumulator<A>& a,
447  const Image<I>& input,
448  unsigned length, unsigned dir)
449  {
450  return impl::generic::transform_line(a,
451  input,
452  length, dir);
453  }
454 
455  template <typename A, typename I>
456  inline
457  mln_ch_value(I, mln_result(A))
458  transform_line_dispatch(trait::image::speed::fastest,
459  trait::accumulator::when_pix::use_none,
460  const Accumulator<A>& a,
461  const Image<I>& input,
462  unsigned length, unsigned dir)
463  {
464  return impl::transform_line_fastest(a,
465  input,
466  length, dir);
467  }
468 
469  template <typename A, typename I>
470  inline
471  mln_ch_value(I, mln_result(A))
472  transform_line_dispatch(trait::image::speed::fastest,
473  trait::accumulator::when_pix::use_v,
474  const Accumulator<A>& a,
475  const Image<I>& input,
476  unsigned length, unsigned dir)
477  {
478  return impl::transform_line_fastest(a,
479  input,
480  length, dir);
481  }
482 
483  template <typename A, typename I>
484  inline
485  mln_ch_value(I, mln_result(A))
486  transform_line_dispatch(const Accumulator<A>& a,
487  const Image<I>& input,
488  unsigned length, unsigned dir)
489  {
490  return transform_line_dispatch(mln_trait_image_speed(I)(),
491  mln_trait_accumulator_when_pix(A)(),
492  a, input, length, dir);
493  }
494 
495  } // end of namespace mln::accu::internal
496 
497 
498 
499 
500  // Facades.
501 
502 
503  template <typename A, typename I>
504  inline
505  mln_ch_value(I, mln_result(A))
506  transform_line(const Accumulator<A>& a,
507  const Image<I>& input,
508  unsigned length, unsigned dir)
509  {
510  trace::entering("accu::transform_line");
511 
512  internal::transform_line_tests(a, input);
513 
514  extension::adjust(input, length / 2); // Safety.
515 
516  mln_ch_value(I, mln_result(A)) output;
517  output = internal::transform_line_dispatch(a, input, length, dir);
518 
519  trace::exiting("accu::transform_line");
520  return output;
521  }
522 
523 
524  template <typename A, typename I>
525  inline
526  mln_ch_value(I, mln_meta_accu_result(A, mln_value(I)))
527  transform_line(const Meta_Accumulator<A>& a,
528  const Image<I>& input,
529  unsigned length, unsigned dir)
530  {
531  trace::entering("accu::transform_line");
532 
533  typedef mln_accu_with(A, mln_value(I)) A_;
534  A_ a_ = accu::unmeta(exact(a), mln_value(I)());
535 
536  internal::transform_line_tests(a_, input);
537 
538  mln_ch_value(I, mln_result(A_)) output;
539  output = internal::transform_line_dispatch(a_, input, length, dir);
540 
541  trace::exiting("accu::transform_line");
542  return output;
543  }
544 
545 
546 # endif // ! MLN_INCLUDE_ONLY
547 
548  } // end of namespace mln::accu
549 
550 } // end of namespace mln
551 
552 
553 #endif // ! MLN_ACCU_TRANSFORM_LINE_HH