annotate DEPENDENCIES/generic/include/boost/gil/algorithm.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 /*
Chris@16 2 Copyright 2005-2007 Adobe Systems Incorporated
Chris@16 3
Chris@16 4 Use, modification and distribution are subject to the Boost Software License,
Chris@16 5 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 6 http://www.boost.org/LICENSE_1_0.txt).
Chris@16 7
Chris@16 8 See http://opensource.adobe.com/gil for most recent version including documentation.
Chris@16 9 */
Chris@16 10
Chris@16 11
Chris@16 12 /*************************************************************************************************/
Chris@16 13
Chris@16 14 #ifndef GIL_ALGORITHM_HPP
Chris@16 15 #define GIL_ALGORITHM_HPP
Chris@16 16
Chris@16 17 #include <cassert>
Chris@16 18 #include <cstddef>
Chris@16 19 #include <cstring>
Chris@16 20 #include <algorithm>
Chris@16 21 #include <iterator>
Chris@16 22 #include <memory>
Chris@16 23 #include <typeinfo>
Chris@16 24 #include "gil_config.hpp"
Chris@16 25 #include "gil_concept.hpp"
Chris@16 26 #include "color_base_algorithm.hpp"
Chris@16 27 #include "image_view.hpp"
Chris@16 28 #include "image_view_factory.hpp"
Chris@16 29 #include "bit_aligned_pixel_iterator.hpp"
Chris@16 30
Chris@16 31 ////////////////////////////////////////////////////////////////////////////////////////
Chris@16 32 /// \file
Chris@16 33 /// \brief Some basic STL-style algorithms when applied to image views
Chris@16 34 /// \author Lubomir Bourdev and Hailin Jin \n
Chris@16 35 /// Adobe Systems Incorporated
Chris@16 36 /// \date 2005-2008 \n Last updated on March 12, 2008
Chris@16 37 ///
Chris@16 38 ////////////////////////////////////////////////////////////////////////////////////////
Chris@16 39
Chris@16 40 //#ifdef _MSC_VER
Chris@16 41 //#pragma warning(push)
Chris@16 42 //#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)
Chris@16 43 //#endif
Chris@16 44
Chris@16 45 namespace boost { namespace gil {
Chris@16 46
Chris@16 47 //forward declarations
Chris@16 48 template <typename ChannelPtr, typename ColorSpace>
Chris@16 49 struct planar_pixel_iterator;
Chris@16 50 template <typename Iterator>
Chris@16 51 class memory_based_step_iterator;
Chris@16 52 template <typename StepIterator>
Chris@16 53 class memory_based_2d_locator;
Chris@16 54
Chris@16 55 // a tag denoting incompatible arguments
Chris@16 56 struct error_t {};
Chris@16 57
Chris@16 58 /// \defgroup ImageViewSTLAlgorithms STL-like Algorithms
Chris@16 59 /// \ingroup ImageViewAlgorithm
Chris@16 60 /// \brief Image view-equivalents of STL algorithms
Chris@16 61 ///
Chris@16 62 /// Image views provide 1D iteration of their pixels via \p begin() and \p end() methods,
Chris@16 63 /// which makes it possible to use STL algorithms with them. However, using nested loops
Chris@16 64 /// over X and Y is in many cases more efficient. The algorithms in this section resemble
Chris@16 65 /// STL algorithms, but they abstract away the nested loops and take views (as opposed to ranges) as input.
Chris@16 66 ///
Chris@16 67 /// Most algorithms check whether the image views are 1D-traversable. A 1D-traversable image view has no gaps
Chris@16 68 /// at the end of the rows. In other words, if an x_iterator of that view is advanced past the last pixel in a row
Chris@16 69 /// it will move to the first pixel of the next row. When image views are 1D-traversable, the algorithms use
Chris@16 70 /// a single loop and run more efficiently. If one or more of the input views are not 1D-traversable, the algorithms
Chris@16 71 /// fall-back to an X-loop nested inside a Y-loop.
Chris@16 72 ///
Chris@16 73 /// The algorithms typically delegate the work to their corresponding STL algorithms. For example, \p copy_pixels calls
Chris@16 74 /// \p std::copy either for each row, or, when the images are 1D-traversable, once for all pixels.
Chris@16 75 ///
Chris@16 76 /// In addition, overloads are sometimes provided for the STL algorithms. For example, std::copy for planar iterators
Chris@16 77 /// is overloaded to perform \p std::copy for each of the planes. \p std::copy over bitwise-copiable pixels results in
Chris@16 78 /// std::copy over unsigned char, which STL typically implements via \p memmove.
Chris@16 79 ///
Chris@16 80 /// As a result \p copy_pixels may result in a single call to \p memmove for interleaved 1D-traversable views,
Chris@16 81 /// or one per each plane of planar 1D-traversable views, or one per each row of interleaved non-1D-traversable images, etc.
Chris@16 82
Chris@16 83
Chris@16 84 /// \defgroup STLOptimizations Performance overloads of STL algorithms
Chris@16 85 /// \ingroup ImageViewAlgorithm
Chris@16 86 /// \brief overloads of STL algorithms allowing more efficient implementation when used with GIL constructs
Chris@16 87
Chris@16 88 /// \brief A generic binary operation on views
Chris@16 89 /// \ingroup ImageViewSTLAlgorithms
Chris@16 90 ///
Chris@16 91 /// Use this class as a convenience superclass when defining an operation for any image views.
Chris@16 92 /// Many operations have different behavior when the two views are compatible. This class checks
Chris@16 93 /// for compatibility and invokes apply_compatible(V1,V2) or apply_incompatible(V1,V2) of the subclass.
Chris@16 94 /// You must provide apply_compatible(V1,V2) method in your subclass, but apply_incompatible(V1,V2)
Chris@16 95 /// is not required and the default throws std::bad_cast.
Chris@16 96 template <typename Derived, typename Result=void>
Chris@16 97 struct binary_operation_obj {
Chris@16 98 typedef Result result_type;
Chris@16 99
Chris@16 100 template <typename V1, typename V2> GIL_FORCEINLINE
Chris@16 101 result_type operator()(const std::pair<const V1*,const V2*>& p) const {
Chris@16 102 return apply(*p.first, *p.second, typename views_are_compatible<V1,V2>::type());
Chris@16 103 }
Chris@16 104
Chris@16 105 template <typename V1, typename V2> GIL_FORCEINLINE
Chris@16 106 result_type operator()(const V1& v1, const V2& v2) const {
Chris@16 107 return apply(v1, v2, typename views_are_compatible<V1,V2>::type());
Chris@16 108 }
Chris@16 109
Chris@16 110 result_type operator()(const error_t&) const { throw std::bad_cast(); }
Chris@16 111 private:
Chris@16 112
Chris@16 113 // dispatch from apply overload to a function with distinct name
Chris@16 114 template <typename V1, typename V2>
Chris@16 115 GIL_FORCEINLINE result_type apply(const V1& v1, const V2& v2, mpl::false_) const {
Chris@16 116 return ((const Derived*)this)->apply_incompatible(v1,v2);
Chris@16 117 }
Chris@16 118
Chris@16 119 // dispatch from apply overload to a function with distinct name
Chris@16 120 template <typename V1, typename V2>
Chris@16 121 GIL_FORCEINLINE result_type apply(const V1& v1, const V2& v2, mpl::true_) const {
Chris@16 122 return ((const Derived*)this)->apply_compatible(v1,v2);
Chris@16 123 }
Chris@16 124
Chris@16 125 // function with distinct name - it can be overloaded by subclasses
Chris@16 126 template <typename V1, typename V2>
Chris@16 127 GIL_FORCEINLINE result_type apply_incompatible(const V1& v1, const V2& v2) const {
Chris@16 128 throw std::bad_cast();
Chris@16 129 }
Chris@16 130 };
Chris@16 131 } } // namespace boost::gil
Chris@16 132
Chris@16 133 //////////////////////////////////////////////////////////////////////////////////////
Chris@16 134 ///
Chris@16 135 /// std::copy and gil::copy_pixels
Chris@16 136 ///
Chris@16 137 //////////////////////////////////////////////////////////////////////////////////////
Chris@16 138
Chris@16 139 /// \defgroup ImageViewSTLAlgorithmsCopyPixels copy_pixels
Chris@16 140 /// \ingroup ImageViewSTLAlgorithms
Chris@16 141 /// \brief std::copy for image views
Chris@16 142
Chris@16 143 namespace std {
Chris@16 144
Chris@16 145 /// \ingroup STLOptimizations
Chris@16 146 /// \brief Copy when both src and dst are interleaved and of the same type can be just memmove
Chris@16 147 template<typename T, typename Cs>
Chris@16 148 GIL_FORCEINLINE boost::gil::pixel<T,Cs>*
Chris@16 149 copy(boost::gil::pixel<T,Cs>* first, boost::gil::pixel<T,Cs>* last,
Chris@16 150 boost::gil::pixel<T,Cs>* dst) {
Chris@16 151 return (boost::gil::pixel<T,Cs>*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst);
Chris@16 152 }
Chris@16 153
Chris@16 154 /// \ingroup STLOptimizations
Chris@16 155 /// \brief Copy when both src and dst are interleaved and of the same type can be just memmove
Chris@16 156 template<typename T, typename Cs>
Chris@16 157 GIL_FORCEINLINE boost::gil::pixel<T,Cs>*
Chris@16 158 copy(const boost::gil::pixel<T,Cs>* first, const boost::gil::pixel<T,Cs>* last,
Chris@16 159 boost::gil::pixel<T,Cs>* dst) {
Chris@16 160 return (boost::gil::pixel<T,Cs>*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst);
Chris@16 161 }
Chris@16 162 } // namespace std
Chris@16 163
Chris@16 164 namespace boost { namespace gil {
Chris@16 165 namespace detail {
Chris@16 166 template <typename I, typename O> struct copy_fn {
Chris@16 167 GIL_FORCEINLINE I operator()(I first, I last, O dst) const { return std::copy(first,last,dst); }
Chris@16 168 };
Chris@16 169 } // namespace detail
Chris@16 170 } } // namespace boost::gil
Chris@16 171
Chris@16 172 namespace std {
Chris@16 173 /// \ingroup STLOptimizations
Chris@16 174 /// \brief Copy when both src and dst are planar pointers is copy for each channel
Chris@16 175 template<typename Cs, typename IC1, typename IC2> GIL_FORCEINLINE
Chris@16 176 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) {
Chris@16 177 boost::gil::gil_function_requires<boost::gil::ChannelsCompatibleConcept<typename std::iterator_traits<IC1>::value_type,typename std::iterator_traits<IC2>::value_type> >();
Chris@16 178 static_for_each(first,last,dst,boost::gil::detail::copy_fn<IC1,IC2>());
Chris@16 179 return dst+(last-first);
Chris@16 180 }
Chris@16 181 } // namespace std
Chris@16 182
Chris@16 183 namespace boost { namespace gil {
Chris@16 184 namespace detail {
Chris@16 185 /// Does a copy-n. If the inputs contain image iterators, performs a copy at each row using the row iterators
Chris@16 186 /// \ingroup CopyPixels
Chris@16 187 template <typename I, typename O>
Chris@16 188 struct copier_n {
Chris@16 189 GIL_FORCEINLINE void operator()(I src, typename std::iterator_traits<I>::difference_type n, O dst) const { std::copy(src,src+n, dst); }
Chris@16 190 };
Chris@16 191
Chris@16 192 /// Source range is delimited by image iterators
Chris@16 193 template <typename IL, typename O> // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept
Chris@16 194 struct copier_n<iterator_from_2d<IL>,O> {
Chris@16 195 typedef typename std::iterator_traits<iterator_from_2d<IL> >::difference_type diff_t;
Chris@16 196 GIL_FORCEINLINE void operator()(iterator_from_2d<IL> src, diff_t n, O dst) const {
Chris@16 197 gil_function_requires<PixelLocatorConcept<IL> >();
Chris@16 198 gil_function_requires<MutablePixelIteratorConcept<O> >();
Chris@16 199 while (n>0) {
Chris@16 200 typedef typename iterator_from_2d<IL>::difference_type diff_t;
Chris@16 201 diff_t l=src.width()-src.x_pos();
Chris@16 202 diff_t numToCopy=(n<l ? n:l);
Chris@16 203 detail::copy_n(src.x(), numToCopy, dst);
Chris@16 204 dst+=numToCopy;
Chris@16 205 src+=numToCopy;
Chris@16 206 n-=numToCopy;
Chris@16 207 }
Chris@16 208 }
Chris@16 209 };
Chris@16 210
Chris@16 211 /// Destination range is delimited by image iterators
Chris@16 212 template <typename I, typename OL> // I Models ConstPixelIteratorConcept, OL Models PixelLocatorConcept
Chris@16 213 struct copier_n<I,iterator_from_2d<OL> > {
Chris@16 214 typedef typename std::iterator_traits<I>::difference_type diff_t;
Chris@16 215 GIL_FORCEINLINE void operator()(I src, diff_t n, iterator_from_2d<OL> dst) const {
Chris@16 216 gil_function_requires<PixelIteratorConcept<I> >();
Chris@16 217 gil_function_requires<MutablePixelLocatorConcept<OL> >();
Chris@16 218 while (n>0) {
Chris@16 219 diff_t l=dst.width()-dst.x_pos();
Chris@16 220 diff_t numToCopy=(n<l ? n:l);
Chris@16 221 detail::copy_n(src, numToCopy, dst.x());
Chris@16 222 dst+=numToCopy;
Chris@16 223 src+=numToCopy;
Chris@16 224 n-=numToCopy;
Chris@16 225 }
Chris@16 226 }
Chris@16 227 };
Chris@16 228
Chris@16 229 /// Both source and destination ranges are delimited by image iterators
Chris@16 230 template <typename IL, typename OL>
Chris@16 231 struct copier_n<iterator_from_2d<IL>,iterator_from_2d<OL> > {
Chris@16 232 typedef typename iterator_from_2d<IL>::difference_type diff_t;
Chris@16 233 GIL_FORCEINLINE void operator()(iterator_from_2d<IL> src, diff_t n, iterator_from_2d<OL> dst) const {
Chris@16 234 gil_function_requires<PixelLocatorConcept<IL> >();
Chris@16 235 gil_function_requires<MutablePixelLocatorConcept<OL> >();
Chris@16 236 if (src.x_pos()!=dst.x_pos() || src.width()!=dst.width()) {
Chris@16 237 while(n-->0) {
Chris@16 238 *dst++=*src++;
Chris@16 239 }
Chris@16 240 }
Chris@16 241 while (n>0) {
Chris@16 242 diff_t l=dst.width()-dst.x_pos();
Chris@16 243 diff_t numToCopy=(n<l ? n : l);
Chris@16 244 detail::copy_n(src.x(), numToCopy, dst.x());
Chris@16 245 dst+=numToCopy;
Chris@16 246 src+=numToCopy;
Chris@16 247 n-=numToCopy;
Chris@16 248 }
Chris@16 249 }
Chris@16 250 };
Chris@16 251
Chris@16 252 template <typename SrcIterator, typename DstIterator>
Chris@16 253 GIL_FORCEINLINE DstIterator copy_with_2d_iterators(SrcIterator first, SrcIterator last, DstIterator dst) {
Chris@16 254 typedef typename SrcIterator::x_iterator src_x_iterator;
Chris@16 255 typedef typename DstIterator::x_iterator dst_x_iterator;
Chris@16 256
Chris@16 257 typename SrcIterator::difference_type n = last - first;
Chris@16 258
Chris@16 259 if (first.is_1d_traversable()) {
Chris@16 260 if (dst.is_1d_traversable())
Chris@16 261 copier_n<src_x_iterator,dst_x_iterator>()(first.x(),n, dst.x());
Chris@16 262 else
Chris@16 263 copier_n<src_x_iterator,DstIterator >()(first.x(),n, dst);
Chris@16 264 } else {
Chris@16 265 if (dst.is_1d_traversable())
Chris@16 266 copier_n<SrcIterator,dst_x_iterator>()(first,n, dst.x());
Chris@16 267 else
Chris@16 268 copier_n<SrcIterator,DstIterator>()(first,n,dst);
Chris@16 269 }
Chris@16 270 return dst+n;
Chris@16 271 }
Chris@16 272
Chris@16 273 } // namespace detail
Chris@16 274 } } // namespace boost::gil
Chris@16 275
Chris@16 276 namespace std {
Chris@16 277 /// \ingroup STLOptimizations
Chris@16 278 /// \brief std::copy(I1,I1,I2) with I1 and I2 being a iterator_from_2d
Chris@16 279 template <typename IL, typename OL>
Chris@16 280 GIL_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) {
Chris@16 281 return boost::gil::detail::copy_with_2d_iterators(first,last,dst);
Chris@16 282 }
Chris@16 283
Chris@16 284 } // namespace std
Chris@16 285
Chris@16 286 namespace boost { namespace gil {
Chris@16 287
Chris@16 288
Chris@16 289 /// \ingroup ImageViewSTLAlgorithmsCopyPixels
Chris@16 290 /// \brief std::copy for image views
Chris@16 291 template <typename View1, typename View2> GIL_FORCEINLINE
Chris@16 292 void copy_pixels(const View1& src, const View2& dst) {
Chris@16 293 assert(src.dimensions()==dst.dimensions());
Chris@16 294 detail::copy_with_2d_iterators(src.begin(),src.end(),dst.begin());
Chris@16 295 }
Chris@16 296
Chris@16 297 //////////////////////////////////////////////////////////////////////////////////////
Chris@16 298 ///
Chris@16 299 /// copy_and_convert_pixels
Chris@16 300 ///
Chris@16 301 //////////////////////////////////////////////////////////////////////////////////////
Chris@16 302
Chris@16 303 /// \defgroup ImageViewSTLAlgorithmsCopyAndConvertPixels copy_and_convert_pixels
Chris@16 304 /// \ingroup ImageViewSTLAlgorithms
Chris@16 305 /// \brief copies src view into dst view, color converting if necessary.
Chris@16 306 ///
Chris@16 307 /// Versions taking static and runtime views are provided. Versions taking user-defined color convered are provided.
Chris@16 308
Chris@16 309 namespace detail {
Chris@16 310 template <typename CC>
Chris@16 311 class copy_and_convert_pixels_fn : public binary_operation_obj<copy_and_convert_pixels_fn<CC> > {
Chris@16 312 private:
Chris@16 313 CC _cc;
Chris@16 314 public:
Chris@16 315 typedef typename binary_operation_obj<copy_and_convert_pixels_fn<CC> >::result_type result_type;
Chris@16 316 copy_and_convert_pixels_fn() {}
Chris@16 317 copy_and_convert_pixels_fn(CC cc_in) : _cc(cc_in) {}
Chris@16 318 // when the two color spaces are incompatible, a color conversion is performed
Chris@16 319 template <typename V1, typename V2> GIL_FORCEINLINE
Chris@16 320 result_type apply_incompatible(const V1& src, const V2& dst) const {
Chris@16 321 copy_pixels(color_converted_view<typename V2::value_type>(src,_cc),dst);
Chris@16 322 }
Chris@16 323
Chris@16 324 // If the two color spaces are compatible, copy_and_convert is just copy
Chris@16 325 template <typename V1, typename V2> GIL_FORCEINLINE
Chris@16 326 result_type apply_compatible(const V1& src, const V2& dst) const {
Chris@16 327 copy_pixels(src,dst);
Chris@16 328 }
Chris@16 329 };
Chris@16 330 } // namespace detail
Chris@16 331
Chris@16 332 /// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels
Chris@16 333 template <typename V1, typename V2,typename CC>
Chris@16 334 GIL_FORCEINLINE
Chris@16 335 void copy_and_convert_pixels(const V1& src, const V2& dst,CC cc) {
Chris@16 336 detail::copy_and_convert_pixels_fn<CC> ccp(cc);
Chris@16 337 ccp(src,dst);
Chris@16 338 }
Chris@16 339
Chris@16 340 struct default_color_converter;
Chris@16 341
Chris@16 342 /// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels
Chris@16 343 template <typename View1, typename View2>
Chris@16 344 GIL_FORCEINLINE
Chris@16 345 void copy_and_convert_pixels(const View1& src, const View2& dst) {
Chris@16 346 detail::copy_and_convert_pixels_fn<default_color_converter> ccp;
Chris@16 347 ccp(src,dst);
Chris@16 348 }
Chris@16 349
Chris@16 350 } } // namespace boost::gil
Chris@16 351
Chris@16 352 //////////////////////////////////////////////////////////////////////////////////////
Chris@16 353 //
Chris@16 354 // std::fill and gil::fill_pixels
Chris@16 355 //
Chris@16 356 //////////////////////////////////////////////////////////////////////////////////////
Chris@16 357
Chris@16 358 /// \defgroup ImageViewSTLAlgorithmsFillPixels fill_pixels
Chris@16 359 /// \ingroup ImageViewSTLAlgorithms
Chris@16 360 /// \brief std::fill for image views
Chris@16 361
Chris@16 362
Chris@16 363 namespace std {
Chris@16 364 /// \ingroup STLOptimizations
Chris@16 365 /// \brief std::fill(I,I,V) with I being a iterator_from_2d
Chris@16 366 ///
Chris@16 367 /// Invoked when one calls std::fill(I,I,V) with I being a iterator_from_2d (which is
Chris@16 368 /// a 1D iterator over the pixels in an image). For contiguous images (i.e. images that have
Chris@16 369 /// no alignment gap at the end of each row) it is more efficient to use the underlying
Chris@16 370 /// pixel iterator that does not check for the end of rows. For non-contiguous images fill
Chris@16 371 /// resolves to fill of each row using the underlying pixel iterator, which is still faster
Chris@16 372 template <typename IL, typename V>
Chris@16 373 void fill(boost::gil::iterator_from_2d<IL> first, boost::gil::iterator_from_2d<IL> last, const V& val) {
Chris@16 374 boost::gil::gil_function_requires<boost::gil::MutablePixelLocatorConcept<IL> >();
Chris@16 375 if (first.is_1d_traversable()) {
Chris@16 376 std::fill(first.x(), last.x(), val);
Chris@16 377 } else {
Chris@16 378 // fill row by row
Chris@16 379 std::ptrdiff_t n=last-first;
Chris@16 380 while (n>0) {
Chris@16 381 std::ptrdiff_t numToDo=std::min<const std::ptrdiff_t>(n,(std::ptrdiff_t)(first.width()-first.x_pos()));
Chris@16 382 fill_n(first.x(), numToDo, val);
Chris@16 383 first+=numToDo;
Chris@16 384 n-=numToDo;
Chris@16 385 }
Chris@16 386 }
Chris@16 387 }
Chris@16 388 } // namespace std
Chris@16 389
Chris@16 390 namespace boost { namespace gil {
Chris@16 391
Chris@16 392 namespace detail {
Chris@16 393 /// struct to do std::fill
Chris@16 394 struct std_fill_t {
Chris@16 395 template <typename It, typename P>
Chris@16 396 void operator()(It first, It last, const P& p_in) {
Chris@16 397 std::fill(first,last,p_in);
Chris@16 398 }
Chris@16 399 };
Chris@16 400 /// std::fill for planar iterators
Chris@16 401 template <typename It, typename P>
Chris@16 402 GIL_FORCEINLINE
Chris@16 403 void fill_aux(It first, It last, const P& p, mpl::true_) {
Chris@16 404 static_for_each(first,last,p,std_fill_t());
Chris@16 405 }
Chris@16 406 /// std::fill for interleaved iterators
Chris@16 407 template <typename It, typename P>
Chris@16 408 GIL_FORCEINLINE
Chris@16 409 void fill_aux(It first, It last, const P& p,mpl::false_) {
Chris@16 410 std::fill(first,last,p);
Chris@16 411 }
Chris@16 412 } // namespace detail
Chris@16 413
Chris@16 414 /// \ingroup ImageViewSTLAlgorithmsFillPixels
Chris@16 415 /// \brief std::fill for image views
Chris@16 416 template <typename View, typename Value> GIL_FORCEINLINE
Chris@16 417 void fill_pixels(const View& img_view, const Value& val) {
Chris@16 418 if (img_view.is_1d_traversable())
Chris@16 419 detail::fill_aux(img_view.begin().x(), img_view.end().x(),
Chris@16 420 val,is_planar<View>());
Chris@16 421 else
Chris@16 422 for (std::ptrdiff_t y=0; y<img_view.height(); ++y)
Chris@16 423 detail::fill_aux(img_view.row_begin(y),img_view.row_end(y),
Chris@16 424 val,is_planar<View>());
Chris@16 425 }
Chris@16 426
Chris@16 427 //////////////////////////////////////////////////////////////////////////////////////
Chris@16 428 ///
Chris@16 429 /// destruct_pixels
Chris@16 430 ///
Chris@16 431 //////////////////////////////////////////////////////////////////////////////////////
Chris@16 432
Chris@16 433 /// \defgroup ImageViewSTLAlgorithmsDestructPixels destruct_pixels
Chris@16 434 /// \ingroup ImageViewSTLAlgorithms
Chris@16 435 /// \brief invokes the destructor on every pixel of an image view
Chris@16 436
Chris@16 437
Chris@16 438 namespace detail {
Chris@16 439
Chris@16 440 template <typename It> GIL_FORCEINLINE
Chris@16 441 void destruct_range_impl(It first, It last, mpl::true_) {
Chris@16 442 typedef typename std::iterator_traits<It>::value_type value_t;
Chris@16 443 if (boost::has_trivial_destructor<value_t>::value)
Chris@16 444 return;
Chris@16 445 while (first!=last) {
Chris@16 446 first->~value_t();
Chris@16 447 ++first;
Chris@16 448 }
Chris@16 449 }
Chris@16 450 template <typename It> GIL_FORCEINLINE
Chris@16 451 void destruct_range_impl(It, It, mpl::false_) {}
Chris@16 452
Chris@16 453 template <typename It> GIL_FORCEINLINE
Chris@16 454 void destruct_range(It first, It last) {
Chris@16 455 destruct_range_impl(first,last,typename is_pointer<It>::type());
Chris@16 456 }
Chris@16 457
Chris@16 458 struct std_destruct_t {
Chris@16 459 template <typename It> void operator()(It first, It last) const { destruct_range(first,last); }
Chris@16 460 };
Chris@16 461
Chris@16 462 /// destruct for planar iterators
Chris@16 463 template <typename It>
Chris@16 464 GIL_FORCEINLINE
Chris@16 465 void destruct_aux(It first, It last, mpl::true_) {
Chris@16 466 static_for_each(first,last,std_destruct_t());
Chris@16 467 }
Chris@16 468 /// destruct for interleaved iterators
Chris@16 469 template <typename It>
Chris@16 470 GIL_FORCEINLINE
Chris@16 471 void destruct_aux(It first, It last, mpl::false_) {
Chris@16 472 destruct_range(first,last);
Chris@16 473 }
Chris@16 474
Chris@16 475 } // namespace detail
Chris@16 476
Chris@16 477 /// \ingroup ImageViewSTLAlgorithmsDestructPixels
Chris@16 478 /// \brief Invokes the in-place destructor on every pixel of the view
Chris@16 479 template <typename View> GIL_FORCEINLINE
Chris@16 480 void destruct_pixels(const View& img_view) {
Chris@16 481 if (img_view.is_1d_traversable())
Chris@16 482 detail::destruct_aux(img_view.begin().x(), img_view.end().x(),
Chris@16 483 is_planar<View>());
Chris@16 484 else
Chris@16 485 for (std::ptrdiff_t y=0; y<img_view.height(); ++y)
Chris@16 486 detail::destruct_aux(img_view.row_begin(y),img_view.row_end(y),
Chris@16 487 is_planar<View>());
Chris@16 488 }
Chris@16 489
Chris@16 490 //////////////////////////////////////////////////////////////////////////////////////
Chris@16 491 ///
Chris@16 492 /// uninitialized_fill_pixels
Chris@16 493 ///
Chris@16 494 //////////////////////////////////////////////////////////////////////////////////////
Chris@16 495
Chris@16 496 /// \defgroup ImageViewSTLAlgorithmsUninitializedFillPixels uninitialized_fill_pixels
Chris@16 497 /// \ingroup ImageViewSTLAlgorithms
Chris@16 498 /// \brief std::uninitialized_fill for image views
Chris@16 499
Chris@16 500
Chris@16 501 namespace detail {
Chris@16 502
Chris@16 503 /// std::uninitialized_fill for planar iterators
Chris@16 504 /// If an exception is thrown destructs any in-place copy-constructed objects
Chris@16 505 template <typename It, typename P>
Chris@16 506 GIL_FORCEINLINE
Chris@16 507 void uninitialized_fill_aux(It first, It last,
Chris@16 508 const P& p, mpl::true_) {
Chris@16 509 int channel=0;
Chris@16 510 try {
Chris@16 511 typedef typename std::iterator_traits<It>::value_type pixel_t;
Chris@16 512 while (channel < num_channels<pixel_t>::value) {
Chris@16 513 std::uninitialized_fill(dynamic_at_c(first,channel), dynamic_at_c(last,channel),
Chris@16 514 dynamic_at_c(p,channel));
Chris@16 515 ++channel;
Chris@16 516 }
Chris@16 517 } catch (...) {
Chris@16 518 for (int c=0; c<channel; ++c)
Chris@16 519 destruct_range(dynamic_at_c(first,c), dynamic_at_c(last,c));
Chris@16 520 throw;
Chris@16 521 }
Chris@16 522 }
Chris@16 523
Chris@16 524 /// std::uninitialized_fill for interleaved iterators
Chris@16 525 /// If an exception is thrown destructs any in-place copy-constructed objects
Chris@16 526 template <typename It, typename P>
Chris@16 527 GIL_FORCEINLINE
Chris@16 528 void uninitialized_fill_aux(It first, It last,
Chris@16 529 const P& p,mpl::false_) {
Chris@16 530 std::uninitialized_fill(first,last,p);
Chris@16 531 }
Chris@16 532
Chris@16 533 } // namespace detail
Chris@16 534
Chris@16 535 /// \ingroup ImageViewSTLAlgorithmsUninitializedFillPixels
Chris@16 536 /// \brief std::uninitialized_fill for image views.
Chris@16 537 /// Does not support planar heterogeneous views.
Chris@16 538 /// If an exception is thrown destructs any in-place copy-constructed pixels
Chris@16 539 template <typename View, typename Value>
Chris@16 540 void uninitialized_fill_pixels(const View& img_view, const Value& val) {
Chris@16 541 if (img_view.is_1d_traversable())
Chris@16 542 detail::uninitialized_fill_aux(img_view.begin().x(), img_view.end().x(),
Chris@16 543 val,is_planar<View>());
Chris@16 544 else {
Chris@16 545 typename View::y_coord_t y;
Chris@16 546 try {
Chris@16 547 for (y=0; y<img_view.height(); ++y)
Chris@16 548 detail::uninitialized_fill_aux(img_view.row_begin(y),img_view.row_end(y),
Chris@16 549 val,is_planar<View>());
Chris@16 550 } catch(...) {
Chris@16 551 for (typename View::y_coord_t y0=0; y0<y; ++y0)
Chris@16 552 detail::destruct_aux(img_view.row_begin(y0),img_view.row_end(y0), is_planar<View>());
Chris@16 553 throw;
Chris@16 554 }
Chris@16 555 }
Chris@16 556 }
Chris@16 557
Chris@16 558 //////////////////////////////////////////////////////////////////////////////////////
Chris@16 559 ///
Chris@16 560 /// default_construct_pixels
Chris@16 561 ///
Chris@16 562 //////////////////////////////////////////////////////////////////////////////////////
Chris@16 563
Chris@16 564 /// \defgroup ImageViewSTLAlgorithmsDefaultConstructPixels default_construct_pixels
Chris@16 565 /// \ingroup ImageViewSTLAlgorithms
Chris@16 566 /// \brief invokes the default constructor on every pixel of an image view
Chris@16 567
Chris@16 568 namespace detail {
Chris@16 569
Chris@16 570 template <typename It> GIL_FORCEINLINE
Chris@16 571 void default_construct_range_impl(It first, It last, mpl::true_) {
Chris@16 572 typedef typename std::iterator_traits<It>::value_type value_t;
Chris@16 573 It first1=first;
Chris@16 574 try {
Chris@16 575 while (first!=last) {
Chris@16 576 new (first) value_t();
Chris@16 577 ++first;
Chris@16 578 }
Chris@16 579 } catch (...) {
Chris@16 580 destruct_range(first1,first);
Chris@16 581 throw;
Chris@16 582 }
Chris@16 583 }
Chris@16 584
Chris@16 585 template <typename It> GIL_FORCEINLINE
Chris@16 586 void default_construct_range_impl(It, It, mpl::false_) {}
Chris@16 587
Chris@16 588 template <typename It> GIL_FORCEINLINE
Chris@16 589 void default_construct_range(It first, It last) { default_construct_range_impl(first, last, typename is_pointer<It>::type()); }
Chris@16 590
Chris@16 591 /// uninitialized_default_construct for planar iterators
Chris@16 592 template <typename It>
Chris@16 593 GIL_FORCEINLINE
Chris@16 594 void default_construct_aux(It first, It last, mpl::true_) {
Chris@16 595 int channel=0;
Chris@16 596 try {
Chris@16 597 typedef typename std::iterator_traits<It>::value_type pixel_t;
Chris@16 598 while (channel < num_channels<pixel_t>::value) {
Chris@16 599 default_construct_range(dynamic_at_c(first,channel), dynamic_at_c(last,channel));
Chris@16 600 ++channel;
Chris@16 601 }
Chris@16 602 } catch (...) {
Chris@16 603 for (int c=0; c<channel; ++c)
Chris@16 604 destruct_range(dynamic_at_c(first,c), dynamic_at_c(last,c));
Chris@16 605 throw;
Chris@16 606 }
Chris@16 607 }
Chris@16 608
Chris@16 609 /// uninitialized_default_construct for interleaved iterators
Chris@16 610 template <typename It>
Chris@16 611 GIL_FORCEINLINE
Chris@16 612 void default_construct_aux(It first, It last, mpl::false_) {
Chris@16 613 default_construct_range(first,last);
Chris@16 614 }
Chris@16 615
Chris@16 616 template <typename View, bool IsPlanar>
Chris@16 617 struct has_trivial_pixel_constructor : public boost::has_trivial_constructor<typename View::value_type> {};
Chris@16 618 template <typename View>
Chris@16 619 struct has_trivial_pixel_constructor<View, true> : public boost::has_trivial_constructor<typename channel_type<View>::type> {};
Chris@16 620
Chris@16 621 } // namespace detail
Chris@16 622
Chris@16 623 /// \ingroup ImageViewSTLAlgorithmsDefaultConstructPixels
Chris@16 624 /// \brief Invokes the in-place default constructor on every pixel of the (uninitialized) view.
Chris@16 625 /// Does not support planar heterogeneous views.
Chris@16 626 /// If an exception is thrown destructs any in-place default-constructed pixels
Chris@16 627 template <typename View>
Chris@16 628 void default_construct_pixels(const View& img_view) {
Chris@16 629 if (detail::has_trivial_pixel_constructor<View, is_planar<View>::value>::value)
Chris@16 630 return;
Chris@16 631
Chris@16 632 if (img_view.is_1d_traversable())
Chris@16 633 detail::default_construct_aux(img_view.begin().x(), img_view.end().x(), is_planar<View>());
Chris@16 634 else {
Chris@16 635 typename View::y_coord_t y;
Chris@16 636 try {
Chris@16 637 for (y=0; y<img_view.height(); ++y)
Chris@16 638 detail::default_construct_aux(img_view.row_begin(y),img_view.row_end(y), is_planar<View>());
Chris@16 639 } catch(...) {
Chris@16 640 for (typename View::y_coord_t y0=0; y0<y; ++y0)
Chris@16 641 detail::destruct_aux(img_view.row_begin(y0),img_view.row_end(y0), is_planar<View>());
Chris@16 642 throw;
Chris@16 643 }
Chris@16 644 }
Chris@16 645 }
Chris@16 646
Chris@16 647
Chris@16 648 //////////////////////////////////////////////////////////////////////////////////////
Chris@16 649 ///
Chris@16 650 /// uninitialized_copy_pixels
Chris@16 651 ///
Chris@16 652 //////////////////////////////////////////////////////////////////////////////////////
Chris@16 653
Chris@16 654 /// \defgroup ImageViewSTLAlgorithmsUninitializedCopyPixels uninitialized_copy_pixels
Chris@16 655 /// \ingroup ImageViewSTLAlgorithms
Chris@16 656 /// \brief std::uninitialized_copy for image views
Chris@16 657
Chris@16 658 namespace detail {
Chris@16 659
Chris@16 660 /// std::uninitialized_copy for pairs of planar iterators
Chris@16 661 template <typename It1, typename It2>
Chris@16 662 GIL_FORCEINLINE
Chris@16 663 void uninitialized_copy_aux(It1 first1, It1 last1,
Chris@16 664 It2 first2, mpl::true_) {
Chris@16 665 int channel=0;
Chris@16 666 try {
Chris@16 667 typedef typename std::iterator_traits<It1>::value_type pixel_t;
Chris@16 668 while (channel < num_channels<pixel_t>::value) {
Chris@16 669 std::uninitialized_copy(dynamic_at_c(first1,channel), dynamic_at_c(last1,channel), dynamic_at_c(first2,channel));
Chris@16 670 ++channel;
Chris@16 671 }
Chris@16 672 } catch (...) {
Chris@16 673 It2 last2=first2;
Chris@16 674 std::advance(last2, std::distance(first1,last1));
Chris@16 675 for (int c=0; c<channel; ++c)
Chris@16 676 destruct_range(dynamic_at_c(first2,c), dynamic_at_c(last2,c));
Chris@16 677 throw;
Chris@16 678 }
Chris@16 679 }
Chris@16 680 /// std::uninitialized_copy for interleaved or mixed iterators
Chris@16 681 template <typename It1, typename It2>
Chris@16 682 GIL_FORCEINLINE
Chris@16 683 void uninitialized_copy_aux(It1 first1, It1 last1,
Chris@16 684 It2 first2,mpl::false_) {
Chris@16 685 std::uninitialized_copy(first1,last1,first2);
Chris@16 686 }
Chris@16 687 } // namespace detail
Chris@16 688
Chris@16 689 /// \ingroup ImageViewSTLAlgorithmsUninitializedCopyPixels
Chris@16 690 /// \brief std::uninitialized_copy for image views.
Chris@16 691 /// Does not support planar heterogeneous views.
Chris@16 692 /// If an exception is thrown destructs any in-place copy-constructed objects
Chris@16 693 template <typename View1, typename View2>
Chris@16 694 void uninitialized_copy_pixels(const View1& view1, const View2& view2) {
Chris@16 695 typedef mpl::bool_<is_planar<View1>::value && is_planar<View2>::value> is_planar;
Chris@16 696 assert(view1.dimensions()==view2.dimensions());
Chris@16 697 if (view1.is_1d_traversable() && view2.is_1d_traversable())
Chris@16 698 detail::uninitialized_copy_aux(view1.begin().x(), view1.end().x(),
Chris@16 699 view2.begin().x(),
Chris@16 700 is_planar());
Chris@16 701 else {
Chris@16 702 typename View1::y_coord_t y;
Chris@16 703 try {
Chris@16 704 for (y=0; y<view1.height(); ++y)
Chris@16 705 detail::uninitialized_copy_aux(view1.row_begin(y), view1.row_end(y),
Chris@16 706 view2.row_begin(y),
Chris@16 707 is_planar());
Chris@16 708 } catch(...) {
Chris@16 709 for (typename View1::y_coord_t y0=0; y0<y; ++y0)
Chris@16 710 detail::destruct_aux(view2.row_begin(y0),view2.row_end(y0), is_planar());
Chris@16 711 throw;
Chris@16 712 }
Chris@16 713 }
Chris@16 714 }
Chris@16 715
Chris@16 716 //////////////////////////////////////////////////////////////////////////////////////
Chris@16 717 ///
Chris@16 718 /// for_each_pixel
Chris@16 719 ///
Chris@16 720 //////////////////////////////////////////////////////////////////////////////////////
Chris@16 721
Chris@16 722 /// \defgroup ImageViewSTLAlgorithmsForEachPixel for_each_pixel
Chris@16 723 /// \ingroup ImageViewSTLAlgorithms
Chris@16 724 /// \brief std::for_each for image views
Chris@16 725 ///
Chris@16 726 /// For contiguous images (i.e. images that have no alignment gap at the end of each row) it is
Chris@16 727 /// more efficient to use the underlying pixel iterator that does not check for the end of rows.
Chris@16 728 /// For non-contiguous images for_each_pixel resolves to for_each of each row using the underlying
Chris@16 729 /// pixel iterator, which is still faster
Chris@16 730
Chris@16 731 /// \ingroup ImageViewSTLAlgorithmsForEachPixel
Chris@16 732 template <typename V, typename F>
Chris@16 733 F for_each_pixel(const V& img, F fun) {
Chris@16 734 if (img.is_1d_traversable()) {
Chris@16 735 return std::for_each(img.begin().x(), img.end().x(), fun);
Chris@16 736 } else {
Chris@16 737 for (std::ptrdiff_t y=0; y<img.height(); ++y)
Chris@16 738 fun = std::for_each(img.row_begin(y),img.row_end(y),fun);
Chris@16 739 return fun;
Chris@16 740 }
Chris@16 741 }
Chris@16 742
Chris@16 743 /// \defgroup ImageViewSTLAlgorithmsForEachPixelPosition for_each_pixel_position
Chris@16 744 /// \ingroup ImageViewSTLAlgorithms
Chris@16 745 /// \brief adobe::for_each_position for image views (passes locators, instead of pixel references, to the function object)
Chris@16 746
Chris@16 747 /// \ingroup ImageViewSTLAlgorithmsForEachPixelPosition
Chris@16 748 template <typename View, typename F>
Chris@16 749 F for_each_pixel_position(const View& img, F fun) {
Chris@16 750 typename View::xy_locator loc=img.xy_at(0,0);
Chris@16 751 for (std::ptrdiff_t y=0; y<img.height(); ++y) {
Chris@16 752 for (std::ptrdiff_t x=0; x<img.width(); ++x, ++loc.x())
Chris@16 753 fun(loc);
Chris@16 754 loc.x()-=img.width(); ++loc.y();
Chris@16 755 }
Chris@16 756 return fun;
Chris@16 757 }
Chris@16 758
Chris@16 759
Chris@16 760 //////////////////////////////////////////////////////////////////////////////////////
Chris@16 761 ///
Chris@16 762 /// generate_pixels
Chris@16 763 ///
Chris@16 764 //////////////////////////////////////////////////////////////////////////////////////
Chris@16 765
Chris@16 766 /// \defgroup ImageViewSTLAlgorithmsGeneratePixels generate_pixels
Chris@16 767 /// \ingroup ImageViewSTLAlgorithms
Chris@16 768 /// \brief std::generate for image views
Chris@16 769
Chris@16 770 /// \ingroup ImageViewSTLAlgorithmsGeneratePixels
Chris@16 771 /// \brief std::generate for image views
Chris@16 772 template <typename View, typename F>
Chris@16 773 void generate_pixels(const View& v, F fun) {
Chris@16 774 if (v.is_1d_traversable()) {
Chris@16 775 std::generate(v.begin().x(), v.end().x(), fun);
Chris@16 776 } else {
Chris@16 777 for (std::ptrdiff_t y=0; y<v.height(); ++y)
Chris@16 778 std::generate(v.row_begin(y),v.row_end(y),fun);
Chris@16 779 }
Chris@16 780 }
Chris@16 781
Chris@16 782 //////////////////////////////////////////////////////////////////////////////////////
Chris@16 783 ///
Chris@16 784 /// std::equal and gil::equal_pixels for GIL constructs
Chris@16 785 ///
Chris@16 786 //////////////////////////////////////////////////////////////////////////////////////
Chris@16 787
Chris@16 788 /// \defgroup ImageViewSTLAlgorithmsEqualPixels equal_pixels
Chris@16 789 /// \ingroup ImageViewSTLAlgorithms
Chris@16 790 /// \brief std::equal for image views
Chris@16 791
Chris@16 792 template <typename I1, typename I2> GIL_FORCEINLINE bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2);
Chris@16 793
Chris@16 794 namespace detail {
Chris@16 795
Chris@16 796 template <typename I1, typename I2>
Chris@16 797 struct equal_n_fn {
Chris@16 798 GIL_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, I2 i2) const { return std::equal(i1,i1+n, i2); }
Chris@16 799 };
Chris@16 800
Chris@16 801 /// Equal when both ranges are interleaved and of the same type.
Chris@16 802 /// GIL pixels are bitwise comparable, so memcmp is used. User-defined pixels that are not bitwise comparable need to provide an overload
Chris@16 803 template<typename T, typename Cs>
Chris@16 804 struct equal_n_fn<const pixel<T,Cs>*, const pixel<T,Cs>*> {
Chris@16 805 GIL_FORCEINLINE bool operator()(const pixel<T,Cs>* i1, std::ptrdiff_t n, const pixel<T,Cs>* i2) const {
Chris@16 806 return memcmp(i1, i2, n*sizeof(pixel<T,Cs>))==0;
Chris@16 807 }
Chris@16 808 };
Chris@16 809 template<typename T, typename Cs>
Chris@16 810 struct equal_n_fn<pixel<T,Cs>*, pixel<T,Cs>*> : equal_n_fn<const pixel<T,Cs>*, const pixel<T,Cs>*> {};
Chris@16 811
Chris@16 812 /// EqualPixels
Chris@16 813 /// Equal when both ranges are planar pointers of the same type. memcmp is invoked for each channel plane
Chris@16 814 /// User-defined channels that are not bitwise comparable need to provide an overload
Chris@16 815 template<typename IC, typename Cs>
Chris@16 816 struct equal_n_fn<planar_pixel_iterator<IC,Cs>, planar_pixel_iterator<IC,Cs> > {
Chris@16 817 GIL_FORCEINLINE bool operator()(const planar_pixel_iterator<IC,Cs> i1, std::ptrdiff_t n, const planar_pixel_iterator<IC,Cs> i2) const {
Chris@16 818 ptrdiff_t numBytes=n*sizeof(typename std::iterator_traits<IC>::value_type);
Chris@16 819
Chris@16 820 for (std::ptrdiff_t i=0; i<mpl::size<Cs>::value; ++i)
Chris@16 821 if (memcmp(dynamic_at_c(i1,i), dynamic_at_c(i2,i), numBytes)!=0)
Chris@16 822 return false;
Chris@16 823 return true;
Chris@16 824 }
Chris@16 825 };
Chris@16 826
Chris@16 827
Chris@16 828 /// Source range is delimited by image iterators
Chris@16 829 template <typename Loc, typename I2> // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept
Chris@16 830 struct equal_n_fn<boost::gil::iterator_from_2d<Loc>,I2> {
Chris@16 831 GIL_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc> i1, std::ptrdiff_t n, I2 i2) const {
Chris@16 832 gil_function_requires<boost::gil::PixelLocatorConcept<Loc> >();
Chris@16 833 gil_function_requires<boost::gil::PixelIteratorConcept<I2> >();
Chris@16 834 while (n>0) {
Chris@16 835 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n, i1.width()-i1.x_pos());
Chris@16 836 if (!equal_n(i1.x(), num, i2))
Chris@16 837 return false;
Chris@16 838 i1+=num;
Chris@16 839 i2+=num;
Chris@16 840 n-=num;
Chris@16 841 }
Chris@16 842 return true;
Chris@16 843 }
Chris@16 844 };
Chris@16 845
Chris@16 846 /// Destination range is delimited by image iterators
Chris@16 847 template <typename I1, typename Loc> // I Models PixelIteratorConcept, OL Models PixelLocatorConcept
Chris@16 848 struct equal_n_fn<I1,boost::gil::iterator_from_2d<Loc> > {
Chris@16 849 GIL_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc> i2) const {
Chris@16 850 gil_function_requires<boost::gil::PixelIteratorConcept<I1> >();
Chris@16 851 gil_function_requires<boost::gil::PixelLocatorConcept<Loc> >();
Chris@16 852 while (n>0) {
Chris@16 853 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
Chris@16 854 if (!equal_n(i1, num, i2.x()))
Chris@16 855 return false;
Chris@16 856 i1+=num;
Chris@16 857 i2+=num;
Chris@16 858 n-=num;
Chris@16 859 }
Chris@16 860 return true;
Chris@16 861 }
Chris@16 862 };
Chris@16 863
Chris@16 864 /// Both source and destination ranges are delimited by image iterators
Chris@16 865 template <typename Loc1, typename Loc2>
Chris@16 866 struct equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2> > {
Chris@16 867 GIL_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc1> i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc2> i2) const {
Chris@16 868 gil_function_requires<boost::gil::PixelLocatorConcept<Loc1> >();
Chris@16 869 gil_function_requires<boost::gil::PixelLocatorConcept<Loc2> >();
Chris@16 870 if (i1.x_pos()!=i2.x_pos() || i1.width()!=i2.width()) {
Chris@16 871 while(n-->0) {
Chris@16 872 if (*i1++!=*i2++) return false;
Chris@16 873 }
Chris@16 874 }
Chris@16 875 while (n>0) {
Chris@16 876 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
Chris@16 877 if (!equal_n(i1.x(), num, i2.x()))
Chris@16 878 return false;
Chris@16 879 i1+=num;
Chris@16 880 i2+=num;
Chris@16 881 n-=num;
Chris@16 882 }
Chris@16 883 return true;
Chris@16 884 }
Chris@16 885 };
Chris@16 886 } // namespace detail
Chris@16 887
Chris@16 888 template <typename I1, typename I2> GIL_FORCEINLINE
Chris@16 889 bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2) {
Chris@16 890 return detail::equal_n_fn<I1,I2>()(i1,n,i2);
Chris@16 891 }
Chris@16 892 } } // namespace boost::gil
Chris@16 893
Chris@16 894 namespace std {
Chris@16 895 /// \ingroup STLOptimizations
Chris@16 896 /// \brief std::equal(I1,I1,I2) with I1 and I2 being a iterator_from_2d
Chris@16 897 ///
Chris@16 898 /// Invoked when one calls std::equal(I1,I1,I2) with I1 and I2 being a iterator_from_2d (which is
Chris@16 899 /// a 1D iterator over the pixels in an image). Attempts to demote the source and destination
Chris@16 900 /// iterators to simpler/faster types if the corresponding range is contiguous.
Chris@16 901 /// For contiguous images (i.e. images that have
Chris@16 902 /// no alignment gap at the end of each row) it is more efficient to use the underlying
Chris@16 903 /// pixel iterator that does not check for the end of rows. If the underlying pixel iterator
Chris@16 904 /// happens to be a fundamental planar/interleaved pointer, the call may further resolve
Chris@16 905 /// to memcmp. Otherwise it resolves to copying each row using the underlying pixel iterator
Chris@16 906 template <typename Loc1, typename Loc2> GIL_FORCEINLINE
Chris@16 907 bool equal(boost::gil::iterator_from_2d<Loc1> first, boost::gil::iterator_from_2d<Loc1> last, boost::gil::iterator_from_2d<Loc2> first2) {
Chris@16 908 boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc1> >();
Chris@16 909 boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc2> >();
Chris@16 910 std::ptrdiff_t n=last-first;
Chris@16 911 if (first.is_1d_traversable()) {
Chris@16 912 if (first2.is_1d_traversable())
Chris@16 913 return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,typename Loc2::x_iterator>()(first.x(),n, first2.x());
Chris@16 914 else
Chris@16 915 return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,boost::gil::iterator_from_2d<Loc2> >()(first.x(),n, first2);
Chris@16 916 } else {
Chris@16 917 if (first2.is_1d_traversable())
Chris@16 918 return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,typename Loc2::x_iterator>()(first,n, first2.x());
Chris@16 919 else
Chris@16 920 return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2> >()(first,n,first2);
Chris@16 921 }
Chris@16 922 }
Chris@16 923 } // namespace std
Chris@16 924
Chris@16 925 namespace boost { namespace gil {
Chris@16 926
Chris@16 927 /// \ingroup ImageViewSTLAlgorithmsEqualPixels
Chris@16 928 /// \brief std::equal for image views
Chris@16 929 template <typename View1, typename View2> GIL_FORCEINLINE
Chris@16 930 bool equal_pixels(const View1& v1, const View2& v2) {
Chris@16 931 assert(v1.dimensions()==v2.dimensions());
Chris@16 932 return std::equal(v1.begin(),v1.end(),v2.begin()); // std::equal has overloads with GIL iterators for optimal performance
Chris@16 933 }
Chris@16 934
Chris@16 935 //////////////////////////////////////////////////////////////////////////////////////
Chris@16 936 ///
Chris@16 937 /// transform_pixels
Chris@16 938 ///
Chris@16 939 //////////////////////////////////////////////////////////////////////////////////////
Chris@16 940
Chris@16 941 /// \defgroup ImageViewSTLAlgorithmsTransformPixels transform_pixels
Chris@16 942 /// \ingroup ImageViewSTLAlgorithms
Chris@16 943 /// \brief std::transform for image views
Chris@16 944
Chris@16 945 /// \ingroup ImageViewSTLAlgorithmsTransformPixels
Chris@16 946 /// \brief std::transform for image views
Chris@16 947 template <typename View1, typename View2, typename F> GIL_FORCEINLINE
Chris@16 948 F transform_pixels(const View1& src,const View2& dst, F fun) {
Chris@16 949 assert(src.dimensions()==dst.dimensions());
Chris@16 950 for (std::ptrdiff_t y=0; y<src.height(); ++y) {
Chris@16 951 typename View1::x_iterator srcIt=src.row_begin(y);
Chris@16 952 typename View2::x_iterator dstIt=dst.row_begin(y);
Chris@16 953 for (std::ptrdiff_t x=0; x<src.width(); ++x)
Chris@16 954 dstIt[x]=fun(srcIt[x]);
Chris@16 955 }
Chris@16 956 return fun;
Chris@16 957 }
Chris@16 958
Chris@16 959 /// \ingroup ImageViewSTLAlgorithmsTransformPixels
Chris@16 960 /// \brief transform_pixels with two sources
Chris@16 961 template <typename View1, typename View2, typename View3, typename F> GIL_FORCEINLINE
Chris@16 962 F transform_pixels(const View1& src1, const View2& src2,const View3& dst, F fun) {
Chris@16 963 for (std::ptrdiff_t y=0; y<dst.height(); ++y) {
Chris@16 964 typename View1::x_iterator srcIt1=src1.row_begin(y);
Chris@16 965 typename View2::x_iterator srcIt2=src2.row_begin(y);
Chris@16 966 typename View3::x_iterator dstIt=dst.row_begin(y);
Chris@16 967 for (std::ptrdiff_t x=0; x<dst.width(); ++x)
Chris@16 968 dstIt[x]=fun(srcIt1[x],srcIt2[x]);
Chris@16 969 }
Chris@16 970 return fun;
Chris@16 971 }
Chris@16 972
Chris@16 973 /// \defgroup ImageViewSTLAlgorithmsTransformPixelPositions transform_pixel_positions
Chris@16 974 /// \ingroup ImageViewSTLAlgorithms
Chris@16 975 /// \brief adobe::transform_positions for image views (passes locators, instead of pixel references, to the function object)
Chris@16 976
Chris@16 977 /// \ingroup ImageViewSTLAlgorithmsTransformPixelPositions
Chris@16 978 /// \brief Like transform_pixels but passes to the function object pixel locators instead of pixel references
Chris@16 979 template <typename View1, typename View2, typename F> GIL_FORCEINLINE
Chris@16 980 F transform_pixel_positions(const View1& src,const View2& dst, F fun) {
Chris@16 981 assert(src.dimensions()==dst.dimensions());
Chris@16 982 typename View1::xy_locator loc=src.xy_at(0,0);
Chris@16 983 for (std::ptrdiff_t y=0; y<src.height(); ++y) {
Chris@16 984 typename View2::x_iterator dstIt=dst.row_begin(y);
Chris@16 985 for (std::ptrdiff_t x=0; x<src.width(); ++x, ++loc.x())
Chris@16 986 dstIt[x]=fun(loc);
Chris@16 987 loc.x()-=src.width(); ++loc.y();
Chris@16 988 }
Chris@16 989 return fun;
Chris@16 990 }
Chris@16 991
Chris@16 992 /// \ingroup ImageViewSTLAlgorithmsTransformPixelPositions
Chris@16 993 /// \brief transform_pixel_positions with two sources
Chris@16 994 template <typename View1, typename View2, typename View3, typename F> GIL_FORCEINLINE
Chris@16 995 F transform_pixel_positions(const View1& src1,const View2& src2,const View3& dst, F fun) {
Chris@16 996 assert(src1.dimensions()==dst.dimensions());
Chris@16 997 assert(src2.dimensions()==dst.dimensions());
Chris@16 998 typename View1::xy_locator loc1=src1.xy_at(0,0);
Chris@16 999 typename View2::xy_locator loc2=src2.xy_at(0,0);
Chris@16 1000 for (std::ptrdiff_t y=0; y<src1.height(); ++y) {
Chris@16 1001 typename View3::x_iterator dstIt=dst.row_begin(y);
Chris@16 1002 for (std::ptrdiff_t x=0; x<src1.width(); ++x, ++loc1.x(), ++loc2.x())
Chris@16 1003 dstIt[x]=fun(loc1,loc2);
Chris@16 1004 loc1.x()-=src1.width(); ++loc1.y();
Chris@16 1005 loc2.x()-=src2.width(); ++loc2.y();
Chris@16 1006 }
Chris@16 1007 return fun;
Chris@16 1008 }
Chris@16 1009
Chris@16 1010 } } // namespace boost::gil
Chris@16 1011
Chris@16 1012 //#ifdef _MSC_VER
Chris@16 1013 //#pragma warning(pop)
Chris@16 1014 //#endif
Chris@16 1015
Chris@16 1016 #endif