1 /************************************************************************/
2 /* */
3 /* Copyright 1998-2005 by Hans Meine, Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35
36 #ifndef VIGRA_PIXELNEIGHBORHOOD_HXX
37 #define VIGRA_PIXELNEIGHBORHOOD_HXX
38
39 #include "utilities.hxx"
40
41 namespace vigra {
42
43 /** \addtogroup PixelNeighborhood Utilities to manage pixel neighborhoods
44
45 4- and 8-neighborhood definitions and circulators.
46
47 <b>\#include</b> \<vigra/pixelneighborhood.hxx\><br>
48
49 <b>See also:</b> \ref vigra::NeighborhoodCirculator
50 */
51 //@{
52
53 /********************************************************/
54 /* */
55 /* AtImageBorder */
56 /* */
57 /********************************************************/
58
59 /** \brief Encode whether a point is near the image border.
60
61 This enum is used with \ref isAtImageBorder() and
62 \ref vigra::RestrictedNeighborhoodCirculator.
63
64 <b>\#include</b> \<vigra/pixelneighborhood.hxx\><br>
65 Namespace: vigra
66 */
67
68 enum AtImageBorder
69 {
70 NotAtBorder = 0, ///<
71 RightBorder = 1, ///<
72 LeftBorder = 2, ///<
73 TopBorder = 4, ///<
74 BottomBorder = 8, ///<
75 FrontBorder = 16, ///<
76 RearBorder = 32,
77 TopRightBorder = TopBorder | RightBorder, //5
78 TopLeftBorder = TopBorder | LeftBorder, //6
79 TopFrontBorder = TopBorder | FrontBorder, //20
80 TopRearBorder = TopBorder | RearBorder, //36
81 BottomLeftBorder = BottomBorder | LeftBorder, //10
82 BottomRightBorder = BottomBorder | RightBorder, //9
83 BottomFrontBorder = BottomBorder | FrontBorder, //24
84 BottomRearBorder = BottomBorder | RearBorder, //40
85 FrontLeftBorder = FrontBorder | LeftBorder, //18
86 FrontRightBorder = FrontBorder | RightBorder, //17
87 RearLeftBorder = RearBorder | LeftBorder, //34
88 RearRightBorder = RearBorder | RightBorder, //33
89
90 TopRightFrontBorder = TopBorder | RightBorder | FrontBorder, //21
91 TopLeftFrontBorder = TopBorder | LeftBorder | FrontBorder, //22
92 BottomLeftFrontBorder = BottomBorder | LeftBorder | FrontBorder, //26
93 BottomRightFrontBorder = BottomBorder | RightBorder | FrontBorder, //25
94 TopRightRearBorder = TopBorder | RightBorder | RearBorder, //37
95 TopLeftRearBorder = TopBorder | LeftBorder | RearBorder, //38
96 BottomLeftRearBorder = BottomBorder | LeftBorder | RearBorder, //42
97 BottomRightRearBorder = BottomBorder | RightBorder | RearBorder //41
98 };
99
100
101 /** \brief Find out whether a point is at the image border.
102
103 This function checks if \a x == 0 or \a x == \a width - 1 and
104 \a y == 0 or \a y == \a height - 1 and returns the appropriate value
105 of \ref vigra::AtImageBorder, or zero when the point is not at the image border.
106 The behavior of the function is undefined if (x,y) is not inside the image.
107
108 <b>\#include</b> \<vigra/pixelneighborhood.hxx\><br>
109 Namespace: vigra
110 */
isAtImageBorder(int x,int y,int width,int height)111 inline AtImageBorder isAtImageBorder(int x, int y, int width, int height)
112 {
113 return static_cast<AtImageBorder>((x == 0
114 ? LeftBorder
115 : x == width-1
116 ? RightBorder
117 : NotAtBorder) |
118 (y == 0
119 ? TopBorder
120 : y == height-1
121 ? BottomBorder
122 : NotAtBorder));
123 }
124
125 /********************************************************/
126 /* */
127 /* FourNeighborhood */
128 /* */
129 /********************************************************/
130
131 /** Utilities for 4-neighborhood. */
132 namespace FourNeighborhood
133 {
134
135 /** \brief Encapsulation of direction management for 4-neighborhood.
136
137 This helper class allows the transformation between Freeman chain codes
138 (East = 0, North = 1 etc.) and the corresponding Diff2D instances
139 and back.
140
141 You can either use the chain codes by explicit qualification:
142
143 \code
144 // the following three lines are equivalent
145 FourNeighborhood::NeighborCode::Direction d = FourNeighborhood::NeighborCode::East;
146 FourNeighborCode::Direction d = FourNeighborCode::East;
147 FourNeighborhood::Direction d = FourNeighborhood::East;
148 \endcode
149
150 or you can fix 4-neighborhood by importing the entire namespace in
151 your function:
152
153 \code
154 using namespace FourNeighborhood;
155
156 Direction d = East;
157 \endcode
158
159 If you want to pass 4-neighborhood codes as a template parameter, use
160 the class FourNeighborhood::NeighborCode.
161
162 <b>\#include</b> \<vigra/pixelneighborhood.hxx\><br>
163 Namespace: vigra::FourNeighborhood
164 */
165 class NeighborCode
166 {
167 public:
168
169 typedef Diff2D difference_type;
170
171 /** Freeman direction codes for the 4-neighborhood.
172 <tt>East = 0</tt>, <tt>North = 1</tt> etc.
173 <tt>DirectionCount</tt> may be used for portable loop termination conditions.
174 <tt>CausalFirst</tt> and <tt>CausalLast</tt> are the first and last (inclusive)
175 neighbors in the causal neighborhood, i.e. in the set of neighbors that have
176 already been visited when the image is traversed in scan order.
177 <tt>AntiCausalFirst</tt> and <tt>AntiCausalLast</tt> are the opposite.
178 */
179 enum Direction {
180 Error = -1, ///<
181 East = 0, ///<
182 North, ///<
183 West, ///<
184 South, ///<
185 DirectionCount, ///<
186 CausalFirst = North, ///<
187 CausalLast = West, ///<
188 AntiCausalFirst = South, ///<
189 AntiCausalLast = East, ///<
190
191 InitialDirection = East,
192 OppositeDirPrefix = 1,
193 OppositeOffset = West
194 };
195
196 template <int DUMMY>
197 struct StaticData
198 {
199 static unsigned int b[];
200 static unsigned int c[];
201 static Direction bd[11][4];
202 static Diff2D d[];
203 static Diff2D rd[][4];
204 };
205
directionBit(Direction d)206 static unsigned int directionBit(Direction d)
207 {
208 return StaticData<0>::b[d];
209 };
210
211 /** The number of valid neighbors if the current center is at the image border.
212 */
nearBorderDirectionCount(AtImageBorder b)213 static unsigned int nearBorderDirectionCount(AtImageBorder b)
214 {
215 return StaticData<0>::c[b];
216 }
217
218 /** The valid direction codes when the center is at the image border.
219 \a index must be in the range <tt>0...nearBorderDirectionCount(b)-1</tt>.
220 */
nearBorderDirections(AtImageBorder b,int index)221 static Direction nearBorderDirections(AtImageBorder b, int index)
222 {
223 return StaticData<0>::bd[b][index];
224 }
225
226 /** Transform direction code into corresponding Diff2D offset.
227 (note: there is no bounds checking on the code you pass.)
228 */
diff(Direction code)229 static Diff2D const & diff(Direction code)
230 {
231 return StaticData<0>::d[code];
232 }
233
234 /** Equivalent to <tt>diff(static_cast<Direction>(code))</tt>.
235 (note: there is no bounds checking on the code you pass.)
236 */
diff(int code)237 static Diff2D const & diff(int code) { return diff(static_cast<Direction>(code)); }
238
239 /** Get the relative offset from one neighbor to the other.
240 For example, <tt>relativeDiff(East, West) == Diff2D(-2,0)</tt>.
241 (note: there is no bounds checking on the code you pass.)
242 */
relativeDiff(Direction fromCode,Direction toCode)243 static Diff2D const & relativeDiff(Direction fromCode, Direction toCode)
244 {
245 return StaticData<0>::rd[fromCode][toCode];
246 }
247
248 /** Equivalent to relativeDiff(static_cast<Direction>(fromCode), static_cast<Direction>(toCode)).
249 (note: there is no bounds checking on the code you pass.)
250 */
relativeDiff(int fromCode,int toCode)251 static Diff2D const & relativeDiff(int fromCode, int toCode)
252 {
253 return relativeDiff(static_cast<Direction>(fromCode), static_cast<Direction>(toCode));
254 }
255
256 /** X-component of diff() */
dX(Direction code)257 static int dX(Direction code) { return diff(code).x; }
258 /** Y-component of diff() */
dY(Direction code)259 static int dY(Direction code) { return diff(code).y; }
260 /** X-component of diff() */
dX(int code)261 static int dX(int code) { return diff(code).x; }
262 /** Y-component of diff() */
dY(int code)263 static int dY(int code) { return diff(code).y; }
264
265 /** Transform Diff2D offset into corresponding direction code.
266 The code <tt>Direction::Error</tt> will be returned if <tt>diff</tt>
267 is not in the 4-neighborhood.
268 */
code(Diff2D const & diff)269 static Direction code(Diff2D const & diff)
270 {
271 switch(diff.x)
272 {
273 case 0:
274 {
275 switch(diff.y)
276 {
277 case 1:
278 return South;
279 case -1:
280 return North;
281 default:
282 return Error;
283 }
284 }
285 case -1:
286 {
287 return (diff.y == 0) ?
288 West :
289 Error;
290 }
291 case 1:
292 {
293 return (diff.y == 0) ?
294 East :
295 Error;
296 }
297 }
298 return Error;
299 }
300
301 /** Check whether a code refers to a diagonal direction.
302 Useful if you want to abstract the differences between 4- and 8-neighborhood.
303 Always <tt>false</tt> for 4-neighborhood.
304 */
isDiagonal(Direction)305 static bool isDiagonal(Direction) { return false; }
306
right()307 static Diff2D const & right() { return diff(East); } /**< Offset to the right neighbor */
top()308 static Diff2D const & top() { return diff(North); } /**< Offset to the top neighbor */
left()309 static Diff2D const & left() { return diff(West); } /**< Offset to the left neighbor */
bottom()310 static Diff2D const & bottom() { return diff(South); } /**< Offset to the bottom neighbor */
311
east()312 static Diff2D const & east() { return diff(East); } /**< Offset to the east neighbor */
north()313 static Diff2D const & north() { return diff(North); } /**< Offset to the north neighbor */
west()314 static Diff2D const & west() { return diff(West); } /**< Offset to the west neighbor */
south()315 static Diff2D const & south() { return diff(South); } /**< Offset to the south neighbor */
316 };
317
318
319 /** Export NeighborCode::Direction into the scope of namespace FourNeighborhood.
320 */
321 typedef NeighborCode::Direction Direction;
322
323 static const Direction Error = NeighborCode::Error; /**< Export NeighborCode::Error to namespace FourNeighborhood */
324 static const Direction East = NeighborCode::East; /**< Export NeighborCode::East to namespace FourNeighborhood */
325 static const Direction North = NeighborCode::North; /**< Export NeighborCode::North to namespace FourNeighborhood */
326 static const Direction West = NeighborCode::West; /**< Export NeighborCode::West to namespace FourNeighborhood */
327 static const Direction South = NeighborCode::South; /**< Export NeighborCode::South to namespace FourNeighborhood */
328 static const Direction DirectionCount = NeighborCode::DirectionCount; /**< Export NeighborCode::DirectionCount to namespace FourNeighborhood */
329
east()330 inline Diff2D const & east() { return NeighborCode::diff(East); } /**< Offset to the east neighbor */
north()331 inline Diff2D const & north() { return NeighborCode::diff(North); } /**< Offset to the north neighbor */
west()332 inline Diff2D const & west() { return NeighborCode::diff(West); } /**< Offset to the west neighbor */
south()333 inline Diff2D const & south() { return NeighborCode::diff(South); } /**< Offset to the south neighbor */
334
335
336 template <int DUMMY>
337 unsigned int NeighborCode::StaticData<DUMMY>::b[] = {1 << East,
338 1 << North,
339 1 << West,
340 1 << South };
341
342 template <int DUMMY>
343 unsigned int NeighborCode::StaticData<DUMMY>::c[] = { 4, 3, 3, 0, 3, 2, 2, 0, 3, 2, 2};
344
345 template <int DUMMY>
346 Direction NeighborCode::StaticData<DUMMY>::bd[11][4] = {
347 { East, North, West, South},
348 { North, West, South, Error},
349 { East, North, South, Error},
350 { Error, Error, Error, Error},
351 { East, West, South, Error},
352 { West, South, Error, Error},
353 { East, South, Error, Error},
354 { Error, Error, Error, Error},
355 { East, North, West, Error},
356 { North, West, Error, Error},
357 { East, North, Error, Error}
358 };
359
360 template <int DUMMY>
361 Diff2D NeighborCode::StaticData<DUMMY>::d[] = {
362 Diff2D(1, 0), Diff2D(0, -1), Diff2D(-1, 0), Diff2D(0, 1)
363 };
364
365 template <int DUMMY>
366 Diff2D NeighborCode::StaticData<DUMMY>::rd[][4] = {
367 { Diff2D(0, 0), Diff2D(-1, -1), Diff2D(-2, 0), Diff2D(-1, 1) },
368 { Diff2D(1, 1), Diff2D(0, 0), Diff2D(-1, 1), Diff2D(0, 2) },
369 { Diff2D(2, 0), Diff2D(1, -1), Diff2D(0, 0), Diff2D(1, 1) },
370 { Diff2D(1, -1), Diff2D(0, -2), Diff2D(-1, -1), Diff2D(0, 0) }
371 };
372
373 } // namespace FourNeighborhood
374
375
376
377 /** Export \ref vigra::FourNeighborhood::NeighborCode into the scope of namespace vigra.
378 */
379 typedef FourNeighborhood::NeighborCode FourNeighborCode;
380
381 /********************************************************/
382 /* */
383 /* EightNeighborhood */
384 /* */
385 /********************************************************/
386
387 /** Utilities for 8-neighborhood. */
388 namespace EightNeighborhood
389 {
390 /** \brief Encapsulation of direction management for the 8-neighborhood.
391
392 This helper class allows the transformation between Freeman chain codes
393 (East = 0, NorthEast = 1 etc.) and the corresponding Diff2D instances
394 and back.
395
396 You can either use the chain codes by explicit qualification:
397
398 \code
399 // the following three lines are equivalent
400 EightNeighborhood::NeighborCode::Direction d = EightNeighborhood::NeighborCode::East;
401 EightNeighborCode::Direction d = EightNeighborCode::East;
402 EightNeighborhood::Direction d = EightNeighborhood::East;
403 \endcode
404
405 or you can fix 8-neighborhood by importing the entire namespace in
406 your function:
407
408 \code
409 using namespace EightNeighborhood;
410
411 Direction d = East;
412 \endcode
413
414 If you want to pass 8-neighborhood codes as a template parameter, use
415 the class EightNeighborhood::NeighborCode.
416
417 <b>\#include</b> \<vigra/pixelneighborhood.hxx\><br>
418 Namespace: vigra::EightNeighborhood
419 */
420 class NeighborCode
421 {
422 public:
423
424 typedef Diff2D difference_type;
425
426 /** Freeman direction codes for the 8-neighborhood.
427 <tt>East = 0</tt>, <tt>North = 1</tt> etc.
428 <tt>DirectionCount</tt> may be used for portable loop termination conditions.
429 <tt>CausalFirst</tt> and <tt>CausalLast</tt> are the first and last (inclusive)
430 neighbors in the causal neighborhood, i.e. in the set of neighbors that have
431 already been visited when the image is traversed in scan order.
432 <tt>AntiCausalFirst</tt> and <tt>AntiCausalLast</tt> are the opposite.
433 */
434 enum Direction {
435 Error = -1, ///<
436 East = 0, ///<
437 NorthEast, ///<
438 North, ///<
439 NorthWest, ///<
440 West, ///<
441 SouthWest, ///<
442 South, ///<
443 SouthEast, ///<
444 DirectionCount, ///<
445 CausalFirst = NorthEast, ///<
446 CausalLast = West, ///<
447 AntiCausalFirst = SouthWest, ///<
448 AntiCausalLast = East, ///<
449
450 InitialDirection = East,
451 OppositeDirPrefix = 1,
452 OppositeOffset = West
453 };
454
455 template <int DUMMY>
456 struct StaticData
457 {
458 static unsigned int b[];
459 static unsigned int c[];
460 static Direction bd[11][8];
461 static Diff2D d[];
462 static Diff2D rd[][8];
463 };
464
directionBit(Direction d)465 static unsigned int directionBit(Direction d)
466 {
467 return StaticData<0>::b[d];
468 };
469
470 /** The number of valid neighbors if the current center is at the image border.
471 */
nearBorderDirectionCount(AtImageBorder b)472 static unsigned int nearBorderDirectionCount(AtImageBorder b)
473 {
474 return StaticData<0>::c[b];
475 }
476
477 /** The valid direction codes when the center is at the image border.
478 \a index must be in the range <tt>0...nearBorderDirectionCount(b)-1</tt>.
479 */
nearBorderDirections(AtImageBorder b,int index)480 static Direction nearBorderDirections(AtImageBorder b, int index)
481 {
482 return StaticData<0>::bd[b][index];
483 }
484
485 /** Transform direction code into corresponding Diff2D offset.
486 (note: there is no bounds checking on the code you pass.)
487 */
diff(Direction code)488 static Diff2D const & diff(Direction code)
489 {
490 return StaticData<0>::d[code];
491 }
492
493 /** Equivalent to diff(static_cast<Direction>(code)).
494 (note: there is no bounds checking on the code you pass.)
495 */
diff(int code)496 static Diff2D const & diff(int code) { return diff(static_cast<Direction>(code)); }
497
498 /** Get the relative offset from one neighbor to the other.
499 For example, <tt>relativeDiff(East, West) == Diff2D(-2,0)</tt>.
500 (note: there is no bounds checking on the code you pass.)
501 */
relativeDiff(Direction fromCode,Direction toCode)502 static Diff2D const & relativeDiff(Direction fromCode, Direction toCode)
503 {
504 return StaticData<0>::rd[fromCode][toCode];
505 }
506
507 /** Equivalent to relativeDiff(static_cast<Direction>(fromCode), static_cast<Direction>(toCode)).
508 (note: there is no bounds checking on the code you pass.)
509 */
relativeDiff(int fromCode,int toCode)510 static Diff2D const & relativeDiff(int fromCode, int toCode)
511 {
512 return relativeDiff(static_cast<Direction>(fromCode), static_cast<Direction>(toCode));
513 }
514
515 /** X-component of diff() */
dX(Direction code)516 static int dX(Direction code) { return diff(code).x; }
517 /** Y-component of diff() */
dY(Direction code)518 static int dY(Direction code) { return diff(code).y; }
519 /** X-component of diff() */
dX(int code)520 static int dX(int code) { return diff(code).x; }
521 /** Y-component of diff() */
dY(int code)522 static int dY(int code) { return diff(code).y; }
523
524 /** Transform 4-neighborhood code into 8-neighborhood code.
525 */
code(FourNeighborhood::Direction d)526 static Direction code(FourNeighborhood::Direction d)
527 { return static_cast<Direction>(2*d); }
528
529 /** Transform Diff2D offset into corresponding direction code.
530 The code <tt>Direction::Error</tt> will be returned if <tt>diff</tt>
531 is not in the 8-neighborhood.
532 */
code(Diff2D const & diff)533 static Direction code(Diff2D const & diff)
534 {
535 switch(diff.x)
536 {
537 case 0:
538 {
539 switch(diff.y)
540 {
541 case 1:
542 return South;
543 case -1:
544 return North;
545 default:
546 return Error;
547 }
548 }
549 case -1:
550 {
551 switch(diff.y)
552 {
553 case 0:
554 return West;
555 case 1:
556 return SouthWest;
557 case -1:
558 return NorthWest;
559 default:
560 return Error;
561 }
562 }
563 case 1:
564 {
565 switch(diff.y)
566 {
567 case 0:
568 return East;
569 case 1:
570 return SouthEast;
571 case -1:
572 return NorthEast;
573 default:
574 return Error;
575 }
576 }
577 }
578 return Error;
579 }
580
581 /** Check whether a code refers to a diagonal direction.
582 Useful if you want to abstract the differences between 4- and 8-neighborhood.
583 */
isDiagonal(Direction code)584 static bool isDiagonal(Direction code) { return (code % 2) != 0; }
585
right()586 static Diff2D const & right() { return diff(East); } /**< Offset to the right neighbor */
topRight()587 static Diff2D const & topRight() { return diff(NorthEast); } /**< Offset to the topRight neighbor */
top()588 static Diff2D const & top() { return diff(North); } /**< Offset to the top neighbor */
topLeft()589 static Diff2D const & topLeft() { return diff(NorthWest); } /**< Offset to the topLeft neighbor */
left()590 static Diff2D const & left() { return diff(West); } /**< Offset to the left neighbor */
bottomLeft()591 static Diff2D const & bottomLeft() { return diff(SouthWest); } /**< Offset to the bottomLeft neighbor */
bottom()592 static Diff2D const & bottom() { return diff(South); } /**< Offset to the bottom neighbor */
bottomRight()593 static Diff2D const & bottomRight() { return diff(SouthEast); } /**< Offset to the bottomRight neighbor */
594
east()595 static Diff2D const & east() { return diff(East); } /**< Offset to the east neighbor */
northEast()596 static Diff2D const & northEast() { return diff(NorthEast); } /**< Offset to the northEast neighbor */
north()597 static Diff2D const & north() { return diff(North); } /**< Offset to the north neighbor */
northWest()598 static Diff2D const & northWest() { return diff(NorthWest); } /**< Offset to the northWest neighbor */
west()599 static Diff2D const & west() { return diff(West); } /**< Offset to the west neighbor */
southWest()600 static Diff2D const & southWest() { return diff(SouthWest); } /**< Offset to the southWest neighbor */
south()601 static Diff2D const & south() { return diff(South); } /**< Offset to the south neighbor */
southEast()602 static Diff2D const & southEast() { return diff(SouthEast); } /**< Offset to the southEast neighbor */
603 };
604
605 /** Export NeighborCode::Direction into the scope of namespace EightNeighborhood.
606 */
607 typedef NeighborCode::Direction Direction;
608
609 static const Direction East = NeighborCode::East; /**< Export NeighborCode::East to namespace EightNeighborhood */
610 static const Direction NorthEast = NeighborCode::NorthEast; /**< Export NeighborCode::NorthEast to namespace EightNeighborhood */
611 static const Direction North = NeighborCode::North; /**< Export NeighborCode::North to namespace EightNeighborhood */
612 static const Direction NorthWest = NeighborCode::NorthWest; /**< Export NeighborCode::NorthWest to namespace EightNeighborhood */
613 static const Direction West = NeighborCode::West; /**< Export NeighborCode::West to namespace EightNeighborhood */
614 static const Direction SouthWest = NeighborCode::SouthWest; /**< Export NeighborCode::SouthWest to namespace EightNeighborhood */
615 static const Direction South = NeighborCode::South; /**< Export NeighborCode::South to namespace EightNeighborhood */
616 static const Direction SouthEast = NeighborCode::SouthEast; /**< Export NeighborCode::SouthEast to namespace EightNeighborhood */
617 static const Direction DirectionCount = NeighborCode::DirectionCount; /**< Export NeighborCode::DirectionCount to namespace EightNeighborhood */
618
east()619 inline Diff2D const & east() { return NeighborCode::diff(East); } /**< Offset to the east neighbor */
northEast()620 inline Diff2D const & northEast() { return NeighborCode::diff(NorthEast); } /**< Offset to the northEast neighbor */
north()621 inline Diff2D const & north() { return NeighborCode::diff(North); } /**< Offset to the north neighbor */
northWest()622 inline Diff2D const & northWest() { return NeighborCode::diff(NorthWest); } /**< Offset to the northWest neighbor */
west()623 inline Diff2D const & west() { return NeighborCode::diff(West); } /**< Offset to the west neighbor */
southWest()624 inline Diff2D const & southWest() { return NeighborCode::diff(SouthWest); } /**< Offset to the southWest neighbor */
south()625 inline Diff2D const & south() { return NeighborCode::diff(South); } /**< Offset to the south neighbor */
southEast()626 inline Diff2D const & southEast() { return NeighborCode::diff(SouthEast); } /**< Offset to the southEast neighbor */
627
628 template <int DUMMY>
629 unsigned int NeighborCode::StaticData<DUMMY>::b[] = {
630 1 << East,
631 1 << NorthEast,
632 1 << North,
633 1 << NorthWest,
634 1 << West,
635 1 << SouthWest,
636 1 << South,
637 1 << SouthEast};
638
639 template <int DUMMY>
640 unsigned int NeighborCode::StaticData<DUMMY>::c[] = { 8, 5, 5, 0, 5, 3, 3, 0, 5, 3, 3};
641
642 template <int DUMMY>
643 Direction NeighborCode::StaticData<DUMMY>::bd[11][8] = {
644 { East, NorthEast, North, NorthWest, West, SouthWest, South, SouthEast},
645 { North, NorthWest, West, SouthWest, South, Error, Error, Error},
646 { East, NorthEast, North, South, SouthEast, Error, Error, Error},
647 { Error, Error, Error, Error, Error, Error, Error, Error},
648 { East, West, SouthWest, South, SouthEast, Error, Error, Error},
649 { West, SouthWest, South, Error, Error, Error, Error, Error},
650 { East, South, SouthEast, Error, Error, Error, Error, Error},
651 { Error, Error, Error, Error, Error, Error, Error, Error},
652 { East, NorthEast, North, NorthWest, West, Error, Error, Error},
653 { North, NorthWest, West, Error, Error, Error, Error, Error},
654 { East, NorthEast, North, Error, Error, Error, Error, Error}
655 };
656
657 template <int DUMMY>
658 Diff2D NeighborCode::StaticData<DUMMY>::d[] = {
659 Diff2D(1, 0), Diff2D(1, -1), Diff2D(0, -1), Diff2D(-1, -1),
660 Diff2D(-1, 0), Diff2D(-1, 1), Diff2D(0, 1), Diff2D(1, 1)
661 };
662
663 template <int DUMMY>
664 Diff2D NeighborCode::StaticData<DUMMY>::rd[][8] = {
665 { Diff2D(0, 0), Diff2D(0, -1), Diff2D(-1, -1), Diff2D(-2, -1),
666 Diff2D(-2, 0), Diff2D(-2, 1), Diff2D(-1, 1), Diff2D(0, 1) },
667 { Diff2D(0, 1), Diff2D(0, 0), Diff2D(-1, 0), Diff2D(-2, 0),
668 Diff2D(-2, 1), Diff2D(-2, 2), Diff2D(-1, 2), Diff2D(0, 2) },
669 { Diff2D(1, 1), Diff2D(1, 0), Diff2D(0, 0), Diff2D(-1, 0),
670 Diff2D(-1, 1), Diff2D(-1, 2), Diff2D(0, 2), Diff2D(1, 2) },
671 { Diff2D(2, 1), Diff2D(2, 0), Diff2D(1, 0), Diff2D(0, 0),
672 Diff2D(0, 1), Diff2D(0, 2), Diff2D(1, 2), Diff2D(2, 2) },
673 { Diff2D(2, 0), Diff2D(2, -1), Diff2D(1, -1), Diff2D(0, -1),
674 Diff2D(0, 0), Diff2D(0, 1), Diff2D(1, 1), Diff2D(2, 1) },
675 { Diff2D(2, -1), Diff2D(2, -2), Diff2D(1, -2), Diff2D(0, -2),
676 Diff2D(0, -1), Diff2D(0, 0), Diff2D(1, 0), Diff2D(2, 0) },
677 { Diff2D(1, -1), Diff2D(1, -2), Diff2D(0, -2), Diff2D(-1, -2),
678 Diff2D(-1, -1), Diff2D(-1, 0), Diff2D(0, 0), Diff2D(1, 0) },
679 { Diff2D(0, -1), Diff2D(0, -2), Diff2D(-1, -2), Diff2D(-2, -2),
680 Diff2D(-2, -1), Diff2D(-2, 0), Diff2D(-1, 0), Diff2D(0, 0) }
681 };
682
683 } // namespace EightNeighborhood
684
685 /** Export \ref vigra::EightNeighborhood::NeighborCode into the scope of namespace vigra.
686 */
687 typedef EightNeighborhood::NeighborCode EightNeighborCode;
688
689 /********************************************************/
690 /* */
691 /* NeighborOffsetCirculator */
692 /* */
693 /********************************************************/
694
695 /** \brief Circulator that walks around a given location.
696
697 The template parameter defines the kind of neighborhood used, e.g.
698
699 \code
700 NeighborOffsetCirculator<EightNeighborCode> eight_circulator;
701 NeighborOffsetCirculator<FourNeighborCode> four_circulator;
702 \endcode
703
704 Since this circulator doesn't know about the pixels in any particular image,
705 you usually don't use it directly but rather as a base class or helper for
706 neighborhood circulators referring to a particular image (e.g. NeighborhoodCirculator)
707
708 <b>\#include</b> \<vigra/pixelneighborhood.hxx\><br>
709 Namespace: vigra
710 */
711 template<class NEIGHBORCODE>
712 class NeighborOffsetCirculator
713 : public NEIGHBORCODE
714 {
715 public:
716 typedef NEIGHBORCODE NeighborCode;
717
718 /** return type of direction()
719 */
720 typedef typename NEIGHBORCODE::Direction Direction;
721
722 /** the circulator's value type
723 */
724 typedef typename NEIGHBORCODE::difference_type value_type;
725
726 /** the circulator's reference type (return type of <TT>*circ</TT>)
727 */
728 typedef value_type const & reference;
729
730 /** the circulator's index reference type (return type of <TT>circ[n]</TT>)
731 */
732 typedef value_type const & index_reference;
733
734 /** the circulator's pointer type (return type of <TT>operator-></TT>)
735 */
736 typedef value_type const * pointer;
737
738 /** the circulator's difference type (argument type of <TT>circ[diff]</TT>)
739 */
740 typedef int difference_type;
741
742 /** the circulator tag (random access iterator)
743 */
744 typedef random_access_circulator_tag iterator_category;
745
746 protected:
747 Direction direction_;
748
749 public:
750 /** Create circulator referring to the given direction.
751 */
NeighborOffsetCirculator(Direction dir=NEIGHBORCODE::InitialDirection)752 NeighborOffsetCirculator(Direction dir = NEIGHBORCODE::InitialDirection)
753 : direction_(dir)
754 {
755 }
756
757 /** pre-increment */
operator ++()758 NeighborOffsetCirculator & operator++()
759 {
760 direction_ = static_cast<Direction>((direction_+1) % NEIGHBORCODE::DirectionCount);
761 return *this;
762 }
763
764 /** pre-decrement */
operator --()765 NeighborOffsetCirculator & operator--()
766 {
767 direction_ = static_cast<Direction>((direction_ + NEIGHBORCODE::DirectionCount-1) % NEIGHBORCODE::DirectionCount);
768 return *this;
769 }
770
771 /** post-increment */
operator ++(int)772 NeighborOffsetCirculator operator++(int)
773 {
774 NeighborOffsetCirculator ret(*this);
775 operator++();
776 return ret;
777 }
778
779 /** post-decrement */
operator --(int)780 NeighborOffsetCirculator operator--(int)
781 {
782 NeighborOffsetCirculator ret(*this);
783 operator--();
784 return ret;
785 }
786
787 /** add-assignment */
operator +=(difference_type d)788 NeighborOffsetCirculator & operator+=(difference_type d)
789 {
790 direction_ = static_cast<Direction>((direction_ + d) % NEIGHBORCODE::DirectionCount);
791 if(direction_ < 0)
792 direction_ = static_cast<Direction>(direction_ + NEIGHBORCODE::DirectionCount);
793 return *this;
794 }
795
796 /** subtract-assignment */
operator -=(difference_type d)797 NeighborOffsetCirculator & operator-=(difference_type d)
798 {
799 direction_ = static_cast<Direction>((direction_ - d) % NEIGHBORCODE::DirectionCount);
800 if(direction_ < 0)
801 direction_ = static_cast<Direction>(direction_ + NEIGHBORCODE::DirectionCount);
802 return *this;
803 }
804
805 /** addition */
operator +(difference_type d) const806 NeighborOffsetCirculator operator+(difference_type d) const
807 {
808 return NeighborOffsetCirculator(*this) += d;
809 }
810
811 /** subtraction */
operator -(difference_type d) const812 NeighborOffsetCirculator operator-(difference_type d) const
813 {
814 return NeighborOffsetCirculator(*this) -= d;
815 }
816
817 /** Move to the direction that is 'right' relative to the current direction.
818 This is equivalent to <tt>four_circulator--</tt> and
819 <tt>eight_circulator -= 2</tt> respectively.
820 */
turnRight()821 NeighborOffsetCirculator & turnRight()
822 {
823 direction_ = static_cast<Direction>((direction_ + NEIGHBORCODE::South) % NEIGHBORCODE::DirectionCount);
824 return *this;
825 }
826
827 /** Move to the direction that is 'left' relative to the current direction.
828 This is equivalent to <tt>four_circulator++</tt> and
829 <tt>eight_circulator += 2</tt> respectively.
830 */
turnLeft()831 NeighborOffsetCirculator & turnLeft()
832 {
833 direction_ = static_cast<Direction>((direction_ + NEIGHBORCODE::North) % NEIGHBORCODE::DirectionCount);
834 return *this;
835 }
836
837 /** Move to the opposite direction of the current direction.
838 This is equivalent to <tt>four_circulator += 2</tt> and
839 <tt>eight_circulator += 4</tt> respectively.
840 */
turnRound()841 NeighborOffsetCirculator & turnRound()
842 {
843 direction_ = opposite();
844 return *this;
845 }
846
847 /** Move to the given direction.
848 */
turnTo(Direction d)849 NeighborOffsetCirculator & turnTo(Direction d)
850 {
851 direction_ = d;
852 return *this;
853 }
854
855 /** equality */
operator ==(NeighborOffsetCirculator const & o) const856 bool operator==(NeighborOffsetCirculator const & o) const
857 {
858 return direction_ == o.direction_;
859 }
860
861 /** inequality */
operator !=(NeighborOffsetCirculator const & o) const862 bool operator!=(NeighborOffsetCirculator const & o) const
863 {
864 return direction_ != o.direction_;
865 }
866
867 /** subtraction */
operator -(NeighborOffsetCirculator const & o) const868 difference_type operator-(NeighborOffsetCirculator const & o) const
869 {
870 return direction_ - o.direction_;
871 }
872
873 /** dereference */
operator *() const874 reference operator*() const
875 {
876 return diff();
877 }
878
879 /** index */
operator [](difference_type d) const880 index_reference operator[](difference_type d) const
881 {
882 return NEIGHBORCODE::diff(direction(d));
883 }
884
885 /** member access */
operator ->() const886 pointer operator->() const
887 {
888 return &diff();
889 }
890
891 /** Get offset from center to current neighbor.
892 */
diff() const893 reference diff() const
894 {
895 return NEIGHBORCODE::diff(direction_);
896 }
897
898 /** Get offset to given direction.
899 */
diff(Direction dir)900 static reference diff(Direction dir)
901 {
902 return NEIGHBORCODE::diff(dir);
903 }
904
905 /** Get relative distance from current neighbor to neighbor
906 at given offset.
907 */
relativeDiff(difference_type offset) const908 value_type relativeDiff(difference_type offset) const
909 {
910 Direction toDir = static_cast<Direction>((direction_ + offset) % NEIGHBORCODE::DirectionCount);
911 if(toDir < 0)
912 toDir = static_cast<Direction>(toDir + NEIGHBORCODE::DirectionCount);
913 return NEIGHBORCODE::relativeDiff(direction_, toDir);
914 }
915
916 /** X-component of diff() */
dX() const917 int dX() const
918 {
919 return NEIGHBORCODE::dX(direction_);
920 }
921
922 /** Y-component of diff() */
dY() const923 int dY() const
924 {
925 return NEIGHBORCODE::dY(direction_);
926 }
927
928 /** Check whether current direction is a diagonal one.
929 */
isDiagonal() const930 bool isDiagonal() const
931 {
932 return NEIGHBORCODE::isDiagonal(direction_);
933 }
934
935 /** Get current direction.
936 */
direction() const937 Direction direction() const
938 {
939 return direction_;
940 }
941
942 /** Get current direction bit.
943 */
directionBit() const944 unsigned int directionBit() const
945 {
946 return NEIGHBORCODE::directionBit(direction_);
947 }
948
949 /** Get opposite of current direction.
950 */
opposite() const951 Direction opposite() const
952 {
953 return static_cast<Direction>((NEIGHBORCODE::OppositeDirPrefix*direction_ + NEIGHBORCODE::OppositeOffset) % NEIGHBORCODE::DirectionCount);
954 }
955
956 /** Get opposite bit of current direction.
957 */
oppositeDirectionBit() const958 unsigned int oppositeDirectionBit() const
959 {
960 return NEIGHBORCODE::directionBit(opposite());
961 }
962
963 /** Get direction code at offset of current direction.
964 */
direction(difference_type offset) const965 Direction direction(difference_type offset) const
966 {
967 int result = (direction_ + offset) % NEIGHBORCODE::DirectionCount;
968 if(result < 0)
969 result += NEIGHBORCODE::DirectionCount;
970 return static_cast<Direction>(result);
971 }
972 };
973
974 /** Specialization of NeighborOffsetCirculator for 8-neighborhood.
975 */
976 typedef NeighborOffsetCirculator<EightNeighborCode> EightNeighborOffsetCirculator;
977
978 /** Specialization of NeighborOffsetCirculator for 4-neighborhood.
979 */
980 typedef NeighborOffsetCirculator<FourNeighborCode> FourNeighborOffsetCirculator;
981
982
983 //@}
984
985 /** \addtogroup ImageIteratorAdapters
986 */
987 //@{
988
989 /********************************************************/
990 /* */
991 /* NeighborhoodCirculator */
992 /* */
993 /********************************************************/
994
995 /** \brief Circulator that walks around a given location in a given image.
996
997 The template parameters define the kind of neighborhood used and the underlying
998 image. The access functions return the value of the current neighbor pixel.
999 Use <tt>center()</tt> to access the center pixel of the neighborhood.
1000 The center can be changed by calling <tt>moveCenterToNeighbor()</tt>
1001 or <tt>swapCenterNeighbor()</tt>. Note that this circulator cannot be used
1002 when the center is at the image border. You must then use
1003 \ref vigra::RestrictedNeighborhoodCirculator
1004
1005 <b>Usage:</b><br>
1006
1007 <b>\#include</b> \<vigra/pixelneighborhood.hxx\><br>
1008 Namespace: vigra
1009
1010 \code
1011 BImage::traverser upperleft(...), lowerright(...);
1012
1013 int width = lowerright.x - upperleft.x;
1014 int height = lowerright.y - upperleft.y;
1015
1016 ++upperleft.y; // avoid image border
1017 for(int y=1; y<height-1; ++y, ++upperleft.y)
1018 {
1019 BImage::traverser ix = upperleft + Diff2D(1,0);
1020 for(int x=1; x<width-1; ++x, ++ix.x)
1021 {
1022 // analyse all neighbors of a pixel (use FourNeighborCode
1023 // instead of EightNeighborCode for 4-neighborhood):
1024 NeighborhoodCirculator<BImage::traverser, EightNeighborCode>
1025 circulator(ix),
1026 end(circulator);
1027 do
1028 {
1029 analysisFunc(*circulator, ...); // do sth. with current neighbor
1030 }
1031 while(++circulator != end); // compare with start/end circulator
1032 }
1033 }
1034 \endcode
1035 */
1036 template <class IMAGEITERATOR, class NEIGHBORCODE>
1037 class NeighborhoodCirculator : private IMAGEITERATOR
1038 {
1039 typedef NeighborOffsetCirculator<NEIGHBORCODE> NEIGHBOROFFSETCIRCULATOR;
1040
1041
1042 public:
1043 /** type of the underlying image iterator
1044 */
1045 typedef IMAGEITERATOR base_type;
1046
1047 /** type of the used neighbor code
1048 */
1049 typedef NEIGHBORCODE NeighborCode;
1050
1051 /** the circulator's value type
1052 */
1053 typedef typename IMAGEITERATOR::value_type value_type;
1054
1055 /** type of the direction code
1056 */
1057 typedef typename NEIGHBORCODE::Direction Direction;
1058
1059 /** the circulator's reference type (return type of <TT>*circ</TT>)
1060 */
1061 typedef typename IMAGEITERATOR::reference reference;
1062
1063 /** the circulator's index reference type (return type of <TT>circ[n]</TT>)
1064 */
1065
1066 typedef reference index_reference;
1067
1068 /** the circulator's pointer type (return type of <TT>operator-></TT>)
1069 */
1070 typedef typename IMAGEITERATOR::pointer pointer;
1071
1072 /** the circulator's difference type (argument type of <TT>circ[diff]</TT>)
1073 */
1074 typedef typename NEIGHBOROFFSETCIRCULATOR::difference_type difference_type;
1075
1076 /** the circulator tag (random_access_circulator_tag)
1077 */
1078 typedef typename NEIGHBOROFFSETCIRCULATOR::iterator_category iterator_category;
1079
1080 /** Construct circulator with given <tt>center</tt> pixel, pointing to the neighbor
1081 at the given direction <tt>d</tt>.
1082 */
NeighborhoodCirculator(IMAGEITERATOR const & aCenter=IMAGEITERATOR (),Direction d=NEIGHBOROFFSETCIRCULATOR::InitialDirection)1083 NeighborhoodCirculator(IMAGEITERATOR const & aCenter = IMAGEITERATOR(),
1084 Direction d = NEIGHBOROFFSETCIRCULATOR::InitialDirection)
1085 : IMAGEITERATOR(aCenter), neighborCode_(d)
1086 {
1087 IMAGEITERATOR::operator+=(neighborCode_.diff());
1088 }
1089
1090 /** pre-increment */
operator ++()1091 NeighborhoodCirculator & operator++()
1092 {
1093 return operator+=(1);
1094 }
1095
1096 /** post-increment */
operator ++(int)1097 NeighborhoodCirculator operator++(int)
1098 {
1099 NeighborhoodCirculator ret(*this);
1100 operator++();
1101 return ret;
1102 }
1103
1104 /** pre-decrement */
operator --()1105 NeighborhoodCirculator & operator--()
1106 {
1107 return operator+=(-1);
1108 }
1109
1110 /** post-decrement */
operator --(int)1111 NeighborhoodCirculator operator--(int)
1112 {
1113 NeighborhoodCirculator ret(*this);
1114 operator--();
1115 return ret;
1116 }
1117
1118 /** add-assignment */
operator +=(difference_type d)1119 NeighborhoodCirculator & operator+=(difference_type d)
1120 {
1121 IMAGEITERATOR::operator+=(neighborCode_.relativeDiff(d));
1122 neighborCode_+= d;
1123 return *this;
1124 }
1125
1126 /** subtract-assignment */
operator -=(difference_type d)1127 NeighborhoodCirculator & operator-=(difference_type d)
1128 {
1129 return operator+=(-d);
1130 }
1131
1132 /** addition */
operator +(difference_type d) const1133 NeighborhoodCirculator operator+(difference_type d) const
1134 {
1135 NeighborhoodCirculator result(*this);
1136 result+= d;
1137 return result;
1138 }
1139
1140 /** subtraction */
operator -(difference_type d) const1141 NeighborhoodCirculator operator-(difference_type d) const
1142 {
1143 NeighborhoodCirculator result(*this);
1144 result-= d;
1145 return result;
1146 }
1147
1148 /** Move to the direction that is 'right' relative to the current direction.
1149 This is equivalent to <tt>four_circulator--</tt> and
1150 <tt>eight_circulator -= 2</tt> respectively.
1151 */
turnRight()1152 NeighborhoodCirculator & turnRight()
1153 {
1154 Direction oldDirection = neighborCode_.direction();
1155 neighborCode_.turnRight();
1156 IMAGEITERATOR::operator+=(NeighborCode::relativeDiff
1157 (oldDirection, neighborCode_.direction()));
1158 return *this;
1159 }
1160
1161 /** Move to the direction that is 'left' relative to the current direction.
1162 This is equivalent to <tt>four_circulator++</tt> and
1163 <tt>eight_circulator += 2</tt> respectively.
1164 */
turnLeft()1165 NeighborhoodCirculator & turnLeft()
1166 {
1167 Direction oldDirection = neighborCode_.direction();
1168 neighborCode_.turnLeft();
1169 IMAGEITERATOR::operator+=(NeighborCode::relativeDiff
1170 (oldDirection, neighborCode_.direction()));
1171 return *this;
1172 }
1173
1174 /** Move to the opposite direction of the current direction.
1175 This is equivalent to <tt>four_circulator += 2</tt> and
1176 <tt>eight_circulator += 4</tt> respectively.
1177 */
turnRound()1178 NeighborhoodCirculator & turnRound()
1179 {
1180 Direction oldDirection = neighborCode_.direction();
1181 neighborCode_.turnRound();
1182 IMAGEITERATOR::operator+=(NeighborCode::relativeDiff
1183 (oldDirection, neighborCode_.direction()));
1184 return *this;
1185 }
1186
1187 /** Move to the given direction.
1188 */
turnTo(Direction d)1189 NeighborhoodCirculator & turnTo(Direction d)
1190 {
1191 Direction oldDirection = neighborCode_.direction();
1192 neighborCode_.turnTo(d);
1193 IMAGEITERATOR::operator+=(NeighborCode::relativeDiff
1194 (oldDirection, neighborCode_.direction()));
1195 return *this;
1196 }
1197
1198 /** Move the center in the current direction.
1199 The current neighbor becomes the new center, the direction does not change.
1200 */
moveCenterToNeighbor()1201 NeighborhoodCirculator & moveCenterToNeighbor()
1202 {
1203 IMAGEITERATOR::operator+=(neighborCode_.diff());
1204 return *this;
1205 }
1206
1207 /** Exchange the center with the current neighbor.
1208 Equivalent to <tt>circ.moveCenterToNeighbor().turnRound()</tt>
1209 (but shorter and more efficient).
1210 */
swapCenterNeighbor()1211 NeighborhoodCirculator & swapCenterNeighbor()
1212 {
1213 neighborCode_.turnRound();
1214 IMAGEITERATOR::operator+=(neighborCode_.diff());
1215 return *this;
1216 }
1217
1218 /** equality */
operator ==(NeighborhoodCirculator const & rhs) const1219 bool operator==(NeighborhoodCirculator const & rhs) const
1220 {
1221 return neighborCode_ == rhs.neighborCode_ &&
1222 IMAGEITERATOR::operator==(rhs);
1223 }
1224
1225 /** inequality */
operator !=(NeighborhoodCirculator const & rhs) const1226 bool operator!=(NeighborhoodCirculator const & rhs) const
1227 {
1228 return neighborCode_ != rhs.neighborCode_ ||
1229 IMAGEITERATOR::operator!=(rhs);
1230 }
1231
1232 /** subtraction */
operator -(NeighborhoodCirculator const & rhs) const1233 difference_type operator-(NeighborhoodCirculator const & rhs) const
1234 {
1235 return neighborCode_ - rhs.neighborCode_;
1236 }
1237
1238 /** dereference */
operator *() const1239 reference operator*() const
1240 {
1241 return IMAGEITERATOR::operator*();
1242 }
1243
1244 /** index */
operator [](difference_type d) const1245 index_reference operator[](difference_type d) const
1246 {
1247 return IMAGEITERATOR::operator[](neighborCode_.relativeDiff(d));
1248 }
1249
1250 /** member access */
operator ->() const1251 pointer operator->() const
1252 {
1253 return IMAGEITERATOR::operator->();
1254 }
1255
1256 /** Get the base iterator for the current neighbor. */
base() const1257 base_type const & base() const
1258 {
1259 return *this;
1260 }
1261
1262 /** Get the base iterator for the center of the circulator. */
center() const1263 base_type center() const
1264 {
1265 return (base_type)*this - neighborCode_.diff();
1266 }
1267
1268 /** Get the current direction. */
direction() const1269 Direction direction() const
1270 {
1271 return neighborCode_.direction();
1272 }
1273
1274 /** Get the current direction bit. */
directionBit() const1275 unsigned int directionBit() const
1276 {
1277 return neighborCode_.directionBit();
1278 }
1279
1280 /** Get the difference vector (Diff2D) from the center to the current neighbor. */
diff() const1281 typename NEIGHBOROFFSETCIRCULATOR::value_type const & diff() const
1282 {
1283 return neighborCode_.diff();
1284 }
1285
1286 /** Is the current neighbor a diagonal neighbor? */
isDiagonal() const1287 bool isDiagonal() const
1288 {
1289 return neighborCode_.isDiagonal();
1290 }
1291
1292 private:
1293 NEIGHBOROFFSETCIRCULATOR neighborCode_;
1294 };
1295
1296 /********************************************************/
1297 /* */
1298 /* RestrictedNeighborhoodCirculator */
1299 /* */
1300 /********************************************************/
1301
1302 /** \brief Circulator that walks around a given location in a given image,
1303 using a restricted neighborhood.
1304
1305 This circulator behaves essentially like \ref vigra::NeighborhoodCirculator,
1306 but can also be used near the image border, where some of the neighbor points
1307 would be outside the image und must not be accessed.
1308 The template parameters define the kind of neighborhood used (four or eight)
1309 and the underlying image, whereas the required neighborhood restriction is
1310 given by the last constructor argument. This below for typical usage.
1311
1312 The access functions return the value of the current neighbor pixel. Use <tt>center()</tt> to
1313 access the center pixel of the neighborhood.
1314
1315 <b>Usage:</b><br>
1316
1317 <b>\#include</b> \<vigra/pixelneighborhood.hxx\><br>
1318 Namespace: vigra
1319
1320 \code
1321 BImage::traverser upperleft(...), lowerright(...);
1322
1323 int width = lowerright.x - upperleft.x;
1324 int height = lowerright.y - upperleft.y;
1325
1326 for(int y=0; y<height; ++y, ++upperleft.y)
1327 {
1328 BImage::traverser ix = upperleft;
1329 for(int x=0; x<width; ++x, ++ix.x)
1330 {
1331 // use FourNeighborCode instead of EightNeighborCode for 4-neighborhood
1332 RestrictedNeighborhoodCirculator<BImage::traverser, EightNeighborCode>
1333 circulator(ix, isAtImageBorder(x, y, width, height)),
1334 end(circulator);
1335 do
1336 {
1337 ... // do something with the circulator
1338 }
1339 while(++circulator != end); // out-of-range pixels will be automatically skipped
1340 }
1341 }
1342 \endcode
1343 */
1344 template <class IMAGEITERATOR, class NEIGHBORCODE>
1345 class RestrictedNeighborhoodCirculator
1346 : private NeighborhoodCirculator<IMAGEITERATOR, NEIGHBORCODE>
1347 {
1348 typedef NeighborhoodCirculator<IMAGEITERATOR, NEIGHBORCODE> BaseType;
1349
1350 public:
1351 /** type of the underlying image iterator
1352 */
1353 typedef IMAGEITERATOR base_type;
1354
1355 /** type of the used neighbor code
1356 */
1357 typedef NEIGHBORCODE NeighborCode;
1358
1359 /** the circulator's value type
1360 */
1361 typedef typename BaseType::value_type value_type;
1362
1363 /** type of the direction code
1364 */
1365 typedef typename BaseType::Direction Direction;
1366
1367 /** the circulator's reference type (return type of <TT>*circ</TT>)
1368 */
1369 typedef typename BaseType::reference reference;
1370
1371 /** the circulator's index reference type (return type of <TT>circ[n]</TT>)
1372 */
1373 typedef typename BaseType::index_reference index_reference;
1374
1375 /** the circulator's pointer type (return type of <TT>operator-></TT>)
1376 */
1377 typedef typename BaseType::pointer pointer;
1378
1379 /** the circulator's difference type (argument type of <TT>circ[diff]</TT>)
1380 */
1381 typedef typename BaseType::difference_type difference_type;
1382
1383 /** the circulator tag (random_access_circulator_tag)
1384 */
1385 typedef typename BaseType::iterator_category iterator_category;
1386
1387 /** Construct circulator with given <tt>center</tt> pixel, using the restricted
1388 neighborhood given by \a atBorder.
1389 */
RestrictedNeighborhoodCirculator(IMAGEITERATOR const & center=IMAGEITERATOR (),AtImageBorder atBorder=NotAtBorder)1390 RestrictedNeighborhoodCirculator(IMAGEITERATOR const & center = IMAGEITERATOR(),
1391 AtImageBorder atBorder = NotAtBorder)
1392 : BaseType(center, NEIGHBORCODE::nearBorderDirections(atBorder, 0)),
1393 whichBorder_(atBorder),
1394 count_(NEIGHBORCODE::nearBorderDirectionCount(atBorder)),
1395 current_(0)
1396 {}
1397
1398 /** pre-increment */
operator ++()1399 RestrictedNeighborhoodCirculator & operator++()
1400 {
1401 return operator+=(1);
1402 }
1403
1404 /** post-increment */
operator ++(int)1405 RestrictedNeighborhoodCirculator operator++(int)
1406 {
1407 RestrictedNeighborhoodCirculator ret(*this);
1408 operator++();
1409 return ret;
1410 }
1411
1412 /** pre-decrement */
operator --()1413 RestrictedNeighborhoodCirculator & operator--()
1414 {
1415 return operator+=(-1);
1416 }
1417
1418 /** post-decrement */
operator --(int)1419 RestrictedNeighborhoodCirculator operator--(int)
1420 {
1421 RestrictedNeighborhoodCirculator ret(*this);
1422 operator--();
1423 return ret;
1424 }
1425
1426 /** add-assignment */
operator +=(difference_type d)1427 RestrictedNeighborhoodCirculator & operator+=(difference_type d)
1428 {
1429 current_ = static_cast<Direction>((current_ + count_ + d) % count_);
1430 BaseType::turnTo(NEIGHBORCODE::nearBorderDirections(whichBorder_, current_));
1431 return *this;
1432 }
1433
1434 /** subtract-assignment */
operator -=(difference_type d)1435 RestrictedNeighborhoodCirculator & operator-=(difference_type d)
1436 {
1437 return operator+=(-d);
1438 }
1439
1440 /** addition */
operator +(difference_type d) const1441 RestrictedNeighborhoodCirculator operator+(difference_type d) const
1442 {
1443 RestrictedNeighborhoodCirculator result(*this);
1444 result+= d;
1445 return result;
1446 }
1447
1448 /** subtraction */
operator -(difference_type d) const1449 RestrictedNeighborhoodCirculator operator-(difference_type d) const
1450 {
1451 RestrictedNeighborhoodCirculator result(*this);
1452 result-= d;
1453 return result;
1454 }
1455
1456 /** equality */
operator ==(RestrictedNeighborhoodCirculator const & rhs) const1457 bool operator==(RestrictedNeighborhoodCirculator const & rhs) const
1458 {
1459 return current_ == rhs.current_;
1460 }
1461
1462 /** inequality */
operator !=(RestrictedNeighborhoodCirculator const & rhs) const1463 bool operator!=(RestrictedNeighborhoodCirculator const & rhs) const
1464 {
1465 return current_ != rhs.current_;
1466 }
1467
1468 /** subtraction */
operator -(RestrictedNeighborhoodCirculator const & rhs) const1469 difference_type operator-(RestrictedNeighborhoodCirculator const & rhs) const
1470 {
1471 return (current_ - rhs.current_) % count_;
1472 }
1473
1474 /** dereference */
operator *() const1475 reference operator*() const
1476 {
1477 return BaseType::operator*();
1478 }
1479
1480 /** member access */
operator ->() const1481 pointer operator->() const
1482 {
1483 return BaseType::operator->();
1484 }
1485
1486 /** Get the base iterator for the current neighbor. */
base() const1487 base_type const & base() const
1488 {
1489 return BaseType::base();
1490 }
1491
1492 /** Get the base iterator for the center of the circulator. */
center() const1493 base_type center() const
1494 {
1495 return BaseType::center();
1496 }
1497
1498 /** Get the current direction. */
direction() const1499 Direction direction() const
1500 {
1501 return BaseType::direction();
1502 }
1503
1504 /** Get the current direction bit. */
directionBit() const1505 unsigned int directionBit() const
1506 {
1507 return BaseType::directionBit();
1508 }
1509
1510 /** Get the difference vector (Diff2D) from the center to the current neighbor. */
diff() const1511 typename NeighborCode::difference_type const & diff() const
1512 {
1513 return BaseType::diff();
1514 }
1515
1516 /** Is the current neighbor a diagonal neighbor? */
isDiagonal() const1517 bool isDiagonal() const
1518 {
1519 return BaseType::isDiagonal();
1520 }
1521
1522 private:
1523 AtImageBorder whichBorder_;
1524 signed char count_, current_;
1525 };
1526
1527 //@}
1528
1529 } // namespace vigra
1530
1531 #endif /* VIGRA_PIXELNEIGHBORHOOD_HXX */
1532