Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
enlarge.hh
1 // Copyright (C) 2009, 2011 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_WORLD_BINARY_2D_ENLARGE_HH
28 # define MLN_WORLD_BINARY_2D_ENLARGE_HH
29 
35 
36 
37 # include <iostream>
38 
39 # include <mln/core/image/image2d.hh>
40 # include <mln/core/routine/initialize.hh>
41 
42 # include <mln/value/int_u8.hh>
43 # include <mln/fun/p2v/ternary.hh>
44 # include <mln/fun/v2b/threshold.hh>
45 
46 # include <mln/data/transform.hh>
47 
48 # include <mln/pw/image.hh>
49 # include <mln/pw/cst.hh>
50 # include <mln/pw/value.hh>
51 # include <mln/opt/at.hh>
52 
53 # include <mln/geom/min_row.hh>
54 # include <mln/geom/min_col.hh>
55 
56 # include <mln/core/routine/duplicate.hh>
57 
58 
59 namespace mln
60 {
61 
62  namespace world
63  {
64 
65  namespace binary_2d
66  {
67 
74  //
75  template <typename I>
76  mln_concrete(I)
77  enlarge(const Image<I>& input, unsigned n);
78 
79 
80 # ifndef MLN_INCLUDE_ONLY
81 
82 
83  // Internal routines.
84 
85  namespace internal
86  {
87 
88  inline
89  float
90  val(bool b)
91  {
92  return b ? 1 : 0;
93  }
94 
95  inline
96  int
97  do_threshold(float value)
98  {
99  return static_cast<int>(255.f * value);
100  }
101 
102  } // end of namespace mln::world::binary_2d
103 
104 
105 
106 
107  // Implementation.
108 
109  namespace impl
110  {
111 
113  inline
114  image2d<value::int_u8>
115  enlargex2(const image2d<bool>& input)
116  {
117  using value::int_u8;
118 
119  mln_precondition(input.is_valid());
120 
121  def::coord
122  mrow = geom::min_row(input),
123  mcol = geom::min_col(input);
124 
125  image2d<int_u8> output(make::box2d(mrow, mcol,
126  mrow + 2 * input.nrows() - 1,
127  mcol + 2 * input.ncols() - 1));
128  float value;
129 
130  // row 0
131  opt::at(output, mrow, mcol) = internal::do_threshold(opt::at(input, mrow, mcol));
132 
133  for (unsigned col = 2; col < output.ncols(); col += 2)
134  {
135  value = internal::val(opt::at(input, mrow, mcol + col / 2));
136  value += internal::val(opt::at(input, mrow, mcol + col / 2 - 1));
137  opt::at(output, mrow, mcol + col) = internal::do_threshold(value / 2);
138  }
139 
140  for (unsigned col = 1; col < output.ncols(); col += 2)
141  opt::at(output, mrow, mcol + col)
142  = internal::do_threshold(opt::at(input, mrow, mcol + col / 2));
143 
144  // col 0
145 
146  for (unsigned row = 2; row < output.nrows(); row += 2)
147  {
148  value = internal::val(opt::at(input, mrow + row / 2, mcol));
149  value += internal::val(opt::at(input, mrow + row / 2 - 1, mcol));
150  opt::at(output, mrow + row, mcol) = internal::do_threshold(value / 2);
151  }
152 
153  for (unsigned row = 1; row < output.nrows(); row += 2)
154  opt::at(output, mrow + row, mcol)
155  = internal::do_threshold(opt::at(input, mrow + row / 2, mcol));
156 
157  // others
158 
159  for (unsigned row = 2; row < output.nrows(); row += 2)
160  {
161  for (unsigned col = 2; col < output.ncols(); col += 2)
162  {
163  value = internal::val(opt::at(input, mrow + row / 2, mcol + col / 2));
164  value += internal::val(opt::at(input, mrow + row / 2 - 1, mcol + col / 2));
165  value += internal::val(opt::at(input, mrow + row / 2, mcol + col / 2 - 1));
166  value += internal::val(opt::at(input, mrow + row / 2 - 1, mcol + col / 2 - 1));
167  opt::at(output, mrow + row, mcol + col)
168  = internal::do_threshold(value / 4);
169  }
170  for (unsigned col = 1; col < output.ncols(); col += 2)
171  {
172  value = internal::val(opt::at(input, mrow + row / 2, mcol + col / 2));
173  value += internal::val(opt::at(input, mrow + row / 2 - 1, mcol + col / 2));
174  opt::at(output, mrow + row, mcol + col) = internal::do_threshold(value / 2);
175  }
176  }
177 
178  for (unsigned row = 1; row < output.nrows(); row += 2)
179  {
180  for (unsigned col = 2; col < output.ncols(); col += 2)
181  {
182  value = internal::val(opt::at(input, mrow + row / 2, mcol + col / 2));
183  value += internal::val(opt::at(input, mrow + row / 2, mcol + col / 2 - 1));
184  opt::at(output, mrow + row, mcol + col) = internal::do_threshold(value / 2);
185  }
186  for (unsigned col = 1; col < output.ncols(); col += 2)
187  opt::at(output, mrow + row, mcol + col)
188  = internal::do_threshold(opt::at(input, mrow + row / 2, mcol + col / 2));
189  }
190 
191  return output;
192  }
193 
194 
195 
196  inline
197  image2d<value::int_u8>
198  enlargex2(const image2d<value::int_u8>& input)
199  {
200  using value::int_u8;
201 
202  unsigned
203  mrow = geom::min_row(input),
204  mcol = geom::min_col(input);
205 
206  image2d<int_u8> output(make::box2d(mrow, mcol,
207  mrow + 2 * input.nrows() - 1,
208  mcol + 2 * input.ncols() - 1));
209  unsigned value;
210 
211  // row 0
212  opt::at(output, mrow, mcol) = (opt::at(input, mrow, mcol));
213 
214  for (unsigned col = 2; col < output.ncols(); col += 2)
215  {
216  value = (opt::at(input, mrow, mcol + col / 2));
217  value += (opt::at(input, mrow, mcol + col / 2 - 1));
218  opt::at(output, mrow, mcol + col) = (value / 2);
219  }
220 
221  for (unsigned col = 1; col < output.ncols(); col += 2)
222  opt::at(output, mrow, mcol + col) = (opt::at(input, mrow, mcol + col / 2));
223 
224  // col 0
225 
226  for (unsigned row = 2; row < output.nrows(); row += 2)
227  {
228  value = (opt::at(input, mrow + row / 2, mcol));
229  value += (opt::at(input, mrow + row / 2 - 1, mcol));
230  opt::at(output, mrow + row, mcol) = (value / 2);
231  }
232 
233  for (unsigned row = 1; row < output.nrows(); row += 2)
234  opt::at(output, mrow + row, mcol) = (opt::at(input, mrow + row / 2, mcol));
235 
236  // others
237 
238  for (unsigned row = 2; row < output.nrows(); row += 2)
239  {
240  for (unsigned col = 2; col < output.ncols(); col += 2)
241  {
242  value = (opt::at(input, mrow + row / 2, mcol + col / 2));
243  value += (opt::at(input, mrow + row / 2 - 1, mcol + col / 2));
244  value += (opt::at(input, mrow + row / 2, mcol + col / 2 - 1));
245  value += (opt::at(input, mrow + row / 2 - 1, mcol + col / 2 - 1));
246  opt::at(output, mrow + row, mcol + col) = ((unsigned(value)+2) / 4);
247  }
248  for (unsigned col = 1; col < output.ncols(); col += 2)
249  {
250  value = (opt::at(input, mrow + row / 2, mcol + col / 2));
251  value += (opt::at(input, mrow + row / 2 - 1, mcol + col / 2));
252  opt::at(output, mrow + row, mcol + col) = (value / 2);
253  }
254  }
255 
256  for (unsigned row = 1; row < output.nrows(); row += 2)
257  {
258  for (unsigned col = 2; col < output.ncols(); col += 2)
259  {
260  value = (opt::at(input, mrow + row / 2, mcol + col / 2));
261  value += (opt::at(input, mrow + row / 2, mcol + col / 2 - 1));
262  opt::at(output, mrow + row, mcol + col) = (value / 2);
263  }
264  for (unsigned col = 1; col < output.ncols(); col += 2)
265  opt::at(output, mrow + row, mcol + col)
266  = (opt::at(input, mrow + row / 2, mcol + col / 2));
267  }
268 
269  return output;
270  }
271 
272 
273  template <typename I>
274  inline
275  mln_ch_value(I,value::int_u8)
276  do_enlarge_gl(const I& input, unsigned n)
277  {
278  using value::int_u8;
279 
280  mln_ch_value(I,int_u8) output = enlargex2(input);
281 
282  while (--n)
283  output = enlargex2(output);
284 
285  return output;
286  }
287 
288 
289  template <typename I>
290  inline
291  mln_concrete(I)
292  do_enlarge_bool(const I& input, unsigned n)
293  {
294  mln_ch_value(I,value::int_u8) tmp = do_enlarge_gl(input, n);
295  I output
296  = data::transform(tmp, fun::v2b::threshold<value::int_u8>(150));
297  return output;
298  }
299 
300 
301  } // end of namespace mln::world::binary_2d::impl
302 
303 
304 
305 
306  // Dispatch
307 
308  namespace internal
309  {
310 
311  template<typename I>
312  inline
313  mln_concrete(I)
314  enlarge_dispatch(const I& input, const bool&, unsigned n)
315  {
316  return impl::do_enlarge_bool(input, n);
317  }
318 
319  template<typename I>
320  inline
321  mln_concrete(I)
322  enlarge_dispatch(const I& input, const value::int_u8&, unsigned n)
323  {
324  return impl::do_enlarge_gl(input, n);
325  }
326 
327  template<typename I>
328  inline
329  mln_concrete(I)
330  enlarge_dispatch(const I& input, const mln_value(I)&, unsigned n)
331  {
332  (void) input;
333  (void) n;
334 
335  mlc_abort(I)::check();
336  return mln_concrete(I)();
337  }
338 
339  template<typename I>
340  inline
341  mln_concrete(I)
342  enlarge_dispatch(const Image<I>& input, unsigned n)
343  {
344  return enlarge_dispatch(exact(input), mln_value(I)(), n);
345  }
346 
347  } // end of namespace mln::world::binary_2d::internal
348 
349 
350 
351  // Facade
352 
353  template <typename I>
354  inline
355  mln_concrete(I)
356  enlarge(const Image<I>& input, unsigned n)
357  {
358  trace::entering("mln::world::binary_2d::enlarge");
359 
360  mln_precondition(exact(input).is_valid());
361  typedef mln_site(I) S;
362  mlc_bool(S::dim == 2)::check();
363 
364  mln_concrete(I) output;
365  if (n == 0)
366  output = duplicate(input);
367  else
368  output = internal::enlarge_dispatch(input, n);
369 
370  trace::exiting("mln::world::binary_2d::enlarge");
371  return output;
372  }
373 
374 
375 # endif // ! MLN_INCLUDE_ONLY
376 
377  } // end of namespace mln::world::binary_2d
378 
379  } // end of namespace mln::world
380 
381 } // mln
382 
383 #endif // ! MLN_WORLD_BINARY_2D_ENLARGE_HH