Generic Image Library: algorithm.hpp Source File

###  | #  |

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

algorithm.hpp
Go to the documentation of this file.
1 /*
2 Copyright 2005-2007 Adobe Systems Incorporated
3
4 Use, modification and distribution are subject to the Boost Software License,
5 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 http://www.boost.org/LICENSE_1_0.txt).
7
8 See http://opensource.adobe.com/gil for most recent version including documentation.
9 */
10
11 /*************************************************************************************************/
12
13 #ifndef GIL_ALGORITHM_HPP
14 #define GIL_ALGORITHM_HPP
15
16 #include <cassert>
17 #include <cstddef>
18 #include <cstring>
19 #include <algorithm>
20 #include <iterator>
21 #include <memory>
22 #include <typeinfo>
23
24 #include <boost/config.hpp>
25 #include <boost/utility/enable_if.hpp>
26 #include <boost/mpl/and.hpp>
27 #include <boost/mpl/or.hpp>
28
29 #include "gil_config.hpp"
30 #include "gil_concept.hpp"
31 #include "color_base_algorithm.hpp"
32 #include "image_view.hpp"
33 #include "image_view_factory.hpp"
34 #include "bit_aligned_pixel_iterator.hpp"
35
44
45 //#ifdef _MSC_VER
46 //#pragma warning(push)
47 //#pragma warning(disable : 4244) // conversion from 'gil::image<V,Alloc>::coord_t' to 'int', possible loss of data (visual studio compiler doesn't realize that the two types are the same)
48 //#endif
49
50 namespace boost { namespace gil {
51 //forward declarations
52 template <typename ChannelPtr, typename ColorSpace>
53 struct planar_pixel_iterator;
54 template <typename Iterator>
55 class memory_based_step_iterator;
56 template <typename StepIterator>
57 class memory_based_2d_locator;
58
59 // a tag denoting incompatible arguments
60 struct error_t {};
61
86
90
99 template <typename Derived, typename Result=void>
100 struct binary_operation_obj {
101 typedef Result result_type;
102
103 template <typename V1, typename V2> BOOST_FORCEINLINE
104 result_type operator()(const std::pair<const V1*,const V2*>& p) const {
105 return apply(*p.first, *p.second, typename views_are_compatible<V1,V2>::type());
106 }
107
108 template <typename V1, typename V2> BOOST_FORCEINLINE
109 result_type operator()(const V1& v1, const V2& v2) const {
110 return apply(v1, v2, typename views_are_compatible<V1,V2>::type());
111 }
112
113 result_type operator()(const error_t&) const { throw std::bad_cast(); }
114 private:
115
116 // dispatch from apply overload to a function with distinct name
117 template <typename V1, typename V2>
118 BOOST_FORCEINLINE result_type apply(const V1& v1, const V2& v2, mpl::false_) const {
119 return ((const Derived*)this)->apply_incompatible(v1,v2);
120 }
121
122 // dispatch from apply overload to a function with distinct name
123 template <typename V1, typename V2>
124 BOOST_FORCEINLINE result_type apply(const V1& v1, const V2& v2, mpl::true_) const {
125 return ((const Derived*)this)->apply_compatible(v1,v2);
126 }
127
128 // function with distinct name - it can be overloaded by subclasses
129 template <typename V1, typename V2>
130 BOOST_FORCEINLINE result_type apply_incompatible(const V1&, const V2&) const {
131 throw std::bad_cast();
132 }
133 };
134 } } // namespace boost::gil
135
141
145
146 namespace std {
149 template<typename T, typename Cs>
150 BOOST_FORCEINLINE boost::gil::pixel<T,Cs>*
151 copy(boost::gil::pixel<T,Cs>* first, boost::gil::pixel<T,Cs>* last,
152 boost::gil::pixel<T,Cs>* dst) {
153 return (boost::gil::pixel<T,Cs>*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst);
154 }
155
158 template<typename T, typename Cs>
159 BOOST_FORCEINLINE boost::gil::pixel<T,Cs>*
160 copy(const boost::gil::pixel<T,Cs>* first, const boost::gil::pixel<T,Cs>* last,
161 boost::gil::pixel<T,Cs>* dst) {
162 return (boost::gil::pixel<T,Cs>*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst);
163 }
164 } // namespace std
165
166 namespace boost { namespace gil {
167 namespace detail {
168 template <typename I, typename O> struct copy_fn {
169 BOOST_FORCEINLINE I operator()(I first, I last, O dst) const { return std::copy(first,last,dst); }
170 };
171 } // namespace detail
172 } } // namespace boost::gil
173
174 namespace std {
177 template<typename Cs, typename IC1, typename IC2> BOOST_FORCEINLINE
178 boost::gil::planar_pixel_iterator<IC2,Cs> copy(boost::gil::planar_pixel_iterator<IC1,Cs> first, boost::gil::planar_pixel_iterator<IC1,Cs> last, boost::gil::planar_pixel_iterator<IC2,Cs> dst) {
179 boost::gil::gil_function_requires<boost::gil::ChannelsCompatibleConcept<typename std::iterator_traits<IC1>::value_type,typename std::iterator_traits<IC2>::value_type> >();
180 static_for_each(first,last,dst,boost::gil::detail::copy_fn<IC1,IC2>());
181 return dst+(last-first);
182 }
183 } // namespace std
184
185 namespace boost { namespace gil {
186 namespace detail {
189 template <typename I, typename O>
190 struct copier_n {
191 BOOST_FORCEINLINE void operator()(I src, typename std::iterator_traits<I>::difference_type n, O dst) const { std::copy(src,src+n, dst); }
192 };
193
195 template <typename IL, typename O> // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept
196 struct copier_n<iterator_from_2d<IL>,O> {
197 typedef typename std::iterator_traits<iterator_from_2d<IL> >::difference_type diff_t;
198 BOOST_FORCEINLINE void operator()(iterator_from_2d<IL> src, diff_t n, O dst) const {
199 gil_function_requires<PixelLocatorConcept<IL> >();
200 gil_function_requires<MutablePixelIteratorConcept<O> >();
201 while (n>0) {
202 diff_t l=src.width()-src.x_pos();
203 diff_t numToCopy=(n<l ? n:l);
204 detail::copy_n(src.x(), numToCopy, dst);
205 dst+=numToCopy;
206 src+=numToCopy;
207 n-=numToCopy;
208 }
209 }
210 };
211
213 template <typename I, typename OL> // I Models ConstPixelIteratorConcept, OL Models PixelLocatorConcept
214 struct copier_n<I,iterator_from_2d<OL> > {
215 typedef typename std::iterator_traits<I>::difference_type diff_t;
216 BOOST_FORCEINLINE void operator()(I src, diff_t n, iterator_from_2d<OL> dst) const {
217 gil_function_requires<PixelIteratorConcept<I> >();
218 gil_function_requires<MutablePixelLocatorConcept<OL> >();
219 while (n>0) {
220 diff_t l=dst.width()-dst.x_pos();
221 diff_t numToCopy=(n<l ? n:l);
222 detail::copy_n(src, numToCopy, dst.x());
223 dst+=numToCopy;
224 src+=numToCopy;
225 n-=numToCopy;
226 }
227 }
228 };
229
231 template <typename IL, typename OL>
232 struct copier_n<iterator_from_2d<IL>,iterator_from_2d<OL> > {
233 typedef typename iterator_from_2d<IL>::difference_type diff_t;
234 BOOST_FORCEINLINE void operator()(iterator_from_2d<IL> src, diff_t n, iterator_from_2d<OL> dst) const {
235 gil_function_requires<PixelLocatorConcept<IL> >();
236 gil_function_requires<MutablePixelLocatorConcept<OL> >();
237 if (src.x_pos()!=dst.x_pos() || src.width()!=dst.width()) {
238 while(n-->0) {
239 *dst++=*src++;
240 }
241 }
242 while (n>0) {
243 diff_t l=dst.width()-dst.x_pos();
244 diff_t numToCopy=(n<l ? n : l);
245 detail::copy_n(src.x(), numToCopy, dst.x());
246 dst+=numToCopy;
247 src+=numToCopy;
248 n-=numToCopy;
249 }
250 }
251 };
252
253 template <typename SrcIterator, typename DstIterator>
254 BOOST_FORCEINLINE DstIterator copy_with_2d_iterators(SrcIterator first, SrcIterator last, DstIterator dst) {
255 typedef typename SrcIterator::x_iterator src_x_iterator;
256 typedef typename DstIterator::x_iterator dst_x_iterator;
257
258 typename SrcIterator::difference_type n = last - first;
259
260 if (first.is_1d_traversable()) {
261 if (dst.is_1d_traversable())
262 copier_n<src_x_iterator,dst_x_iterator>()(first.x(),n, dst.x());
263 else
264 copier_n<src_x_iterator,DstIterator >()(first.x(),n, dst);
265 } else {
266 if (dst.is_1d_traversable())
267 copier_n<SrcIterator,dst_x_iterator>()(first,n, dst.x());
268 else
269 copier_n<SrcIterator,DstIterator>()(first,n,dst);
270 }
271 return dst+n;
272 }
273 } // namespace detail
274 } } // namespace boost::gil
275
276 namespace std {
279 template <typename IL, typename OL>
280 BOOST_FORCEINLINE boost::gil::iterator_from_2d<OL> copy1(boost::gil::iterator_from_2d<IL> first, boost::gil::iterator_from_2d<IL> last, boost::gil::iterator_from_2d<OL> dst) {
281 return boost::gil::detail::copy_with_2d_iterators(first,last,dst);
282 }
283 } // namespace std
284
285 namespace boost { namespace gil {
288 template <typename View1, typename View2> BOOST_FORCEINLINE
289 void copy_pixels(const View1& src, const View2& dst) {
290 assert(src.dimensions()==dst.dimensions());
291 detail::copy_with_2d_iterators(src.begin(),src.end(),dst.begin());
292 }
293
299
305
306 namespace detail {
307 template <typename CC>
308 class copy_and_convert_pixels_fn : public binary_operation_obj<copy_and_convert_pixels_fn<CC> > {
309 private:
310 CC _cc;
311 public:
312 typedef typename binary_operation_obj<copy_and_convert_pixels_fn<CC> >::result_type result_type;
313 copy_and_convert_pixels_fn() {}
314 copy_and_convert_pixels_fn(CC cc_in) : _cc(cc_in) {}
315 // when the two color spaces are incompatible, a color conversion is performed
316 template <typename V1, typename V2> BOOST_FORCEINLINE
317 result_type apply_incompatible(const V1& src, const V2& dst) const {
318 copy_pixels(color_converted_view<typename V2::value_type>(src,_cc),dst);
319 }
320
321 // If the two color spaces are compatible, copy_and_convert is just copy
322 template <typename V1, typename V2> BOOST_FORCEINLINE
323 result_type apply_compatible(const V1& src, const V2& dst) const {
324 copy_pixels(src,dst);
325 }
326 };
327 } // namespace detail
328
330 template <typename V1, typename V2,typename CC>
331 BOOST_FORCEINLINE
332 void copy_and_convert_pixels(const V1& src, const V2& dst,CC cc) {
333 detail::copy_and_convert_pixels_fn<CC> ccp(cc);
334 ccp(src,dst);
335 }
336
337 struct default_color_converter;
338
340 template <typename View1, typename View2>
341 BOOST_FORCEINLINE
342 void copy_and_convert_pixels(const View1& src, const View2& dst) {
343 detail::copy_and_convert_pixels_fn<default_color_converter> ccp;
344 ccp(src,dst);
345 }
346 } } // namespace boost::gil
347
349 //
350 // std::fill and gil::fill_pixels
351 //
353
357
358 namespace std {
367 template <typename IL, typename V>
368 void fill(boost::gil::iterator_from_2d<IL> first, boost::gil::iterator_from_2d<IL> last, const V& val) {
369 boost::gil::gil_function_requires<boost::gil::MutablePixelLocatorConcept<IL> >();
370 if (first.is_1d_traversable()) {
371 std::fill(first.x(), last.x(), val);
372 } else {
373 // fill row by row
374 std::ptrdiff_t n=last-first;
375 while (n>0) {
376 std::ptrdiff_t numToDo=std::min<const std::ptrdiff_t>(n,(std::ptrdiff_t)(first.width()-first.x_pos()));
377 fill_n(first.x(), numToDo, val);
378 first+=numToDo;
379 n-=numToDo;
380 }
381 }
382 }
383 } // namespace std
384
385 namespace boost { namespace gil {
386 namespace detail {
388 struct std_fill_t {
389 template <typename It, typename P>
390 void operator()(It first, It last, const P& p_in) {
391 std::fill(first,last,p_in);
392 }
393 };
395 template <typename It, typename P>
396 BOOST_FORCEINLINE
397 void fill_aux(It first, It last, const P& p, mpl::true_) {
398 static_for_each(first,last,p,std_fill_t());
399 }
401 template <typename It, typename P>
402 BOOST_FORCEINLINE
403 void fill_aux(It first, It last, const P& p,mpl::false_) {
404 std::fill(first,last,p);
405 }
406 } // namespace detail
407
410 template <typename View, typename Value> BOOST_FORCEINLINE
411 void fill_pixels(const View& img_view, const Value& val) {
412 if (img_view.is_1d_traversable())
413 detail::fill_aux(img_view.begin().x(), img_view.end().x(),
414 val,is_planar<View>());
415 else
416 for (std::ptrdiff_t y=0; y<img_view.height(); ++y)
417 detail::fill_aux(img_view.row_begin(y),img_view.row_end(y),
418 val,is_planar<View>());
419 }
420
426
430
431 namespace detail {
432 template <typename It> BOOST_FORCEINLINE
433 void destruct_range_impl( It first
434 , It last
435 , typename enable_if< mpl::and_< is_pointer< It >
436 , mpl::not_< boost::has_trivial_destructor< typename std::iterator_traits<It>::value_type > >
437 >
438 >::type* /*ptr*/ = 0
439 )
440 {
441 while (first!=last) {
442 first->~value_t();
443 ++first;
444 }
445 }
446
447 template <typename It> BOOST_FORCEINLINE
448 void destruct_range_impl( It
449 , It
450 , typename enable_if< mpl::or_< mpl::not_< is_pointer< It > >
451 , boost::has_trivial_destructor< typename std::iterator_traits< It >::value_type >
452 >
453 >::type* /* ptr */ = 0)
454 {}
455
456 template <typename It> BOOST_FORCEINLINE
457 void destruct_range(It first, It last) {
458 destruct_range_impl( first
459 , last
460 );
461 }
462
463 struct std_destruct_t {
464 template <typename It> void operator()(It first, It last) const { destruct_range(first,last); }
465 };
466
468 template <typename It>
469 BOOST_FORCEINLINE
470 void destruct_aux(It first, It last, mpl::true_) {
471 static_for_each(first,last,std_destruct_t());
472 }
474 template <typename It>
475 BOOST_FORCEINLINE
476 void destruct_aux(It first, It last, mpl::false_) {
477 destruct_range(first,last);
478 }
479 } // namespace detail
480
483 template <typename View> BOOST_FORCEINLINE
484 void destruct_pixels(const View& img_view) {
485 if (img_view.is_1d_traversable())
486 detail::destruct_aux(img_view.begin().x(), img_view.end().x(),
487 is_planar<View>());
488 else
489 for (std::ptrdiff_t y=0; y<img_view.height(); ++y)
490 detail::destruct_aux(img_view.row_begin(y),img_view.row_end(y),
491 is_planar<View>());
492 }
493
499
503
504 namespace detail {
507 template <typename It, typename P>
508 BOOST_FORCEINLINE
509 void uninitialized_fill_aux(It first, It last,
510 const P& p, mpl::true_) {
511 int channel=0;
512 try {
513 typedef typename std::iterator_traits<It>::value_type pixel_t;
514 while (channel < num_channels<pixel_t>::value) {
515 std::uninitialized_fill(dynamic_at_c(first,channel), dynamic_at_c(last,channel),
516 dynamic_at_c(p,channel));
517 ++channel;
518 }
519 } catch (...) {
520 for (int c=0; c<channel; ++c)
521 destruct_range(dynamic_at_c(first,c), dynamic_at_c(last,c));
522 throw;
523 }
524 }
525
528 template <typename It, typename P>
529 BOOST_FORCEINLINE
530 void uninitialized_fill_aux(It first, It last,
531 const P& p,mpl::false_) {
532 std::uninitialized_fill(first,last,p);
533 }
534 } // namespace detail
535
540 template <typename View, typename Value>
541 void uninitialized_fill_pixels(const View& img_view, const Value& val) {
542 if (img_view.is_1d_traversable())
543 detail::uninitialized_fill_aux(img_view.begin().x(), img_view.end().x(),
544 val,is_planar<View>());
545 else {
546 typename View::y_coord_t y = 0;
547 try {
548 for (y=0; y<img_view.height(); ++y)
549 detail::uninitialized_fill_aux(img_view.row_begin(y),img_view.row_end(y),
550 val,is_planar<View>());
551 } catch(...) {
552 for (typename View::y_coord_t y0=0; y0<y; ++y0)
553 detail::destruct_aux(img_view.row_begin(y0),img_view.row_end(y0), is_planar<View>());
554 throw;
555 }
556 }
557 }
558
564
568
569 namespace detail {
570 template <typename It> BOOST_FORCEINLINE
571 void default_construct_range_impl(It first, It last, mpl::true_) {
572 typedef typename std::iterator_traits<It>::value_type value_t;
573 It first1=first;
574 try {
575 while (first!=last) {
576 new (first) value_t();
577 ++first;
578 }
579 } catch (...) {
580 destruct_range(first1,first);
581 throw;
582 }
583 }
584
585 template <typename It> BOOST_FORCEINLINE
586 void default_construct_range_impl(It, It, mpl::false_) {}
587
588 template <typename It> BOOST_FORCEINLINE
589 void default_construct_range(It first, It last) { default_construct_range_impl(first, last, typename is_pointer<It>::type()); }
590
592 template <typename It>
593 BOOST_FORCEINLINE
594 void default_construct_aux(It first, It last, mpl::true_) {
595 int channel=0;
596 try {
597 typedef typename std::iterator_traits<It>::value_type pixel_t;
598 while (channel < num_channels<pixel_t>::value) {
599 default_construct_range(dynamic_at_c(first,channel), dynamic_at_c(last,channel));
600 ++channel;
601 }
602 } catch (...) {
603 for (int c=0; c<channel; ++c)
604 destruct_range(dynamic_at_c(first,c), dynamic_at_c(last,c));
605 throw;
606 }
607 }
608
610 template <typename It>
611 BOOST_FORCEINLINE
612 void default_construct_aux(It first, It last, mpl::false_) {
613 default_construct_range(first,last);
614 }
615
616 template <typename View, bool IsPlanar>
617 struct has_trivial_pixel_constructor : public boost::has_trivial_constructor<typename View::value_type> {};
618 template <typename View>
619 struct has_trivial_pixel_constructor<View, true> : public boost::has_trivial_constructor<typename channel_type<View>::type> {};
620 } // namespace detail
621
622 namespace detail {
623 template< typename View, bool B > BOOST_FORCEINLINE
624 void default_construct_pixels_impl( const View& img_view
625 , boost::enable_if< is_same< mpl::bool_< B >
626 , mpl::false_
627 >
628 >* /* ptr */ = 0
629 )
630 {
631 if( img_view.is_1d_traversable() )
632 {
633 detail::default_construct_aux( img_view.begin().x()
634 , img_view.end().x()
635 , is_planar<View>()
636 );
637 }
638 else
639 {
640 typename View::y_coord_t y = 0;
641 try
642 {
643 for( y = 0; y < img_view.height(); ++y )
644 {
645 detail::default_construct_aux( img_view.row_begin( y )
646 ,img_view.row_end( y )
647 , is_planar<View>()
648 );
649 }
650 } catch(...)
651 {
652 for (typename View::y_coord_t y0 = 0; y0 < y; ++y0 )
653 {
654 detail::destruct_aux( img_view.row_begin(y0)
655 , img_view.row_end(y0)
656 , is_planar<View>()
657 );
658 }
659
660 throw;
661 }
662 }
663 }
664 } // namespace detail
665
670 template <typename View>
671 void default_construct_pixels(const View& img_view) {
672 detail::default_construct_pixels_impl< View
673 , detail::has_trivial_pixel_constructor< View
674 , is_planar< View >::value
675 >::value
676 >( img_view );
677 }
678
684
688
689 namespace detail {
691 template <typename It1, typename It2>
692 BOOST_FORCEINLINE
693 void uninitialized_copy_aux(It1 first1, It1 last1,
694 It2 first2, mpl::true_) {
695 int channel=0;
696 try {
697 typedef typename std::iterator_traits<It1>::value_type pixel_t;
698 while (channel < num_channels<pixel_t>::value) {
699 std::uninitialized_copy(dynamic_at_c(first1,channel), dynamic_at_c(last1,channel), dynamic_at_c(first2,channel));
700 ++channel;
701 }
702 } catch (...) {
703 It2 last2=first2;
704 std::advance(last2, std::distance(first1,last1));
705 for (int c=0; c<channel; ++c)
706 destruct_range(dynamic_at_c(first2,c), dynamic_at_c(last2,c));
707 throw;
708 }
709 }
711 template <typename It1, typename It2>
712 BOOST_FORCEINLINE
713 void uninitialized_copy_aux(It1 first1, It1 last1,
714 It2 first2,mpl::false_) {
715 std::uninitialized_copy(first1,last1,first2);
716 }
717 } // namespace detail
718
723 template <typename View1, typename View2>
724 void uninitialized_copy_pixels(const View1& view1, const View2& view2) {
725 typedef mpl::bool_<is_planar<View1>::value && is_planar<View2>::value> is_planar;
726 assert(view1.dimensions()==view2.dimensions());
727 if (view1.is_1d_traversable() && view2.is_1d_traversable())
728 detail::uninitialized_copy_aux(view1.begin().x(), view1.end().x(),
729 view2.begin().x(),
730 is_planar());
731 else {
732 typename View1::y_coord_t y = 0;
733 try {
734 for (y=0; y<view1.height(); ++y)
735 detail::uninitialized_copy_aux(view1.row_begin(y), view1.row_end(y),
736 view2.row_begin(y),
737 is_planar());
738 } catch(...) {
739 for (typename View1::y_coord_t y0=0; y0<y; ++y0)
740 detail::destruct_aux(view2.row_begin(y0),view2.row_end(y0), is_planar());
741 throw;
742 }
743 }
744 }
745
751
760
762 template <typename V, typename F>
763 F for_each_pixel(const V& img, F fun) {
764 if (img.is_1d_traversable()) {
765 return std::for_each(img.begin().x(), img.end().x(), fun);
766 } else {
767 for (std::ptrdiff_t y=0; y<img.height(); ++y)
768 fun = std::for_each(img.row_begin(y),img.row_end(y),fun);
769 return fun;
770 }
771 }
772
776
778 template <typename View, typename F>
779 F for_each_pixel_position(const View& img, F fun) {
780 typename View::xy_locator loc=img.xy_at(0,0);
781 for (std::ptrdiff_t y=0; y<img.height(); ++y) {
782 for (std::ptrdiff_t x=0; x<img.width(); ++x, ++loc.x())
783 fun(loc);
784 loc.x()-=img.width(); ++loc.y();
785 }
786 return fun;
787 }
788
794
798
801 template <typename View, typename F>
802 void generate_pixels(const View& v, F fun) {
803 if (v.is_1d_traversable()) {
804 std::generate(v.begin().x(), v.end().x(), fun);
805 } else {
806 for (std::ptrdiff_t y=0; y<v.height(); ++y)
807 std::generate(v.row_begin(y),v.row_end(y),fun);
808 }
809 }
810
816
820
821 template <typename I1, typename I2> BOOST_FORCEINLINE bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2);
822
823 namespace detail {
824 template <typename I1, typename I2>
825 struct equal_n_fn {
826 BOOST_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, I2 i2) const { return std::equal(i1,i1+n, i2); }
827 };
828
831 template<typename T, typename Cs>
832 struct equal_n_fn<const pixel<T,Cs>*, const pixel<T,Cs>*> {
833 BOOST_FORCEINLINE bool operator()(const pixel<T,Cs>* i1, std::ptrdiff_t n, const pixel<T,Cs>* i2) const {
834 return memcmp(i1, i2, n*sizeof(pixel<T,Cs>))==0;
835 }
836 };
837 template<typename T, typename Cs>
838 struct equal_n_fn<pixel<T,Cs>*, pixel<T,Cs>*> : equal_n_fn<const pixel<T,Cs>*, const pixel<T,Cs>*> {};
839
843 template<typename IC, typename Cs>
844 struct equal_n_fn<planar_pixel_iterator<IC,Cs>, planar_pixel_iterator<IC,Cs> > {
845 BOOST_FORCEINLINE bool operator()(const planar_pixel_iterator<IC,Cs> i1, std::ptrdiff_t n, const planar_pixel_iterator<IC,Cs> i2) const {
846 std::ptrdiff_t numBytes=n*sizeof(typename std::iterator_traits<IC>::value_type);
847
848 for (std::ptrdiff_t i=0; i<mpl::size<Cs>::value; ++i)
849 if (memcmp(dynamic_at_c(i1,i), dynamic_at_c(i2,i), numBytes)!=0)
850 return false;
851 return true;
852 }
853 };
854
856 template <typename Loc, typename I2> // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept
857 struct equal_n_fn<boost::gil::iterator_from_2d<Loc>,I2> {
858 BOOST_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc> i1, std::ptrdiff_t n, I2 i2) const {
859 gil_function_requires<boost::gil::PixelLocatorConcept<Loc> >();
860 gil_function_requires<boost::gil::PixelIteratorConcept<I2> >();
861 while (n>0) {
862 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n, i1.width()-i1.x_pos());
863 if (!equal_n(i1.x(), num, i2))
864 return false;
865 i1+=num;
866 i2+=num;
867 n-=num;
868 }
869 return true;
870 }
871 };
872
874 template <typename I1, typename Loc> // I Models PixelIteratorConcept, OL Models PixelLocatorConcept
875 struct equal_n_fn<I1,boost::gil::iterator_from_2d<Loc> > {
876 BOOST_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc> i2) const {
877 gil_function_requires<boost::gil::PixelIteratorConcept<I1> >();
878 gil_function_requires<boost::gil::PixelLocatorConcept<Loc> >();
879 while (n>0) {
880 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
881 if (!equal_n(i1, num, i2.x()))
882 return false;
883 i1+=num;
884 i2+=num;
885 n-=num;
886 }
887 return true;
888 }
889 };
890
892 template <typename Loc1, typename Loc2>
893 struct equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2> > {
894 BOOST_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc1> i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc2> i2) const {
895 gil_function_requires<boost::gil::PixelLocatorConcept<Loc1> >();
896 gil_function_requires<boost::gil::PixelLocatorConcept<Loc2> >();
897 if (i1.x_pos()!=i2.x_pos() || i1.width()!=i2.width()) {
898 while(n-->0) {
899 if (*i1++!=*i2++) return false;
900 }
901 }
902 while (n>0) {
903 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
904 if (!equal_n(i1.x(), num, i2.x()))
905 return false;
906 i1+=num;
907 i2+=num;
908 n-=num;
909 }
910 return true;
911 }
912 };
913 } // namespace detail
914
915 template <typename I1, typename I2> BOOST_FORCEINLINE
916 bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2) {
917 return detail::equal_n_fn<I1,I2>()(i1,n,i2);
918 }
919 } } // namespace boost::gil
920
921 namespace std {
933 template <typename Loc1, typename Loc2> BOOST_FORCEINLINE
934 bool equal(boost::gil::iterator_from_2d<Loc1> first, boost::gil::iterator_from_2d<Loc1> last, boost::gil::iterator_from_2d<Loc2> first2) {
935 boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc1> >();
936 boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc2> >();
937 std::ptrdiff_t n=last-first;
938 if (first.is_1d_traversable()) {
939 if (first2.is_1d_traversable())
940 return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,typename Loc2::x_iterator>()(first.x(),n, first2.x());
941 else
942 return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,boost::gil::iterator_from_2d<Loc2> >()(first.x(),n, first2);
943 } else {
944 if (first2.is_1d_traversable())
945 return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,typename Loc2::x_iterator>()(first,n, first2.x());
946 else
947 return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2> >()(first,n,first2);
948 }
949 }
950 } // namespace std
951
952 namespace boost { namespace gil {
955 template <typename View1, typename View2> BOOST_FORCEINLINE
956 bool equal_pixels(const View1& v1, const View2& v2) {
957 assert(v1.dimensions()==v2.dimensions());
958 return std::equal(v1.begin(),v1.end(),v2.begin()); // std::equal has overloads with GIL iterators for optimal performance
959 }
960
966
970
973 template <typename View1, typename View2, typename F> BOOST_FORCEINLINE
974 F transform_pixels(const View1& src,const View2& dst, F fun) {
975 assert(src.dimensions()==dst.dimensions());
976 for (std::ptrdiff_t y=0; y<src.height(); ++y) {
977 typename View1::x_iterator srcIt=src.row_begin(y);
978 typename View2::x_iterator dstIt=dst.row_begin(y);
979 for (std::ptrdiff_t x=0; x<src.width(); ++x)
980 dstIt[x]=fun(srcIt[x]);
981 }
982 return fun;
983 }
984
987 template <typename View1, typename View2, typename View3, typename F> BOOST_FORCEINLINE
988 F transform_pixels(const View1& src1, const View2& src2,const View3& dst, F fun) {
989 for (std::ptrdiff_t y=0; y<dst.height(); ++y) {
990 typename View1::x_iterator srcIt1=src1.row_begin(y);
991 typename View2::x_iterator srcIt2=src2.row_begin(y);
992 typename View3::x_iterator dstIt=dst.row_begin(y);
993 for (std::ptrdiff_t x=0; x<dst.width(); ++x)
994 dstIt[x]=fun(srcIt1[x],srcIt2[x]);
995 }
996 return fun;
997 }
998
1002
1005 template <typename View1, typename View2, typename F> BOOST_FORCEINLINE
1006 F transform_pixel_positions(const View1& src,const View2& dst, F fun) {
1007 assert(src.dimensions()==dst.dimensions());
1008 typename View1::xy_locator loc=src.xy_at(0,0);
1009 for (std::ptrdiff_t y=0; y<src.height(); ++y) {
1010 typename View2::x_iterator dstIt=dst.row_begin(y);
1011 for (std::ptrdiff_t x=0; x<src.width(); ++x, ++loc.x())
1012 dstIt[x]=fun(loc);
1013 loc.x()-=src.width(); ++loc.y();
1014 }
1015 return fun;
1016 }
1017
1020 template <typename View1, typename View2, typename View3, typename F> BOOST_FORCEINLINE
1021 F transform_pixel_positions(const View1& src1,const View2& src2,const View3& dst, F fun) {
1022 assert(src1.dimensions()==dst.dimensions());
1023 assert(src2.dimensions()==dst.dimensions());
1024 typename View1::xy_locator loc1=src1.xy_at(0,0);
1025 typename View2::xy_locator loc2=src2.xy_at(0,0);
1026 for (std::ptrdiff_t y=0; y<src1.height(); ++y) {
1027 typename View3::x_iterator dstIt=dst.row_begin(y);
1028 for (std::ptrdiff_t x=0; x<src1.width(); ++x, ++loc1.x(), ++loc2.x())
1029 dstIt[x]=fun(loc1,loc2);
1030 loc1.x()-=src1.width(); ++loc1.y();
1031 loc2.x()-=src2.width(); ++loc2.y();
1032 }
1033 return fun;
1034 }
1035 } } // namespace boost::gil
1036
1037 //#ifdef _MSC_VER
1038 //#pragma warning(pop)
1039 //#endif
1040
1041 #endif
image_view.hpp
image view class
boost::gil::uninitialized_fill_pixels
void uninitialized_fill_pixels(const View &img_view, const Value &val)
std::uninitialized_fill for image views. Does not support planar heterogeneous views. If an exception is thrown destructs any in-place copy-constructed pixels
Definition: algorithm.hpp:541
color_base_algorithm.hpp
pixel related algorithms
boost::gil::pixel
Represents a pixel value (a container of channels). Models: HomogeneousColorBaseValueConcept, PixelValueConcept, HomogeneousPixelBasedConcept.
Definition: metafunctions.hpp:44
boost::gil::generate_pixels
void generate_pixels(const View &v, F fun)
std::generate for image views
Definition: algorithm.hpp:802
boost::gil::transform_pixels
BOOST_FORCEINLINE F transform_pixels(const View1 &src1, const View2 &src2, const View3 &dst, F fun)
transform_pixels with two sources
Definition: algorithm.hpp:988
boost::gil::planar_pixel_iterator
An iterator over planar pixels. Models HomogeneousColorBaseConcept, PixelIteratorConcept, HomogeneousPixelBasedConcept, MemoryBasedIteratorConcept, HasDynamicXStepTypeConcept.
Definition: algorithm.hpp:53
gil_concept.hpp
Concept check classes for GIL concepts.
boost::gil::detail::copier_n
Definition: algorithm.hpp:190
boost::gil::iterator_from_2d
Provides 1D random-access navigation to the pixels of the image. Models: PixelIteratorConcept, PixelBasedConcept, HasDynamicXStepTypeConcept.
Definition: iterator_from_2d.hpp:52
boost::gil::memory_based_2d_locator
Memory-based pixel locator. Models: PixelLocatorConcept,HasDynamicXStepTypeConcept,HasDynamicYStepTypeConcept,HasTransposedTypeConceptThe class takes a step iterator as a parameter. The step iterator provides navigation along the vertical axis while its base iterator provides horizontal navigation.
Definition: algorithm.hpp:57
boost::gil::equal_pixels
BOOST_FORCEINLINE bool equal_pixels(const View1 &v1, const View2 &v2)
std::equal for image views
Definition: algorithm.hpp:956
std::fill
void fill(boost::gil::iterator_from_2d< IL > first, boost::gil::iterator_from_2d< IL > last, const V &val)
std::fill(I,I,V) with I being a iterator_from_2d
Definition: algorithm.hpp:368
boost::gil::views_are_compatible
Returns whether two views are compatible.
Definition: gil_concept.hpp:2050
boost::gil::copy_pixels
BOOST_FORCEINLINE void copy_pixels(const View1 &src, const View2 &dst)
std::copy for image views
Definition: algorithm.hpp:289
boost::gil::fill_pixels
BOOST_FORCEINLINE void fill_pixels(const View &img_view, const Value &val)
std::fill for image views
Definition: algorithm.hpp:411
boost::gil::default_construct_pixels
void default_construct_pixels(const View &img_view)
Invokes the in-place default constructor on every pixel of the (uninitialized) view. Does not support planar heterogeneous views. If an exception is thrown destructs any in-place default-constructed pixels.
Definition: algorithm.hpp:671
std::copy1
BOOST_FORCEINLINE boost::gil::iterator_from_2d< OL > copy1(boost::gil::iterator_from_2d< IL > first, boost::gil::iterator_from_2d< IL > last, boost::gil::iterator_from_2d< OL > dst)
std::copy(I1,I1,I2) with I1 and I2 being a iterator_from_2d
Definition: algorithm.hpp:280
std::copy
BOOST_FORCEINLINE boost::gil::planar_pixel_iterator< IC2, Cs > copy(boost::gil::planar_pixel_iterator< IC1, Cs > first, boost::gil::planar_pixel_iterator< IC1, Cs > last, boost::gil::planar_pixel_iterator< IC2, Cs > dst)
Copy when both src and dst are planar pointers is copy for each channel.
Definition: algorithm.hpp:178
std::equal
BOOST_FORCEINLINE bool equal(boost::gil::iterator_from_2d< Loc1 > first, boost::gil::iterator_from_2d< Loc1 > last, boost::gil::iterator_from_2d< Loc2 > first2)
std::equal(I1,I1,I2) with I1 and I2 being a iterator_from_2d
Definition: algorithm.hpp:934
boost::gil::binary_operation_obj
A generic binary operation on viewsUse this class as a convenience superclass when defining an operat...
Definition: algorithm.hpp:100
boost::gil::detail::std_fill_t
struct to do std::fill
Definition: algorithm.hpp:388
gil_config.hpp
GIL configuration file.
boost::gil::transform_pixel_positions
BOOST_FORCEINLINE F transform_pixel_positions(const View1 &src1, const View2 &src2, const View3 &dst, F fun)
transform_pixel_positions with two sources
Definition: algorithm.hpp:1021
boost::gil::uninitialized_copy_pixels
void uninitialized_copy_pixels(const View1 &view1, const View2 &view2)
std::uninitialized_copy for image views. Does not support planar heterogeneous views. If an exception is thrown destructs any in-place copy-constructed objects
Definition: algorithm.hpp:724
image_view_factory.hpp
Methods for constructing image views from raw data or other image views /.
boost::gil::destruct_pixels
BOOST_FORCEINLINE void destruct_pixels(const View &img_view)
Invokes the in-place destructor on every pixel of the view.
Definition: algorithm.hpp:484
boost::gil::memory_based_step_iterator
MEMORY-BASED STEP ITERATOR.
Definition: algorithm.hpp:55
bit_aligned_pixel_iterator.hpp
A model of a heterogeneous pixel that is not byte aligned. Examples are bitmap (1-bit pixels) or 6-bi...