Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
antialiased.hh
1 // Copyright (C) 2009, 2010 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_SUBSAMPLING_ANTIALIASED_HH
28 # define MLN_SUBSAMPLING_ANTIALIASED_HH
29 
33 
34 
35 #include <mln/core/concept/image.hh>
36 #include <mln/border/thickness.hh>
37 #include <mln/extension/adjust_duplicate.hh>
38 #include <mln/core/macros.hh>
39 
40 namespace mln
41 {
42 
43  namespace subsampling
44  {
45 
54  template <typename I>
55  inline
56  mln_concrete(I)
57  antialiased(const Image<I>& input,
58  unsigned factor,
59  const mln_domain(I)& output_domain,
60  unsigned border_thickness);
61 
62 
65  template <typename I>
66  mln_concrete(I)
67  antialiased(const Image<I>& input, unsigned factor);
68 
69 
70 
71 # ifndef MLN_INCLUDE_ONLY
72 
73 
74 
75  // Tests
76 
77  namespace internal
78  {
79 
80  template <typename I>
81  inline
82  void
83  antialiased_tests(const Image<I>& input,
84  unsigned factor,
85  const mln_domain(I)& output_domain,
86  unsigned border_thickness)
87  {
88  typedef mln_site(I) P;
89 
90  mlc_is_a(mln_domain(I), Box)::check();
91  mln_precondition(exact(input).is_valid());
92  mln_precondition(exact(input).domain().pmin() == literal::origin);
93 
94  (void) input;
95  (void) factor;
96  (void) output_domain;
97  (void) border_thickness;
98  }
99 
100  } // end of namespace mln::subsampling::internal
101 
102 
103 
104 
105  // Implementations.
106 
107  namespace impl
108  {
109 
110  namespace generic
111  {
112 
113  template <typename I>
114  inline
115  mln_concrete(I)
116  antialiased(const Image<I>& input_,
117  unsigned factor,
118  const mln_domain(I)& output_domain,
119  unsigned border_thickness)
120  {
121  (void) input_;
122  (void) factor;
123  (void) output_domain;
124  (void) border_thickness;
125 
126  // To be written...
127  mlc_abort(I)::check();
128 
129  mln_concrete(I) output;
130  return output;
131  }
132 
133  } // end of namespace mln::subsampling::impl::generic
134 
135 
136 
137  template <typename I>
138  inline
139  mln_concrete(I)
140  antialiased_2d_fastest_scalar(const Image<I>& input_,
141  unsigned factor,
142  const mln_domain(I)& output_domain,
143  unsigned border_thickness)
144  {
145  trace::entering("subsampling::impl::antialiased_2d_fastest");
146 
147  internal::antialiased_tests(input_, factor,
148  output_domain, border_thickness);
149 
150  const I& input = exact(input_);
151 
152  // No reduction.
153  if (factor == 1)
154  {
155  trace::exiting("subsampling::impl::antialiased_2d_fastest");
156  return duplicate(input);
157  }
158 
159  typedef mln_value(I) V;
160  typedef mln_sum(V) S;
161 
162  typedef mln_site(I) P;
163  box<P> b = output_domain;
164  if (!b.is_valid())
165  {
166  P pmin = input.domain().pmin() / factor,
167  pmax = input.domain().pmax() / factor;
168  b = box<P>(pmin, pmax);
169  }
170  typedef mln_concrete(I) O;
171  O output(b, border_thickness);
172 
173  // Make sure there is enough data in input border.
174  unsigned input_border = factor - std::min(input.nrows() % factor,
175  input.ncols() % factor);
176  extension::adjust_duplicate(input, input_border);
177 
178 
179  typedef const V* ptr_t;
180 
181  util::array<ptr_t> ptrs(factor, 0);
182  for (unsigned i = 0; i < factor; ++i)
183  ptrs[i] = & input.at_(i, 0);
184 
185  mln_box_runstart_piter(O) s(output.domain());
186  const unsigned n = s.run_length();
187  const unsigned
188  factor_2 = factor * factor,
189  factor_round = factor_2 / 2;
190  unsigned offset = input.delta_index(point2d(factor,0) - point2d(0,factor*n));
191 
192  for_all(s)
193  {
194  mln_value(O)* po = & output(s);
195  for (unsigned i = 0; i < n; ++i)
196  {
197  mln_sum(V) s = literal::zero;
198  for (unsigned j = 0; j < factor; ++j)
199  for (unsigned k = 0; k < factor; ++k)
200  s += *ptrs[j]++;
201 
202  convert::from_to((s + factor_round) / factor_2, *po);
203  ++po;
204  }
205 
206  for (unsigned j = 0; j < factor; ++j)
207  ptrs[j] += offset;
208  }
209 
210  trace::exiting("subsampling::impl::antialiased_2d_fastest");
211  return output;
212  }
213 
214 
215 
216  template <typename I>
217  inline
218  mln_concrete(I)
219  antialiased_2d_fastest_rgb(const Image<I>& input_,
220  unsigned factor,
221  const mln_domain(I)& output_domain,
222  unsigned border_thickness)
223  {
224  trace::entering("subsampling::impl::antialiased_2d_rgb");
225 
226  internal::antialiased_tests(input_, factor,
227  output_domain, border_thickness);
228 
229  const I& input = exact(input_);
230 
231 
232  // No reduction.
233  if (factor == 1)
234  {
235  trace::exiting("subsampling::impl::antialiased_2d_rgb");
236  return duplicate(input);
237  }
238 
239  typedef mln_value(I) V;
240  typedef mln_sum(V) S;
241 
242  typedef mln_site(I) P;
243  box<P> b = output_domain;
244  if (!b.is_valid())
245  {
246  P pmin = input.domain().pmin() / factor,
247  pmax = input.domain().pmax() / factor;
248  b = box<P>(pmin, pmax);
249  }
250  typedef mln_concrete(I) O;
251  O output(b, border_thickness);
252 
253  // Make sure there is enough data in input border.
254  unsigned input_border = factor - std::min(input.nrows() % factor,
255  input.ncols() % factor);
256  extension::adjust_duplicate(input, input_border);
257 
258 
259  typedef const V* ptr_t;
260 
261  util::array<ptr_t> ptrs(factor, 0);
262  for (unsigned i = 0; i < factor; ++i)
263  ptrs[i] = & input.at_(i, 0);
264 
265  mln_box_runstart_piter(O) s(output.domain());
266  const unsigned n = s.run_length();
267  const unsigned
268  factor_2 = factor * factor,
269  factor_round = factor_2 / 2;
270  unsigned offset = input.delta_index(point2d(factor,0) - point2d(0,factor*n));
271 
272  for_all(s)
273  {
274  mln_value(O)* po = & output(s);
275  for (unsigned i = 0; i < n; ++i)
276  {
277  mln_sum(V) s = literal::zero;
278  for (unsigned j = 0; j < factor; ++j)
279  for (unsigned k = 0; k < factor; ++k)
280  {
281  algebra::vec<3, float> tmp = *ptrs[j]++;
282  s += tmp;
283  }
284 
285  // FIXME: should be removed and replaced by the
286  // commented part below.
287  for (unsigned j = 0; j < P::dim; ++j)
288  s[j] += factor_round;
289 
290  *po++ = (s /*+ factor_round*/) / factor_2;
291  }
292  for (unsigned j = 0; j < factor; ++j)
293  ptrs[j] += offset;
294  }
295 
296  trace::exiting("subsampling::impl::antialiased_2d_rgb");
297  return output;
298  }
299 
300 
301 
302  } // end of namespace mln::subsampling::impl
303 
304 
305 
306  // Dispatch.
307 
308  namespace internal
309  {
310 
311  template <unsigned dim, typename I>
312  inline
313  mln_concrete(I)
314  antialiased_dispatch(trait::image::value_alignment::any,
315  trait::image::value_storage::any,
316  trait::image::value_access::any,
317  const Image<I>& input,
318  unsigned factor,
319  const mln_domain(I)& output_domain,
320  unsigned border_thickness)
321  {
322  (void) input;
323  (void) factor;
324  (void) output_domain;
325  (void) border_thickness;
326 
327  // Not implemented yet.
328  mlc_abort(I)::check();
329  }
330 
331  template <typename I>
332  inline
333  mln_concrete(I)
334  antialiased_2d_fastest_dispatch(const mln_value(I)&,
335  const Image<I>& input,
336  unsigned factor,
337  const mln_domain(I)& output_domain,
338  unsigned border_thickness)
339  {
340  return impl::antialiased_2d_fastest_scalar(input, factor,
341  output_domain,
342  border_thickness);
343  }
344 
345 
346  template <unsigned n, typename I>
347  inline
348  mln_concrete(I)
349  antialiased_2d_fastest_dispatch(const value::rgb<n>&,
350  const Image<I>& input,
351  unsigned factor,
352  const mln_domain(I)& output_domain,
353  unsigned border_thickness)
354  {
355  return impl::antialiased_2d_fastest_rgb(input, factor,
356  output_domain,
357  border_thickness);
358  }
359 
360 
361  template <typename I>
362  inline
363  mln_concrete(I)
364  antialiased_2d_fastest_dispatch(const Image<I>& input,
365  unsigned factor,
366  const mln_domain(I)& output_domain,
367  unsigned border_thickness)
368  {
369  typedef mln_value(I) V;
370  return antialiased_2d_fastest_dispatch(V(), input, factor,
371  output_domain,
372  border_thickness);
373  }
374 
375 
376  template <typename I>
377  inline
378  mln_concrete(I)
379  antialiased_dispatch_2d(trait::image::value_alignment::with_grid,
380  trait::image::value_storage::one_block,
381  trait::image::value_access::direct,
382  const Image<I>& input,
383  unsigned factor,
384  const mln_domain(I)& output_domain,
385  unsigned border_thickness)
386  {
387  return antialiased_2d_fastest_dispatch(input, factor,
388  output_domain,
389  border_thickness);
390  }
391 
392 
393  template <typename I>
394  inline
395  mln_concrete(I)
396  antialiased_dispatch(const Image<I>& input,
397  unsigned factor,
398  const mln_domain(I)& output_domain,
399  unsigned border_thickness)
400  {
401  unsigned dim = mln_site_(I)::dim;
402 
403  if (dim == 2)
404  return antialiased_dispatch_2d(
405  mln_trait_image_value_alignment(I)(),
406  mln_trait_image_value_storage(I)(),
407  mln_trait_image_value_access(I)(),
408  input,
409  factor,
410  output_domain,
411  border_thickness);
412  else
413  trace::warning("Not implemented yet.");
414 
415  mln_concrete(I) output;
416  return output;
417  }
418 
419  } // end of namespace mln::subsampling::internal
420 
421 
422 
423  // Facades.
424 
425  template <typename I>
426  inline
427  mln_concrete(I)
428  antialiased(const Image<I>& input,
429  unsigned factor,
430  const mln_domain(I)& output_domain,
431  unsigned border_thickness)
432  {
433  trace::entering("subsampling::antialiased");
434 
435  typedef mln_site(I) P;
436 
437  internal::antialiased_tests(input, factor,
438  output_domain, border_thickness);
439 
440  mln_concrete(I)
441  output = internal::antialiased_dispatch(input, factor,
442  output_domain,
443  border_thickness);
444 
445  trace::exiting("subsampling::antialiased");
446  return output;
447  }
448 
449 
450  template <typename I>
451  inline
452  mln_concrete(I)
453  antialiased(const Image<I>& input, unsigned factor)
454  {
455  mln_domain(I) domain;
456  return antialiased(input, factor, domain, border::thickness);
457  }
458 
459 
460 
461 # endif // ! MLN_INCLUDE_ONLY
462 
463  } // end of namespace mln::subsampling
464 
465 } // end of namespace mln
466 
467 
468 #endif // ! MLN_SUBSAMPLING_ANTIALIASED_HH