[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

accessor.hxx |

1 /************************************************************************/
2 /* */
3 /* Copyright 1998-2002 by 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_ACCESSOR_HXX
37 #define VIGRA_ACCESSOR_HXX
38
39 #include "metaprogramming.hxx"
40 #include "numerictraits.hxx"
41 #include "tuple.hxx"
42
43 namespace vigra {
44
45 /** \addtogroup DataAccessors Data Accessors
46
47 Basic templates to encapsulate access to the data of an iterator.
48
49 Data accessors are used to allow for flexible access to the data
50 an iterator points to. When we access the data directly, we
51 are bound to what <TT>operator*()</TT> returns, if this method exists at
52 all. Encapsulating access in an accessor enables a better
53 decoupling of data structures and algorithms.
54 <a href="http://ukoethe.github.io/vigra/doc/vigra/documents/DataAccessors.ps">This paper</a> contains
55 a detailed description of the concept. Here is a brief list of the basic
56 accessor requirements:
57
58 <p>
59 <table border=2 cellspacing=0 cellpadding=2 width="100%">
60 <tr><th>
61 Operation
62 </th><th>
63 Result
64 </th><th>
65 Semantics
66 </th>
67 </tr>
68 <tr>
69 <td><tt>accessor(iter)</tt></td><td>convertible to <br><tt>Accessor::value_type const &</tt></td>
70 <td>read data at the current position of the iterator</td>
71 </tr>
72 <tr>
73 <td><tt>accessor(iter, index)</tt></td><td>convertible to <br><tt>Accessor::value_type const &</tt></td>
74 <td>read data at offset <tt>index</tt> relative to iterator's current position
75 (random-access iterator only)</td>
76 </tr>
77 <tr>
78 <td><tt>accessor.set(value, iter)</tt></td><td><tt>void</tt></td>
79 <td>write data <tt>value</tt> at the current position of the iterator (mutable iterator only)</td>
80 </tr>
81 <tr>
82 <td><tt>accessor.set(value, iter, index)</tt></td><td><tt>void</tt></td>
83 <td>write data <tt>value</tt> at offset <tt>index</tt> relative to iterator's current position
84 (mutable random-access iterator only)</td>
85 </tr>
86 <tr><td colspan=2>
87 <tt>Accessor::value_type</tt></td>
88 <td>type of the data field the accessor refers to</td>
89 </tr>
90 <tr><td colspan=3>
91 <tt>iter</tt> is an iterator<br>
92 <tt>index</tt> has the iterator's index type (<tt>Iterator::difference_type</tt>)<br>
93 <tt>value</tt> is convertible to <tt>Accessor::value_type const &</tt>
94 </td>
95 </tr>
96 </table>
97 </p>
98
99 The template <tt>AccessorTraits<T></tt> can be used to find the default accessor
100 associated with the type <tt>T</tt>, e.g.
101
102 \code
103 typedef typename AccessorTraits<typename Image::value_type>::default_accessor Accessor;
104 typedef typename AccessorTraits<typename Image::value_type>::default_const_accessor ConstAccessor;
105 \endcode
106 */
107 //@{
108
109 /********************************************************/
110 /* */
111 /* StandardAccessor */
112 /* */
113 /********************************************************/
114
115 /** \brief Encapsulate access to the values an iterator points to.
116
117 StandardAccessor is a trivial accessor that simply encapsulates
118 the iterator's operator*() and operator[]() in its
119 read and write functions. It passes its arguments <em>by reference</em>.
120 If you want to return items by value, you
121 must use StandardValueAccessor instead of StandardAccessor.
122 Both accessors have different optimization properties --
123 StandardAccessor is usually faster for compound pixel types,
124 while StandardValueAccessor is faster for the built-in types.
125
126 When a floating point number is assigned by means of an accessor
127 with integral value_type, the value is rounded and clipped as appropriate.
128
129 <b>\#include</b> <vigra/accessor.hxx><br>
130 Namespace: vigra
131 */
132 template <class VALUETYPE>
133 class StandardAccessor
134 {
135 public:
136 /** the value_type
137 */
138 typedef VALUETYPE value_type;
139
140 /** read the current data item
141 */
142 template <class ITERATOR>
143 VALUETYPE const & operator()(ITERATOR const & i) const { return *i; }
144
145 VALUETYPE const & operator()(VALUETYPE const * i) const { return *i; }
146
147 /** read the data item at an offset (can be 1D or 2D or higher order difference).
148 */
149 template <class ITERATOR, class OFFSET>
150 VALUETYPE const & operator()(ITERATOR const & i, OFFSET const & diff) const
151 {
152 return i[diff];
153 }
154
155 /** Write the current data item. The type <TT>V</TT> of the passed
156 in <TT>value</TT> is automatically converted to <TT>VALUETYPE</TT>.
157 In case of a conversion floating point -> integral this includes rounding and clipping.
158 */
159 template <class V, class ITERATOR>
160 void set(V const & value, ITERATOR const & i) const
161 { *i = detail::RequiresExplicitCast<VALUETYPE>::cast(value); }
162
163 /* This overload is needed to make the accessor work with a std::back_inserter */
164 template <class V, class ITERATOR>
165 void set(V const & value, ITERATOR & i) const
166 { *i = detail::RequiresExplicitCast<VALUETYPE>::cast(value); }
167
168 /** Write the data item at an offset (can be 1D or 2D or higher order difference)..
169 The type <TT>V</TT> of the passed
170 in <TT>value</TT> is automatically converted to <TT>VALUETYPE</TT>.
171 In case of a conversion floating point -> integral this includes rounding and clipping.
172 */
173 template <class V, class ITERATOR, class OFFSET>
174 void set(V const & value, ITERATOR const & i, OFFSET const & diff) const
175 {
176 i[diff]= detail::RequiresExplicitCast<VALUETYPE>::cast(value);
177 }
178 };
179
180 /** \brief Encapsulate access to the values an iterator points to.
181
182 StandardValueAccessor is a trivial accessor that simply encapsulates
183 the iterator's operator*() and operator[]() in its
184 read and write functions. It passes its arguments <em>by value</em>.
185 If the iterator returns its items by reference (such as \ref vigra::ImageIterator),
186 you can also use StandardAccessor.
187 These accessors have different optimization properties --
188 StandardAccessor is usually faster for compound pixel types,
189 while StandardValueAccessor is faster for the built-in types.
190
191 When a floating point number is assigned by means of an accessor
192 with integral value_type, the value is rounded and clipped as appropriate.
193
194 <b>\#include</b> <vigra/accessor.hxx><br>
195 Namespace: vigra
196 */
197 template <class VALUETYPE>
198 class StandardValueAccessor
199 {
200 public:
201 /** the value_type
202 */
203 typedef VALUETYPE value_type;
204
205 /** Read the current data item. The type <TT>ITERATOR::reference</TT>
206 is automatically converted to <TT>VALUETYPE</TT>.
207 In case of a conversion floating point -> integral this includes rounding and clipping.
208 */
209 template <class ITERATOR>
210 VALUETYPE operator()(ITERATOR const & i) const
211 { return detail::RequiresExplicitCast<VALUETYPE>::cast(*i); }
212
213 /** Read the data item at an offset (can be 1D or 2D or higher order difference).
214 The type <TT>ITERATOR::index_reference</TT>
215 is automatically converted to <TT>VALUETYPE</TT>.
216 In case of a conversion floating point -> integral this includes rounding and clipping.
217 */
218 template <class ITERATOR, class OFFSET>
219 VALUETYPE operator()(ITERATOR const & i, OFFSET const & diff) const
220 {
221 return detail::RequiresExplicitCast<VALUETYPE>::cast(i[diff]);
222 }
223 /** Write the current data item. The type <TT>V</TT> of the passed
224 in <TT>value</TT> is automatically converted to <TT>VALUETYPE</TT>.
225 In case of a conversion floating point -> integral this includes rounding and clipping.
226 */
227 template <class V, class ITERATOR>
228 void set(V value, ITERATOR const & i) const
229 { *i = detail::RequiresExplicitCast<VALUETYPE>::cast(value); }
230
231 /* This overload is needed to make the accessor work with a std::back_inserter */
232 template <class V, class ITERATOR>
233 void set(V value, ITERATOR & i) const
234 { *i = detail::RequiresExplicitCast<VALUETYPE>::cast(value); }
235
236 /** Write the data item at an offset (can be 1D or 2D or higher order difference)..
237 The type <TT>V</TT> of the passed
238 in <TT>value</TT> is automatically converted to <TT>VALUETYPE</TT>.
239 In case of a conversion floating point -> integral this includes rounding and clipping.
240 */
241 template <class V, class ITERATOR, class OFFSET>
242 void set(V value, ITERATOR const & i, OFFSET const & diff) const
243 {
244 i[diff]= detail::RequiresExplicitCast<VALUETYPE>::cast(value);
245 }
246 };
247
248 /********************************************************/
249 /* */
250 /* StandardConstAccessor */
251 /* */
252 /********************************************************/
253
254 /** \brief Encapsulate read access to the values an iterator points to.
255
256 StandardConstAccessor is a trivial accessor that simply encapsulates
257 the iterator's operator*() and operator[]() in its
258 read functions. It passes its arguments <em>by reference</em>.
259 If the iterator returns its items by value (such as \ref vigra::CoordinateIterator), you
260 must use StandardConstValueAccessor instead of StandardConstAccessor.
261 Both accessors also have different optimization properties --
262 StandardConstAccessor is usually faster for compound pixel types,
263 while StandardConstValueAccessor is faster for the built-in types.
264
265 <b>\#include</b> <vigra/accessor.hxx><br>
266 Namespace: vigra
267 */
268 template <class VALUETYPE>
269 class StandardConstAccessor
270 {
271 public:
272 typedef VALUETYPE value_type;
273
274 /** read the current data item
275 */
276 template <class ITERATOR>
277 VALUETYPE const & operator()(ITERATOR const & i) const
278 { return *i; }
279
280 /** read the data item at an offset (can be 1D or 2D or higher order difference).
281 */
282 template <class ITERATOR, class OFFSET>
283 VALUETYPE const & operator()(ITERATOR const & i, OFFSET const & diff) const
284 {
285 return i[diff];
286 }
287 };
288
289 /** \brief Encapsulate access to the values an iterator points to.
290
291 StandardConstValueAccessor is a trivial accessor that simply encapsulates
292 the iterator's operator*() and operator[]() in its
293 read functions. It passes its arguments <em>by value</em>.
294 If the iterator returns its items by reference (such as \ref vigra::ConstImageIterator),
295 you can also use StandardConstAccessor.
296 These accessors have different optimization properties --
297 StandardConstAccessor is usually faster for compound pixel types,
298 while StandardConstValueAccessor is faster for the built-in types.
299
300 When an iterator passes a floating point number to an accessor
301 with integral value_type, the value is rounded and clipped as appropriate.
302
303 <b>\#include</b> <vigra/accessor.hxx><br>
304 Namespace: vigra
305 */
306 template <class VALUETYPE>
307 class StandardConstValueAccessor
308 {
309 public:
310 typedef VALUETYPE value_type;
311
312 /** Read the current data item. The type <TT>ITERATOR::reference</TT>
313 is automatically converted to <TT>VALUETYPE</TT>.
314 In case of a conversion floating point -> integral this includes rounding and clipping.
315 */
316 template <class ITERATOR>
317 VALUETYPE operator()(ITERATOR const & i) const
318 { return detail::RequiresExplicitCast<VALUETYPE>::cast(*i); }
319
320 /** Read the data item at an offset (can be 1D or 2D or higher order difference).
321 The type <TT>ITERATOR::index_reference</TT>
322 is automatically converted to <TT>VALUETYPE</TT>.
323 In case of a conversion floating point -> integral this includes rounding and clipping.
324 */
325 template <class ITERATOR, class OFFSET>
326 VALUETYPE operator()(ITERATOR const & i, OFFSET const & diff) const
327 {
328 return detail::RequiresExplicitCast<VALUETYPE>::cast(i[diff]);
329 }
330 };
331
332 /********************************************************/
333 /* */
334 /* VectorComponentAccessor */
335 /* */
336 /********************************************************/
337
338 /** \brief Accessor for one component of a vector.
339
340 This accessor allows to select a single component (a single 'band')
341 of a vector valued pixel type. The pixel type must support
342 <TT>operator[]</TT>. The index of the component to be selected
343 is passed in the constructor. The accessor returns its items
344 <em>by reference</em>. If you want to pass/return items by value,
345 use VectorComponentValueAccessor. If a floating point number
346 is assigned by means of an accessor with integral value_type, the
347 value is rounded and clipped as appropriate.
348
349 <b>Usage:</b>
350
351 \code
352 vigra::BRGBImage image(w,h);
353
354 // init red channel with 255
355 initImage(destImageRange(image,
356 VectorComponentAccessor<vigra::BRGBImage::value_type>(0)),
357 255);
358 \endcode
359
360 <b>\#include</b> <vigra/accessor.hxx><br>
361 Namespace: vigra
362
363 */
364 template <class VECTORTYPE>
365 class VectorComponentAccessor
366 {
367 int index_;
368 public:
369 /** the value_type
370 */
371 typedef typename VECTORTYPE::value_type value_type;
372
373 /** determine the component to be accessed
374 */
375 VectorComponentAccessor(int index)
376 : index_(index)
377 {}
378
379 /** read the current data item
380 */
381 template <class ITERATOR>
382 value_type const & operator()(ITERATOR const & i) const
383 { return (*i)[index_]; }
384
385 /** read the data item at an offset (can be 1D or 2D or higher order difference).
386 */
387 template <class ITERATOR, class OFFSET>
388 value_type const & operator()(ITERATOR const & i, OFFSET const & diff) const
389 {
390 return i[diff][index_];
391 }
392
393 /** Write the current data item. The type <TT>V</TT> of the passed
394 in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
395 In case of a conversion floating point -> integral this includes rounding and clipping.
396 */
397 template <class V, class ITERATOR>
398 void set(V const & value, ITERATOR const & i) const
399 {
400 (*i)[index_] = detail::RequiresExplicitCast<value_type>::cast(value);
401 }
402
403 /** Write the data item at an offset (can be 1D or 2D or higher order difference)..
404 The type <TT>V</TT> of the passed
405 in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
406 In case of a conversion floating point -> integral this includes rounding and clipping.
407 */
408 template <class V, class ITERATOR, class OFFSET>
409 void set(V const & value, ITERATOR const & i, OFFSET const & diff) const
410 {
411 i[diff][index_]= detail::RequiresExplicitCast<value_type>::cast(value);
412 }
413
414 /** Reset the index to the given number.
415 */
416 void setIndex(int i)
417 {
418 index_ = i;
419 }
420 };
421
422 /** \brief Accessor for one component of a vector.
423
424 This accessor allows to select a single component (a single 'band')
425 of a vector valued pixel type. The pixel type must support
426 <TT>operator[]</TT>. The index of the component to be selected
427 is passed in the constructor. The accessor returns its items
428 <em>by value</em>. If you want to pass/return items by reference,
429 use VectorComponentAccessor. If a floating point number
430 is assigned by means of an accessor with integral value_type, the
431 value is rounded and clipped as appropriate.
432
433 <b>Usage:</b>
434
435 \code
436 vigra::BRGBImage image(w,h);
437
438 // init red channel with 255
439 initImage(destImageRange(image,
440 VectorComponentValueAccessor<vigra::BRGBImage::value_type>(0)),
441 255);
442 \endcode
443
444 <b>\#include</b> <vigra/accessor.hxx><br>
445 Namespace: vigra
446
447 */
448 template <class VECTORTYPE>
449 class VectorComponentValueAccessor
450 {
451 int index_;
452 public:
453 /** the value_type
454 */
455 typedef typename VECTORTYPE::value_type value_type;
456
457 /** determine the component to be accessed
458 */
459 VectorComponentValueAccessor(int index)
460 : index_(index)
461 {}
462
463 /** Read the current data item.
464 The type <TT>ITERATOR::index_reference::value_type</TT>
465 is automatically converted to <TT>value_type</TT>.
466 In case of a conversion floating point -> integral this includes rounding and clipping.
467 */
468 template <class ITERATOR>
469 value_type operator()(ITERATOR const & i) const
470 { return detail::RequiresExplicitCast<value_type>::cast((*i)[index_]); }
471
472 /** Read the data item at an offset (can be 1D or 2D or higher order difference).
473 The type <TT>ITERATOR::index_reference::value_type</TT>
474 is automatically converted to <TT>value_type</TT>.
475 In case of a conversion floating point -> integral this includes rounding and clipping.
476 */
477 template <class ITERATOR, class OFFSET>
478 value_type operator()(ITERATOR const & i, OFFSET const & diff) const
479 {
480 return detail::RequiresExplicitCast<value_type>::cast(i[diff][index_]);
481 }
482
483 /** Write the current data item. The type <TT>V</TT> of the passed
484 in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
485 In case of a conversion floating point -> integral this includes rounding and clipping.
486 */
487 template <class V, class ITERATOR>
488 void set(V value, ITERATOR const & i) const
489 {
490 (*i)[index_] = detail::RequiresExplicitCast<value_type>::cast(value);
491 }
492
493 /** Write the data item at an offset (can be 1D or 2D or higher order difference)..
494 The type <TT>V</TT> of the passed
495 in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
496 In case of a conversion floating point -> integral this includes rounding and clipping.
497 */
498 template <class V, class ITERATOR, class OFFSET>
499 void set(V value, ITERATOR const & i, OFFSET const & diff) const
500 {
501 i[diff][index_]= detail::RequiresExplicitCast<value_type>::cast(value);
502 }
503
504 /** Reset the index to the given number.
505 */
506 void setIndex(int i)
507 {
508 index_ = i;
509 }
510 };
511
512 /********************************************************/
513 /* */
514 /* VectorElementAccessor */
515 /* */
516 /********************************************************/
517
518 /** \brief Accessor for one component of a vector.
519
520 This works like VectorComponentAccessor, only the template parameters differ:
521 Here, we need a vector accessor type , whereas VectorComponentAccessor requires a vector type.
522
523 <b>Usage:</b>
524
525 \code
526 vigra::BRGBImage image(w,h);
527
528 // init red channel with 255
529 initImage(destImageRange(image,
530 VectorElementAccessor<vigra::BRGBImage::Accessor>(0)),
531 255);
532 \endcode
533
534 <b>\#include</b> <vigra/accessor.hxx><br>
535 Namespace: vigra
536
537 */
538 template <class ACCESSOR>
539 class VectorElementAccessor
540 {
541 int index_;
542 ACCESSOR a_;
543 public:
544 /** the value_type
545 */
546 typedef typename ACCESSOR::component_type value_type;
547
548 /** determine the component to be accessed
549 */
550 VectorElementAccessor(int index, ACCESSOR a = ACCESSOR())
551 : index_(index),
552 a_(a)
553 {}
554
555 /** read the current data item
556 */
557 template <class ITERATOR>
558 value_type const & operator()(ITERATOR const & i) const
559 { return a_.getComponent(i, index_); }
560
561 /** read the data item at an offset (can be 1D or 2D or higher order difference).
562 */
563 template <class ITERATOR, class OFFSET>
564 value_type const & operator()(ITERATOR const & i, OFFSET const & diff) const
565 {
566 return a_.getComponent(i, diff, index_);
567 }
568
569 /** Write the current data item. The type <TT>V</TT> of the passed
570 in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
571 In case of a conversion floating point -> integral this includes rounding and clipping.
572 */
573 template <class V, class ITERATOR>
574 void set(V const & value, ITERATOR const & i) const
575 {
576 a_.setComponent(detail::RequiresExplicitCast<value_type>::cast(value), i, index_);
577 }
578
579 /** Write the data item at an offset (can be 1D or 2D or higher order difference)..
580 The type <TT>V</TT> of the passed
581 in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
582 In case of a conversion floating point -> integral this includes rounding and clipping.
583 */
584 template <class V, class ITERATOR, class OFFSET>
585 void set(V const & value, ITERATOR const & i, OFFSET const & diff) const
586 {
587 a_.setComponent(detail::RequiresExplicitCast<value_type>::cast(value), i, diff, index_);
588 }
589
590 /** Reset the index to the given number.
591 */
592 void setIndex(int i)
593 {
594 index_ = i;
595 }
596 };
597
598 /********************************************************/
599 /* */
600 /* SequenceAccessor */
601 /* */
602 /********************************************************/
603
604 /** \brief Accessor for items that are STL compatible sequences.
605
606 It encapsulates access to the sequences' begin() and end()
607 functions.
608
609 <b>Usage:</b>
610
611 <b>\#include</b> <vigra/accessor.hxx><br>
612 Namespace: vigra
613
614 \code
615 typedef std::list<std::list<int> > ListOfLists;
616
617 ListOfLists ll;
618 ...
619
620 typedef vigra::SequenceAccessor<ListOfLists::value_type> ListOfListsAccessor;
621 ListOfListsAccessor a;
622 for(ListOfLists::iterator li = ll.begin(); li != ll.end(); ++li)
623 {
624 for(ListOfListsAccessor::iterator i = a.begin(li); i != a.end(li); ++i)
625 {
626 *i = 10;
627 }
628 }
629 \endcode
630 */
631 template <class SEQUENCE>
632 class SequenceAccessor
633 : public StandardAccessor<SEQUENCE>
634 {
635 public:
636 /** the sequence's value_type
637 */
638 typedef typename SEQUENCE::value_type component_type;
639
640 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
641 typedef typename
642 If<typename TypeTraits<SEQUENCE>::isConst,
643 typename SEQUENCE::const_iterator,
644 typename SEQUENCE::iterator>::type
645 iterator;
646 #else
647 /** the sequence's iterator type
648 */
649 typedef typename SEQUENCE::iterator iterator;
650 #endif
651
652 /** get begin iterator for sequence at given iterator position
653 */
654 template <class ITERATOR>
655 iterator begin(ITERATOR const & i) const
656 {
657 return (*i).begin();
658 }
659
660 /** get end iterator for sequence at given iterator position
661 */
662 template <class ITERATOR>
663 iterator end(ITERATOR const & i) const
664 {
665 return (*i).end();
666 }
667
668 /** get begin iterator for sequence at an offset
669 of given iterator position
670 */
671 template <class ITERATOR, class OFFSET>
672 iterator begin(ITERATOR const & i, OFFSET const & diff) const
673 {
674 return i[diff].begin();
675 }
676
677 /** get end iterator for sequence at a 2D difference vector
678 of given iterator position
679 */
680 template <class ITERATOR, class OFFSET>
681 iterator end(ITERATOR const & i, OFFSET const & diff) const
682 {
683 return i[diff].end();
684 }
685
686 /** get size of sequence at given iterator position
687 */
688 template <class ITERATOR>
689 unsigned int size(ITERATOR const & i) const { return (*i).size(); }
690
691 /** get size of sequence at 2D difference vector of given iterator position
692 */
693 template <class ITERATOR, class OFFSET>
694 unsigned int size(ITERATOR const & i, OFFSET const & diff) const
695 { return i[diff].size(); }
696 };
697
698 /********************************************************/
699 /* */
700 /* VectorAccessor */
701 /* */
702 /********************************************************/
703
704 /** \brief Accessor for items that are STL compatible vectors.
705
706 It encapsulates access to a vector's access functionality.
707
708 <b> Usage:</b>
709
710 <b>\#include</b> <vigra/accessor.hxx><br>
711 Namespace: vigra
712
713 The accessor has two modes of operation:
714
715 <ol>
716 <li> Access the vector's iterator via the <TT>begin()</TT> and <TT>end()</TT>
717 functions:
718
719 \code
720 typedef std::list<std::vector<int> > ListOfVectors;
721
722 ListOfVectors ll;
723 ...
724
725 typedef vigra::SequenceAccessor<ListOfVectors::value_type> ListOfVectorsAccessor;
726 ListOfVectorsAccessor a;
727 for(ListOfVectors::iterator li = ll.begin(); li != ll.end(); ++li)
728 {
729 for(ListOfVectorsAccessor::iterator i = a.begin(li); i != a.end(li); ++i)
730 {
731 *i = 10;
732 }
733 }
734 \endcode
735 <li> Access the vector's components via an index (internally calls
736 the vector's <TT>operator[]</TT> ):
737 \code
738 typedef std::list<std::vector<int> > ListOfVectors;
739
740 ListOfVectors ll;
741 ...
742
743 typedef vigra::SequenceAccessor<ListOfVectors::value_type> ListOfVectorsAccessor;
744 ListOfVectorsAccessor a;
745 for(ListOfVectors::iterator li = ll.begin(); li != ll.end(); ++li)
746 {
747 for(int i = 0; i != a.size(li); ++i)
748 {
749 a.setComponent(10, li, i);
750 }
751 }
752 \endcode
753 </ol>
754
755 <b> Required Interface:</b>
756
757 \code
758 VECTOR v;
759 VECTOR::iterator i;
760 value_type d;
761 int index;
762
763 d = v[index];
764 v[index] = d;
765 i = v.begin();
766 i = v.end();
767 v.size();
768 \endcode
769 */
770 template <class VECTOR>
771 class VectorAccessor
772 : public SequenceAccessor<VECTOR>
773 {
774 public:
775 /** the vector's value_type
776 */
777 typedef typename VECTOR::value_type component_type;
778
779 /** the vector element accessor associated with this vector accessor
780 (see \ref VectorElementAccessor)
781 */
782 typedef VectorElementAccessor<VectorAccessor<VECTOR> > ElementAccessor;
783
784 /** Read the component data at given vector index
785 at given iterator position
786 */
787 template <class ITERATOR>
788 component_type const & getComponent(ITERATOR const & i, int idx) const
789 {
790 return (*i)[idx];
791 }
792
793 /** Set the component data at given vector index
794 at given iterator position. The type <TT>V</TT> of the passed
795 in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
796 In case of a conversion floating point -> integral this includes rounding and clipping.
797 */
798 template <class V, class ITERATOR>
799 void setComponent(V const & value, ITERATOR const & i, int idx) const
800 {
801 (*i)[idx] = detail::RequiresExplicitCast<component_type>::cast(value);
802 }
803
804 /** Read the component data at given vector index
805 at an offset of given iterator position
806 */
807 template <class ITERATOR, class OFFSET>
808 component_type const & getComponent(ITERATOR const & i, OFFSET const & diff, int idx) const
809 {
810 return i[diff][idx];
811 }
812
813 /** Set the component data at given vector index
814 at an offset of given iterator position. The type <TT>V</TT> of the passed
815 in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
816 In case of a conversion floating point -> integral this includes rounding and clipping.
817 */
818 template <class V, class ITERATOR, class OFFSET>
819 void
820 setComponent(V const & value, ITERATOR const & i, OFFSET const & diff, int idx) const
821 {
822 i[diff][idx] = detail::RequiresExplicitCast<component_type>::cast(value);
823 }
824 };
825
826
827 /********************************************************/
828 /* */
829 /* MultiImageAccessor2 */
830 /* */
831 /********************************************************/
832
833 /** \brief Access two images simultaneously.
834
835 This accessor is used when two images need to be treated as one
836 because an algorithm accepts only one image. For example,
837 \ref seededRegionGrowing() uses only one image two calculate
838 the cost for aggregating each pixel into a region. Sometimes, we
839 need more information to calculate this cost, for example gray value
840 and local gradient magnitude. These values can be stored in two images,
841 which appear as only one when we pass a <TT>MultiImageAccessor2</TT> to
842 the algorithms. Of course, the cost functor must accept a <TT>pair</TT>
843 of values for this to work. Instead of an actual image iterator, we
844 pass a <a href="CoordinateIterator.html">CoordinateIterator</a> which
845 selects the right pixels form both images.
846
847 <b> Usage:</b>
848
849 <b>\#include</b> <vigra/accessor.hxx><br>
850 Namespace: vigra
851
852 \code
853 using namespace vigra;
854
855 FImage gray_values(w,h), gradient_magnitude(w,h);
856 IImage seeds(w,h), labels(w,h);
857
858 seededRegionGrowing(
859 srcIterRange(CoordinateIterator(), CoordinateIterator(w,h),
860 MultiImageAccessor2<FImage::iterator, FImage::Accessor,
861 FImage::iterator, FImage::Accessor>
862 (gray_values.upperLeft(), gray_values.accessor(),
863 gradient_magnitude.upperLeft(), gradient_magnitude.accessor())),
864 srcImage(seeds),
865 destImage(labels),
866 SomeCostFunctor());
867 \endcode
868 */
869
870 template <class Iter1, class Acc1, class Iter2, class Acc2>
871 class MultiImageAccessor2
872 {
873 public:
874 /** The accessors value_type: construct a pair that contains
875 the corresponding image values.
876 */
877 typedef pair<typename Acc1::value_type, typename Acc2::value_type>
878 value_type;
879
880 /** Construct from two image iterators and associated accessors.
881 */
882 MultiImageAccessor2(Iter1 i1, Acc1 a1, Iter2 i2, Acc2 a2)
883 : i1_(i1), a1_(a1), i2_(i2), a2_(a2)
884 {}
885
886 /** read the current data item
887 */
888 template <class OFFSET>
889 value_type operator()(OFFSET const & d) const
890 {
891 return std::make_pair(a1_(i1_, d), a2_(i2_, d));
892 }
893
894 /** read the data item at an offset
895 */
896 template <class OFFSET1, class OFFSET2>
897 value_type operator()(OFFSET1 d1, OFFSET2 const & d2) const
898 {
899 d1 += d2;
900 return std::make_pair(a1_(i1_, d1), a2_(i2_, d1));
901 }
902
903 private:
904 Iter1 i1_;
905 Acc1 a1_;
906 Iter2 i2_;
907 Acc2 a2_;
908 };
909
910 //@}
911
912 template <class T>
913 struct AccessorTraits
914 {
915 typedef StandardAccessor<T> default_accessor;
916 typedef StandardConstAccessor<T> default_const_accessor;
917 };
918
919 #define VIGRA_DEFINE_ACCESSOR_TRAITS(VALUE, ACCESSOR, CONST_ACCESSOR) \
920 template <> \
921 struct AccessorTraits<VALUE > \
922 { \
923 typedef ACCESSOR<VALUE > default_accessor; \
924 typedef CONST_ACCESSOR<VALUE > default_const_accessor; \
925 };
926
927 VIGRA_DEFINE_ACCESSOR_TRAITS(signed char, StandardValueAccessor, StandardConstValueAccessor)
928 VIGRA_DEFINE_ACCESSOR_TRAITS(unsigned char, StandardValueAccessor, StandardConstValueAccessor)
929 VIGRA_DEFINE_ACCESSOR_TRAITS(short, StandardValueAccessor, StandardConstValueAccessor)
930 VIGRA_DEFINE_ACCESSOR_TRAITS(unsigned short, StandardValueAccessor, StandardConstValueAccessor)
931 VIGRA_DEFINE_ACCESSOR_TRAITS(int, StandardValueAccessor, StandardConstValueAccessor)
932 VIGRA_DEFINE_ACCESSOR_TRAITS(unsigned int, StandardValueAccessor, StandardConstValueAccessor)
933 VIGRA_DEFINE_ACCESSOR_TRAITS(long, StandardValueAccessor, StandardConstValueAccessor)
934 VIGRA_DEFINE_ACCESSOR_TRAITS(unsigned long, StandardValueAccessor, StandardConstValueAccessor)
935 VIGRA_DEFINE_ACCESSOR_TRAITS(float, StandardValueAccessor, StandardConstValueAccessor)
936 VIGRA_DEFINE_ACCESSOR_TRAITS(double, StandardValueAccessor, StandardConstValueAccessor)
937
938 template <class T, unsigned int RED_IDX, unsigned int GREEN_IDX, unsigned int BLUE_IDX> class RGBValue;
939 template <class T> class RGBAccessor;
940 template <class T, int SIZE> class TinyVector;
941
942 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
943
944 template <class T, unsigned int RED_IDX, unsigned int GREEN_IDX, unsigned int BLUE_IDX>
945 struct AccessorTraits<RGBValue<T, RED_IDX, GREEN_IDX, BLUE_IDX> >
946 {
947 typedef RGBAccessor<RGBValue<T, RED_IDX, GREEN_IDX, BLUE_IDX> > default_accessor;
948 typedef RGBAccessor<RGBValue<T, RED_IDX, GREEN_IDX, BLUE_IDX> > default_const_accessor;
949 };
950
951 template <class T, int SIZE>
952 struct AccessorTraits<TinyVector<T, SIZE> >
953 {
954 typedef VectorAccessor<TinyVector<T, SIZE> > default_accessor;
955 typedef VectorAccessor<TinyVector<T, SIZE> > default_const_accessor;
956 };
957
958 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
959
960 VIGRA_DEFINE_ACCESSOR_TRAITS(RGBValue<unsigned char>, RGBAccessor, RGBAccessor)
961 VIGRA_DEFINE_ACCESSOR_TRAITS(RGBValue<signed char>, RGBAccessor, RGBAccessor)
962 VIGRA_DEFINE_ACCESSOR_TRAITS(RGBValue<short>, RGBAccessor, RGBAccessor)
963 VIGRA_DEFINE_ACCESSOR_TRAITS(RGBValue<unsigned short>, RGBAccessor, RGBAccessor)
964 VIGRA_DEFINE_ACCESSOR_TRAITS(RGBValue<int>, RGBAccessor, RGBAccessor)
965 VIGRA_DEFINE_ACCESSOR_TRAITS(RGBValue<unsigned int>, RGBAccessor, RGBAccessor)
966 VIGRA_DEFINE_ACCESSOR_TRAITS(RGBValue<long>, RGBAccessor, RGBAccessor)
967 VIGRA_DEFINE_ACCESSOR_TRAITS(RGBValue<unsigned long>, RGBAccessor, RGBAccessor)
968 VIGRA_DEFINE_ACCESSOR_TRAITS(RGBValue<float>, RGBAccessor, RGBAccessor)
969 VIGRA_DEFINE_ACCESSOR_TRAITS(RGBValue<double>, RGBAccessor, RGBAccessor)
970
971 #define VIGRA_PIXELTYPE TinyVector<unsigned char, 2>
972 VIGRA_DEFINE_ACCESSOR_TRAITS(VIGRA_PIXELTYPE, VectorAccessor, VectorAccessor)
973 #undef VIGRA_PIXELTYPE
974 #define VIGRA_PIXELTYPE TinyVector<unsigned char, 3>
975 VIGRA_DEFINE_ACCESSOR_TRAITS(VIGRA_PIXELTYPE, VectorAccessor, VectorAccessor)
976 #undef VIGRA_PIXELTYPE
977 #define VIGRA_PIXELTYPE TinyVector<unsigned char, 4>
978 VIGRA_DEFINE_ACCESSOR_TRAITS(VIGRA_PIXELTYPE, VectorAccessor, VectorAccessor)
979 #undef VIGRA_PIXELTYPE
980 #define VIGRA_PIXELTYPE TinyVector<short, 2>
981 VIGRA_DEFINE_ACCESSOR_TRAITS(VIGRA_PIXELTYPE, VectorAccessor, VectorAccessor)
982 #undef VIGRA_PIXELTYPE
983 #define VIGRA_PIXELTYPE TinyVector<short, 3>
984 VIGRA_DEFINE_ACCESSOR_TRAITS(VIGRA_PIXELTYPE, VectorAccessor, VectorAccessor)
985 #undef VIGRA_PIXELTYPE
986 #define VIGRA_PIXELTYPE TinyVector<short, 4>
987 VIGRA_DEFINE_ACCESSOR_TRAITS(VIGRA_PIXELTYPE, VectorAccessor, VectorAccessor)
988 #undef VIGRA_PIXELTYPE
989 #define VIGRA_PIXELTYPE TinyVector<int, 2>
990 VIGRA_DEFINE_ACCESSOR_TRAITS(VIGRA_PIXELTYPE, VectorAccessor, VectorAccessor)
991 #undef VIGRA_PIXELTYPE
992 #define VIGRA_PIXELTYPE TinyVector<int, 3>
993 VIGRA_DEFINE_ACCESSOR_TRAITS(VIGRA_PIXELTYPE, VectorAccessor, VectorAccessor)
994 #undef VIGRA_PIXELTYPE
995 #define VIGRA_PIXELTYPE TinyVector<int, 4>
996 VIGRA_DEFINE_ACCESSOR_TRAITS(VIGRA_PIXELTYPE, VectorAccessor, VectorAccessor)
997 #undef VIGRA_PIXELTYPE
998 #define VIGRA_PIXELTYPE TinyVector<float, 2>
999 VIGRA_DEFINE_ACCESSOR_TRAITS(VIGRA_PIXELTYPE, VectorAccessor, VectorAccessor)
1000 #undef VIGRA_PIXELTYPE
1001 #define VIGRA_PIXELTYPE TinyVector<float, 3>
1002 VIGRA_DEFINE_ACCESSOR_TRAITS(VIGRA_PIXELTYPE, VectorAccessor, VectorAccessor)
1003 #undef VIGRA_PIXELTYPE
1004 #define VIGRA_PIXELTYPE TinyVector<float, 4>
1005 VIGRA_DEFINE_ACCESSOR_TRAITS(VIGRA_PIXELTYPE, VectorAccessor, VectorAccessor)
1006 #undef VIGRA_PIXELTYPE
1007 #define VIGRA_PIXELTYPE TinyVector<double, 2>
1008 VIGRA_DEFINE_ACCESSOR_TRAITS(VIGRA_PIXELTYPE, VectorAccessor, VectorAccessor)
1009 #undef VIGRA_PIXELTYPE
1010 #define VIGRA_PIXELTYPE TinyVector<double, 3>
1011 VIGRA_DEFINE_ACCESSOR_TRAITS(VIGRA_PIXELTYPE, VectorAccessor, VectorAccessor)
1012 #undef VIGRA_PIXELTYPE
1013 #define VIGRA_PIXELTYPE TinyVector<double, 4>
1014 VIGRA_DEFINE_ACCESSOR_TRAITS(VIGRA_PIXELTYPE, VectorAccessor, VectorAccessor)
1015 #undef VIGRA_PIXELTYPE
1016
1017 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
1018
1019 #undef VIGRA_DEFINE_ACCESSOR_TRAITS
1020
1021 } // namespace vigra
1022
1023 #endif // VIGRA_ACCESSOR_HXX
vigra::VectorAccessor::setComponent
void setComponent(V const &value, ITERATOR const &i, int idx) const
Definition: accessor.hxx:799
vigra::VectorElementAccessor
Accessor for one component of a vector.
Definition: accessor.hxx:539
vigra::VectorElementAccessor::set
void set(V const &value, ITERATOR const &i, OFFSET const &diff) const
Definition: accessor.hxx:585
vigra::StandardConstAccessor::operator()
VALUETYPE const & operator()(ITERATOR const &i, OFFSET const &diff) const
Definition: accessor.hxx:283
vigra::VectorElementAccessor::VectorElementAccessor
VectorElementAccessor(int index, ACCESSOR a=ACCESSOR())
Definition: accessor.hxx:550
vigra::VectorComponentValueAccessor::VectorComponentValueAccessor
VectorComponentValueAccessor(int index)
Definition: accessor.hxx:459
vigra::VectorComponentAccessor::set
void set(V const &value, ITERATOR const &i) const
Definition: accessor.hxx:398
vigra::VectorAccessor::setComponent
void setComponent(V const &value, ITERATOR const &i, OFFSET const &diff, int idx) const
Definition: accessor.hxx:820
vigra::VectorElementAccessor::value_type
ACCESSOR::component_type value_type
Definition: accessor.hxx:546
vigra::VectorComponentAccessor::value_type
VECTORTYPE::value_type value_type
Definition: accessor.hxx:371
vigra::StandardValueAccessor::set
void set(V value, ITERATOR const &i) const
Definition: accessor.hxx:228
vigra::VectorElementAccessor::operator()
value_type const & operator()(ITERATOR const &i) const
Definition: accessor.hxx:558
vigra::MultiImageAccessor2::value_type
pair< typename Acc1::value_type, typename Acc2::value_type > value_type
Definition: accessor.hxx:878
vigra::VectorAccessor::getComponent
component_type const & getComponent(ITERATOR const &i, OFFSET const &diff, int idx) const
Definition: accessor.hxx:808
vigra::VectorComponentValueAccessor
Accessor for one component of a vector.
Definition: accessor.hxx:449
vigra::StandardAccessor::value_type
VALUETYPE value_type
Definition: accessor.hxx:138
vigra::StandardValueAccessor::operator()
VALUETYPE operator()(ITERATOR const &i, OFFSET const &diff) const
Definition: accessor.hxx:219
vigra::SequenceAccessor::begin
iterator begin(ITERATOR const &i, OFFSET const &diff) const
Definition: accessor.hxx:672
vigra::VectorComponentValueAccessor::set
void set(V value, ITERATOR const &i) const
Definition: accessor.hxx:488
vigra::StandardConstValueAccessor
Encapsulate access to the values an iterator points to.
Definition: accessor.hxx:307
vigra::MultiImageAccessor2::operator()
value_type operator()(OFFSET1 d1, OFFSET2 const &d2) const
Definition: accessor.hxx:897
vigra::VectorComponentValueAccessor::value_type
VECTORTYPE::value_type value_type
Definition: accessor.hxx:455
vigra::StandardConstValueAccessor::operator()
VALUETYPE operator()(ITERATOR const &i, OFFSET const &diff) const
Definition: accessor.hxx:326
vigra::SequenceAccessor::size
unsigned int size(ITERATOR const &i) const
Definition: accessor.hxx:689
vigra::VectorComponentAccessor::operator()
value_type const & operator()(ITERATOR const &i) const
Definition: accessor.hxx:382
vigra::VectorAccessor
Accessor for items that are STL compatible vectors.
Definition: accessor.hxx:771
vigra::StandardValueAccessor::set
void set(V value, ITERATOR const &i, OFFSET const &diff) const
Definition: accessor.hxx:242
vigra::StandardAccessor::set
void set(V const &value, ITERATOR const &i, OFFSET const &diff) const
Definition: accessor.hxx:174
vigra::StandardValueAccessor::value_type
VALUETYPE value_type
Definition: accessor.hxx:203
vigra::VectorComponentAccessor::VectorComponentAccessor
VectorComponentAccessor(int index)
Definition: accessor.hxx:375
vigra::VectorAccessor::component_type
VECTOR::value_type component_type
Definition: accessor.hxx:777
vigra::SequenceAccessor
Accessor for items that are STL compatible sequences.
Definition: accessor.hxx:632
vigra::VectorComponentValueAccessor::set
void set(V value, ITERATOR const &i, OFFSET const &diff) const
Definition: accessor.hxx:499
vigra::SequenceAccessor::begin
iterator begin(ITERATOR const &i) const
Definition: accessor.hxx:655
vigra::StandardValueAccessor
Encapsulate access to the values an iterator points to.
Definition: accessor.hxx:198
vigra::MultiImageAccessor2
Access two images simultaneously.
Definition: accessor.hxx:871
vigra::VectorComponentAccessor::setIndex
void setIndex(int i)
Definition: accessor.hxx:416
vigra::VectorComponentValueAccessor::operator()
value_type operator()(ITERATOR const &i) const
Definition: accessor.hxx:469
vigra::VectorElementAccessor::setIndex
void setIndex(int i)
Definition: accessor.hxx:592
vigra::VectorElementAccessor::operator()
value_type const & operator()(ITERATOR const &i, OFFSET const &diff) const
Definition: accessor.hxx:564
vigra::VectorAccessor::ElementAccessor
VectorElementAccessor< VectorAccessor< VECTOR > > ElementAccessor
Definition: accessor.hxx:782
vigra::TinyVector
Class for fixed size vectors.This class contains an array of size SIZE of the specified VALUETYPE...
Definition: accessor.hxx:940
vigra::SequenceAccessor::end
iterator end(ITERATOR const &i, OFFSET const &diff) const
Definition: accessor.hxx:681
vigra::VectorComponentAccessor
Accessor for one component of a vector.
Definition: accessor.hxx:365
vigra::MultiImageAccessor2::operator()
value_type operator()(OFFSET const &d) const
Definition: accessor.hxx:889
vigra::StandardAccessor::operator()
VALUETYPE const & operator()(ITERATOR const &i, OFFSET const &diff) const
Definition: accessor.hxx:150
vigra::StandardAccessor::set
void set(V const &value, ITERATOR const &i) const
Definition: accessor.hxx:160
vigra::StandardConstAccessor
Encapsulate read access to the values an iterator points to.
Definition: accessor.hxx:269
vigra::SequenceAccessor::component_type
SEQUENCE::value_type component_type
Definition: accessor.hxx:638
vigra::VectorComponentValueAccessor::operator()
value_type operator()(ITERATOR const &i, OFFSET const &diff) const
Definition: accessor.hxx:478
vigra::StandardConstAccessor::operator()
VALUETYPE const & operator()(ITERATOR const &i) const
Definition: accessor.hxx:277
vigra::VectorComponentAccessor::set
void set(V const &value, ITERATOR const &i, OFFSET const &diff) const
Definition: accessor.hxx:409
vigra::StandardConstValueAccessor::operator()
VALUETYPE operator()(ITERATOR const &i) const
Definition: accessor.hxx:317
vigra::RGBValue
Class for a single RGB value.
Definition: accessor.hxx:938
vigra::StandardAccessor
Encapsulate access to the values an iterator points to.
Definition: accessor.hxx:133
vigra::VectorAccessor::getComponent
component_type const & getComponent(ITERATOR const &i, int idx) const
Definition: accessor.hxx:788
vigra::MultiImageAccessor2::MultiImageAccessor2
MultiImageAccessor2(Iter1 i1, Acc1 a1, Iter2 i2, Acc2 a2)
Definition: accessor.hxx:882
vigra::VectorComponentValueAccessor::setIndex
void setIndex(int i)
Definition: accessor.hxx:506
vigra::StandardValueAccessor::operator()
VALUETYPE operator()(ITERATOR const &i) const
Definition: accessor.hxx:210
vigra::SequenceAccessor::size
unsigned int size(ITERATOR const &i, OFFSET const &diff) const
Definition: accessor.hxx:694
vigra::VectorElementAccessor::set
void set(V const &value, ITERATOR const &i) const
Definition: accessor.hxx:574
vigra::VectorComponentAccessor::operator()
value_type const & operator()(ITERATOR const &i, OFFSET const &diff) const
Definition: accessor.hxx:388
vigra::RGBAccessor
Definition: accessor.hxx:939
vigra::SequenceAccessor::end
iterator end(ITERATOR const &i) const
Definition: accessor.hxx:663
vigra::StandardAccessor::operator()
VALUETYPE const & operator()(ITERATOR const &i) const
Definition: accessor.hxx:143

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python vigra 1.11.0 (Fri May 19 2017)