Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
border/duplicate.hh
1 // Copyright (C) 2007, 2008, 2009, 2011 EPITA Research and Development
2 // Laboratory (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_BORDER_DUPLICATE_HH
28 # define MLN_BORDER_DUPLICATE_HH
29 
33 
34 # include <mln/core/concept/image.hh>
35 # include <mln/core/routine/primary.hh>
36 # include <mln/core/box_runstart_piter.hh>
37 # include <mln/border/get.hh>
38 # include <mln/opt/element.hh>
39 
40 
41 namespace mln
42 {
43 
44  namespace border
45  {
46 
56  template <typename I>
57  void duplicate(const Image<I>& ima);
58 
59 
60 # ifndef MLN_INCLUDE_ONLY
61 
62  namespace impl
63  {
64 
65  template <typename I>
66  inline
67  void duplicate_1D(I& ima)
68  {
69  trace::entering("border::impl::duplicate_1D");
70 
71  typedef mln_psite(I) P;
72  mln_box_runstart_piter(I) pl(ima.domain());
73  unsigned len_c = ima.bbox().len(P::dim - 1);
74  unsigned border = ima.border();
75 
76  for (unsigned i = 0; i < border; ++i)
77  opt::element(ima, i) = opt::element(ima, border);
78 
79  unsigned st = border + len_c - 1;
80  for (unsigned i = st + 1; i < opt::nelements(ima); ++i)
81  opt::element(ima, i) = opt::element(ima, st);
82 
83  trace::exiting("border::impl::duplicate_1D");
84  }
85 
86  template <typename I>
87  inline
88  void duplicate_2D(I& ima)
89  {
90  trace::entering("border::impl::duplicate_2D");
91 
92  typedef mln_psite(I) P;
93  mln_box_runstart_piter(I) pl(ima.domain());
94  unsigned border = ima.border();
95  unsigned border_2x = 2 * ima.border();
96  unsigned len_c = ima.bbox().len(1);
97  unsigned len_r = ima.bbox().len(0);
98  unsigned real_len_c = len_c + border_2x;
99  unsigned st;
100 
101  // Duplicate
102  for_all (pl)
103  {
104  st = ima.index_of_point (pl);
105  for (unsigned i = 1; i <= border; ++i)
106  opt::element(ima, st - i) = opt::element(ima, st);
107  st = st + len_c - 1;
108  for (unsigned i = 1; i <= border; ++i)
109  opt::element(ima, st + i) = opt::element(ima, st);
110  }
111 
112  // Duplicate n first * border line
113  st = real_len_c * border;
114  for (unsigned k = 0; k < border; ++k)
115  for (unsigned i = 0; i < real_len_c; ++i)
116  opt::element(ima, k * real_len_c + i) = opt::element(ima, st + i);
117 
118  // Duplicate n last * border line
119  st = real_len_c * (border + len_r - 1);
120  for (unsigned k = 1; k <= border; ++k)
121  for (unsigned i = st; i < st + real_len_c; ++i)
122  opt::element(ima, k * real_len_c + i) = opt::element(ima, i);
123 
124  trace::exiting("border::impl::duplicate_2D");
125  }
126 
127  template <typename I>
128  inline
129  void duplicate_3D(I& ima)
130  {
131  trace::entering("border::impl::duplicate_3D");
132 
133  mln_precondition(ima.is_valid());
134 
135  typedef mln_psite(I) P;
136  mln_box_runstart_piter(I) pl(ima.domain());
137  unsigned border = ima.border();
138  unsigned border_2x = 2 * ima.border();
139  unsigned len_c = ima.bbox().len(P::dim - 1);
140  unsigned len_r = ima.bbox().len(1);
141  unsigned len_s = ima.bbox().len(0);
142  unsigned real_len_c = len_c + border_2x;
143  unsigned real_len_r = len_r + border_2x;
144  unsigned face = real_len_c * real_len_r;
145  unsigned st;
146 
147  pl.start();
148 
149  for (unsigned k = 0; k < len_s; ++k)
150  {
151 
152  // Duplicate
153  for (unsigned j = 0; j < len_r; ++j)
154  {
155  st = ima.index_of_point (pl);
156  for (unsigned i = 1; i <= border; ++i)
157  opt::element(ima, st - i) = opt::element(ima, st);
158  st = st + len_c - 1;
159  for (unsigned i = 1; i <= border; ++i)
160  opt::element(ima, st + i) = opt::element(ima, st);
161  pl.next();
162  }
163 
164  // Duplicate n last * border line
165  st = border * face + k * face + border * real_len_c ;
166  for (unsigned j = 1; j <= border; ++j)
167  for (unsigned i = 0; i < real_len_c; ++i)
168  opt::element(ima, st - j * real_len_c + i) =
169  opt::element(ima, st + i);
170 
171  // Duplicate n last * border line
172  st = border * face + k * face + (len_r + border - 1) * real_len_c ;
173  for (unsigned j = 1; j <= border; ++j)
174  for (unsigned i = 0; i < real_len_c; ++i)
175  opt::element(ima, st + j * real_len_c + i) =
176  opt::element(ima, st + i);
177  }
178 
179  // Duplicate n first * border face
180  st = border * face;
181  for (unsigned k = 0; k < border; ++k)
182  for (unsigned i = 0; i < face; ++i)
183  opt::element(ima, k * face + i) = opt::element(ima, st + i);
184 
185  // Duplicate n last * border face
186  st = (len_s + border - 1) * face;
187  for (unsigned k = 1; k <= border; ++k)
188  for (unsigned i = 0; i < face; ++i)
189  opt::element(ima, st + k * face + i) = opt::element(ima, st + i);
190 
191  trace::exiting("border::impl::duplicate_3D");
192  }
193 
194  } // end of namespace mln::border::impl
195 
196 
197  namespace internal
198  {
199 
200  template <typename I>
201  void duplicate_dispatch_on(metal::int_<1>, I& ima)
202  {
203  impl::duplicate_1D(ima);
204  }
205 
206  template <typename I>
207  void duplicate_dispatch_on(metal::int_<2>, I& ima)
208  {
209  impl::duplicate_2D(ima);
210  }
211 
212  template <typename I>
213  void duplicate_dispatch_on(metal::int_<3>, I& ima)
214  {
215  impl::duplicate_3D(ima);
216  }
217 
218  template <typename I>
219  void duplicate_dispatch_on(trait::image::speed::fastest,
220  const Image<I>& ima)
221  {
222  typedef mln_site(I) P;
223  duplicate_dispatch_on(metal::int_<P::dim>(),
224  const_cast<I&>(exact(ima)));
225  }
226 
227  template <typename I>
228  void duplicate_dispatch_on(trait::image::speed::any,
229  const Image<I>& ima)
230  {
231  (void) ima;
232  // No-op.
233  }
234 
235  template <typename I>
236  void duplicate_dispatch_on(const Image<I>& ima)
237  {
238  duplicate_dispatch_on(mln_trait_image_speed(I)(),
239  ima);
240  }
241 
242  template <typename I>
243  void duplicate_dispatch(const Image<I>& ima)
244  {
245  duplicate_dispatch_on(primary(ima));
246  }
247 
248  } // end of namespace mln::border::internal
249 
250 
251  // Facade.
252 
253  template <typename I>
254  void duplicate(const Image<I>& ima)
255  {
256  trace::entering("border::duplicate");
257  mln_precondition(exact(ima).is_valid());
258 
259  if (border::get(ima) != 0)
260  internal::duplicate_dispatch(ima);
261 
262  trace::exiting("border::duplicate");
263  }
264 
265 
266 # endif // ! MLN_INCLUDE_ONLY
267 
268  } // end of namespace mln::border
269 
270 } // end of namespace mln
271 
272 
273 #endif // ! MLN_BORDER_DUPLICATE_HH