26 #ifndef SCRIBO_UTIL_COMPONENT_PRECISE_OUTLINE_HH
27 # define SCRIBO_UTIL_COMPONENT_PRECISE_OUTLINE_HH
38 # include <mln/io/pbm/load.hh>
39 # include <mln/literal/colors.hh>
40 # include <mln/io/ppm/save.hh>
41 # include <mln/data/convert.hh>
42 # include <mln/opt/at.hh>
43 # include <mln/extension/adjust_fill.hh>
47 #include <mln/io/pgm/save.hh>
48 #include <mln/data/wrap.hh>
49 #include <mln/data/convert.hh>
63 component_precise_outline(
const Image<I>& input_,
const mln_value(I)&
id,
64 bool compress_points);
68 component_precise_outline(
const Image<I>& input_,
const mln_value(I)&
id);
72 component_precise_outline(
const Image<I>& input_);
75 # ifndef MLN_INCLUDE_ONLY
81 static const int offset[4][8][2] =
83 { { -1, 0 }, { 0, -1 }, { -1, -1 }, { 1, 0 }, { 1, -1 }, { 0, 1 }, {
85 { { 0, -1 }, { 1, 0 }, { 1, -1 }, { 0, 1 }, { 1, 1 }, { -1, 0 }, {
86 -1, 1 }, { -1, -1 } },
87 { { 1, 0 }, { 0, 1 }, { 1, 1 }, { -1, 0 }, { -1, 1 }, { 0, -1 }, {
88 -1, -1 }, { 1, -1 } },
89 { { 0, 1 }, { -1, 0 }, { -1, 1 }, { 0, -1 }, { -1, -1 }, { 1, 0 }, {
96 find_first_point(
const I& input,
98 const mln_value(I)&
id)
106 if (opt::at(input, mid_row, i) == id)
115 template <
typename I>
117 left_up(
int& direction,
120 const mln_value(I)&
id)
122 const point2d p2(cur_pt.
row() + offset[direction][5][1],
123 cur_pt.
col() + offset[direction][5][0]);
124 const point2d p3(cur_pt.
row() + offset[direction][7][1],
125 cur_pt.
col() + offset[direction][7][0]);
127 if ((input.has(p2) && input(p2) != id) && (input.has(p3) && input(p3) == id))
136 left_up_after(
int& direction,
139 if (i == 3 || i == 4)
141 else if (i == 5 || i == 6)
147 template <
typename I>
149 right_up(
int& direction,
152 const mln_value(I)&
id)
154 const point2d p1(cur_pt.
row() + offset[direction][0][1],
155 cur_pt.
col() + offset[direction][0][0]);
156 const point2d p2(cur_pt.
row() + offset[direction][5][1],
157 cur_pt.
col() + offset[direction][5][0]);
158 const point2d p3(cur_pt.
row() + offset[direction][7][1],
159 cur_pt.
col() + offset[direction][7][0]);
161 if ((input(p2) !=
id) && ((input(p1) == id) || (input(p3) == id)))
170 right_up_after(
int& direction,
173 if (i == 3 || i == 4)
175 else if (i == 5 || i == 6)
181 template <
typename I>
183 right_down(
int& direction,
186 const mln_value(I)&
id)
188 const point2d p2(cur_pt.
row() + offset[direction][5][1],
189 cur_pt.
col() + offset[direction][5][0]);
190 const point2d p3(cur_pt.
row() + offset[direction][7][1],
191 cur_pt.
col() + offset[direction][7][0]);
193 if ((input.has(p2) && input(p2) != id) && (input.has(p3) && input(p3) == id))
202 right_down_after(
int& direction,
205 if (i == 3 || i == 4)
207 else if (i == 5 || i == 6)
213 template <
typename I>
215 left_down(
int& direction,
218 const mln_value(I)&
id)
220 const point2d p1(cur_pt.
row() + offset[direction][0][1],
221 cur_pt.
col() + offset[direction][0][0]);
222 const point2d p2(cur_pt.
row() + offset[direction][5][1],
223 cur_pt.
col() + offset[direction][5][0]);
224 const point2d p3(cur_pt.
row() + offset[direction][7][1],
225 cur_pt.
col() + offset[direction][7][0]);
227 if ((input.has(p2) && input(p2) != id)
228 && ((input.has(p1) && input(p1) == id) || (input.has(p3) && input(p3) == id)))
237 left_down_after(
int& direction,
240 if (i == 3 || i == 4)
242 else if (i == 5 || i == 6)
249 template <
typename I>
251 find_next_point(
const I& input,
254 const mln_value(I)&
id)
261 case 0: left_up(direction, input, cur_pt,
id);
break;
262 case 1: right_up(direction , input, cur_pt,
id);
break;
263 case 2: right_down(direction, input, cur_pt,
id);
break;
264 case 3: left_down(direction, input, cur_pt,
id);
break;
269 tmp =
point2d(cur_pt.
row() + offset[direction][i][1],
270 cur_pt.
col() + offset[direction][i][0]);
272 if (input.has(tmp) && input(tmp) == id)
282 case 0: left_up_after(direction, i);
break;
283 case 1: right_up_after(direction , i);
break;
284 case 2: right_down_after(direction, i);
break;
285 case 3: left_down_after(direction, i);
break;
300 const point2d* first_pt = & points[0];
301 const point2d* last_pt = first_pt;
302 waypoints.
append(*first_pt);
304 const point2d* cur_pt = & points[i];
305 bool has_changed =
false;
307 while (i < nelements)
311 while (cur_pt->
row() == first_pt->
row()
312 || cur_pt->
col() == first_pt->
col())
319 const point2d* llast_pt = last_pt;
321 cur_pt = & points[i];
323 if (llast_pt->
col() == last_pt->
col() && last_pt->
col() == cur_pt->
col())
325 if (llast_pt->
row() == cur_pt->
row())
328 else if(llast_pt->
row() == last_pt->
row() && last_pt->
row() == cur_pt->
row())
330 if (llast_pt->
col() == cur_pt->
col())
340 cur_pt = & points[i];
346 waypoints.
append(*last_pt);
351 waypoints.
append(*cur_pt);
355 for (
unsigned i = 0; i < nelements; ++i)
356 waypoints.
append(points[i]);
362 template <
typename I>
364 component_precise_outline(
const Image<I>& input_,
const mln_value(I)&
id,
365 bool compress_points)
367 mln_trace(
"scribo::util::component_precise_outline");
369 const I& input =
exact(input_);
370 typedef mln_site(I) P;
375 points.reserve(std::
max(geom::
ncols(input), geom::
nrows(input)));
380 internal::find_first_point(input, start_pt,
id);
384 internal::find_next_point(input, cur_pt, direction,
id);
385 points.append(cur_pt);
387 while (cur_pt != start_pt)
389 internal::find_next_point(input, cur_pt, direction,
id);
390 points.append(cur_pt);
393 internal::find_next_point(input, cur_pt, direction,
id);
395 const std::vector<point2d>& vec_points = points.hook_std_vector_();
398 vec_points.end(), cur_pt) == vec_points.end())
400 points.append(cur_pt);
402 while (cur_pt != start_pt)
404 internal::find_next_point(input, cur_pt, direction,
id);
405 points.append(cur_pt);
412 internal::filter_points(points, waypoints);
420 template <
typename I>
422 component_precise_outline(
const Image<I>& input,
const mln_value(I)&
id)
424 return component_precise_outline(input,
id,
true);
427 template <
typename I>
429 component_precise_outline(
const Image<I>& input)
431 return component_precise_outline(input,
true,
true);
434 # endif // ! MLN_INCLUDE_ONLY
440 #endif // ! SCRIBO_UTIL_COMPONENT_PRECISE_OUTLINE_HH