00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef GIL_ALGORITHM_HPP
00010 #define GIL_ALGORITHM_HPP
00011
00012 #include <cassert>
00013 #include <cstddef>
00014 #include <algorithm>
00015 #include "gil_config.hpp"
00016 #include "gil_concept.hpp"
00017 #include "pixel_algorithm.hpp"
00018 #include "image_view.hpp"
00019 #include "image_view_factory.hpp"
00020
00029
00030 ADOBE_GIL_NAMESPACE_BEGIN
00031
00032
00033 struct error_t {};
00034
00035
00044 template <typename Derived, typename Result=void>
00045 struct binary_operation_obj {
00046 typedef Result result_type;
00047
00048 template <typename V1, typename V2> GIL_FORCEINLINE
00049 result_type operator()(const std::pair<const V1*,const V2*>& p) const {
00050 return apply(*p.first, *p.second, typename views_are_compatible<V1,V2>::type());
00051 }
00052
00053 template <typename V1, typename V2> GIL_FORCEINLINE
00054 result_type operator()(const V1& v1, const V2& v2) const {
00055 return apply(v1, v2, typename views_are_compatible<V1,V2>::type());
00056 }
00057
00058 result_type operator()(const error_t&) const { throw std::bad_cast(); }
00059 private:
00060
00061
00062 template <typename V1, typename V2>
00063 GIL_FORCEINLINE result_type apply(const V1& v1, const V2& v2, boost::mpl::false_) const {
00064 return ((const Derived*)this)->apply_incompatible(v1,v2);
00065 }
00066
00067
00068 template <typename V1, typename V2>
00069 GIL_FORCEINLINE result_type apply(const V1& v1, const V2& v2, boost::mpl::true_) const {
00070 return ((const Derived*)this)->apply_compatible(v1,v2);
00071 }
00072
00073
00074 template <typename V1, typename V2>
00075 GIL_FORCEINLINE result_type apply_incompatible(const V1& v1, const V2& v2) const {
00076 throw std::bad_cast();
00077 }
00078 };
00079 ADOBE_GIL_NAMESPACE_END
00080
00086
00090
00091 namespace std {
00095
00098 template<typename T, typename Cs>
00099 GIL_FORCEINLINE GIL::pixel<T,Cs>* copy(GIL::pixel<T,Cs>* first, GIL::pixel<T,Cs>* last, GIL::pixel<T,Cs>* dst) {
00100 return (GIL::pixel<T,Cs>*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst);
00101 }
00102
00105 template<typename T, typename Cs>
00106 GIL_FORCEINLINE GIL::pixel<T,Cs>* copy(const GIL::pixel<T,Cs>* first, const GIL::pixel<T,Cs>* last, GIL::pixel<T,Cs>* dst) {
00107 return (GIL::pixel<T,Cs>*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst);
00108 }
00109 }
00110
00111 ADOBE_GIL_NAMESPACE_BEGIN
00112 namespace detail {
00113 template <typename I, typename O> struct copy_fn {
00114 GIL_FORCEINLINE I operator()(I first, I last, O dst) const { return std::copy(first,last,dst); }
00115 };
00116 }
00117 ADOBE_GIL_NAMESPACE_END
00118
00119 namespace std {
00122 template<typename IC1, typename Cs1, typename IC2, typename Cs2> GIL_FORCEINLINE
00123 GIL::planar_ptr<IC2,Cs2> copy(GIL::planar_ptr<IC1,Cs1> first, GIL::planar_ptr<IC1,Cs1> last, GIL::planar_ptr<IC2,Cs2> dst) {
00124 GIL::gil_function_requires<GIL::ChannelsCompatibleConcept<typename std::iterator_traits<IC1>::value_type,typename std::iterator_traits<IC2>::value_type> >();
00125 GIL::gil_function_requires<GIL::ColorSpacesCompatibleConcept<Cs1,Cs2> >();
00126 for_each_channel(first,last,dst,GIL::detail::copy_fn<IC1,IC2>());
00127 return dst+(last-first);
00128 }
00129 }
00130
00131 ADOBE_GIL_NAMESPACE_BEGIN
00132 namespace detail {
00135 template <typename I, typename O>
00136 struct copier_n {
00137 GIL_FORCEINLINE void operator()(I src, typename std::iterator_traits<I>::difference_type n, O dst) const { std::copy(src,src+n, dst); }
00138 };
00139
00142 template <typename IL, typename O>
00143 struct copier_n<GIL::pixel_image_iterator<IL>,O> {
00144 typedef typename std::iterator_traits<GIL::pixel_image_iterator<IL> >::difference_type diff_t;
00145 GIL_FORCEINLINE void operator()(GIL::pixel_image_iterator<IL> src, diff_t n, O dst) const {
00146 GIL::gil_function_requires<GIL::PixelLocatorConcept<IL> >();
00147 GIL::gil_function_requires<GIL::MutablePixelIteratorConcept<O> >();
00148 while (n>0) {
00149 typedef typename GIL::pixel_image_iterator<IL>::difference_type diff_t;
00150 diff_t l=src.width()-src.x_pos();
00151 diff_t numToCopy=(n<l ? n:l);
00152 adobe::copy_n(src.x(), numToCopy, dst);
00153 dst+=numToCopy;
00154 src+=numToCopy;
00155 n-=numToCopy;
00156 }
00157 }
00158 };
00159
00162 template <typename I, typename OL>
00163 struct copier_n<I,GIL::pixel_image_iterator<OL> > {
00164 typedef typename std::iterator_traits<I>::difference_type diff_t;
00165 GIL_FORCEINLINE void operator()(I src, diff_t n, GIL::pixel_image_iterator<OL> dst) const {
00166 GIL::gil_function_requires<GIL::PixelIteratorConcept<I> >();
00167 GIL::gil_function_requires<GIL::MutablePixelLocatorConcept<OL> >();
00168 while (n>0) {
00169 diff_t l=dst.width()-dst.x_pos();
00170 diff_t numToCopy=(n<l ? n:l);
00171 adobe::copy_n(src, numToCopy, dst.x());
00172 dst+=numToCopy;
00173 src+=numToCopy;
00174 n-=numToCopy;
00175 }
00176 }
00177 };
00178
00181 template <typename IL, typename OL>
00182 struct copier_n<GIL::pixel_image_iterator<IL>,GIL::pixel_image_iterator<OL> > {
00183 typedef typename GIL::pixel_image_iterator<IL>::difference_type diff_t;
00184 GIL_FORCEINLINE void operator()(GIL::pixel_image_iterator<IL> src, diff_t n, GIL::pixel_image_iterator<OL> dst) const {
00185 GIL::gil_function_requires<GIL::PixelLocatorConcept<IL> >();
00186 GIL::gil_function_requires<GIL::MutablePixelLocatorConcept<OL> >();
00187 if (src.x_pos()!=dst.x_pos() || src.width()!=dst.width()) {
00188 while(n-->0) {
00189 *dst++=*src++;
00190 }
00191 }
00192 while (n>0) {
00193 diff_t l=dst.width()-dst.x_pos();
00194 diff_t numToCopy=(n<l ? n : l);
00195 adobe::copy_n(src.x(), numToCopy, dst.x());
00196 dst+=numToCopy;
00197 src+=numToCopy;
00198 n-=numToCopy;
00199 }
00200 }
00201 };
00202 }
00203 ADOBE_GIL_NAMESPACE_END
00204
00205 namespace std {
00217 template <typename IL, typename OL>
00218 GIL_FORCEINLINE GIL::pixel_image_iterator<OL> copy(GIL::pixel_image_iterator<IL> first, GIL::pixel_image_iterator<IL> last, GIL::pixel_image_iterator<OL> dst) {
00219 GIL::gil_function_requires<GIL::PixelLocatorConcept<IL> >();
00220 GIL::gil_function_requires<GIL::MutablePixelLocatorConcept<OL> >();
00221 typedef typename GIL::pixel_image_iterator<IL>::difference_type diff_t;
00222 diff_t n=diff_t(last-first);
00223 if (first.is_contiguous()) {
00224 if (dst.is_contiguous())
00225 GIL::detail::copier_n<typename IL::x_iterator,typename OL::x_iterator>()(first.x(),n, dst.x());
00226 else
00227 GIL::detail::copier_n<typename IL::x_iterator,GIL::pixel_image_iterator<OL> >()(first.x(),n, dst);
00228 } else {
00229 if (dst.is_contiguous())
00230 GIL::detail::copier_n<GIL::pixel_image_iterator<IL>,typename OL::x_iterator>()(first,n, dst.x());
00231 else
00232 GIL::detail::copier_n<GIL::pixel_image_iterator<IL>,GIL::pixel_image_iterator<OL> >()(first,n,dst);
00233 }
00234 return dst+n;
00235 }
00236 }
00237
00238 ADOBE_GIL_NAMESPACE_BEGIN
00239
00240
00243 template <typename V1, typename V2> GIL_FORCEINLINE
00244 void copy_pixels(const V1& src, const V2& dst) {
00245 assert(src.dimensions()==dst.dimensions());
00246 std::copy(src.begin(),src.end(),dst.begin());
00247 }
00248
00254
00258
00259 namespace detail {
00260 template <typename CC>
00261 class copy_and_convert_pixels_fn : public binary_operation_obj<copy_and_convert_pixels_fn<CC> > {
00262 private:
00263 CC _cc;
00264 public:
00265 typedef typename binary_operation_obj<copy_and_convert_pixels_fn<CC> >::result_type result_type;
00266 copy_and_convert_pixels_fn() {}
00267 copy_and_convert_pixels_fn(CC cc_in) : _cc(cc_in) {}
00268
00269 template <typename V1, typename V2> GIL_FORCEINLINE
00270 result_type apply_incompatible(const V1& src, const V2& dst) const {
00271 copy_pixels(color_converted_view<typename V2::value_type>(src,_cc),dst);
00272 }
00273
00274
00275 template <typename V1, typename V2> GIL_FORCEINLINE
00276 result_type apply_compatible(const V1& src, const V2& dst) const {
00277 copy_pixels(src,dst);
00278 }
00279 };
00280 }
00281
00284 template <typename V1, typename V2,typename CC>
00285 GIL_FORCEINLINE
00286 void copy_and_convert_pixels(const V1& src, const V2& dst,CC cc) {
00287 detail::copy_and_convert_pixels_fn<CC> ccp(cc);
00288 ccp(src,dst);
00289 }
00290
00291
00292 struct default_color_converter;
00293 template <typename V1, typename V2>
00294 GIL_FORCEINLINE
00295 void copy_and_convert_pixels(const V1& src, const V2& dst) {
00296 detail::copy_and_convert_pixels_fn<default_color_converter> ccp;
00297 ccp(src,dst);
00298 }
00299
00300 ADOBE_GIL_NAMESPACE_END
00301
00303
00304
00305
00307
00311
00312 namespace std {
00321 template <typename IL, typename V>
00322 void fill(GIL::pixel_image_iterator<IL> first, GIL::pixel_image_iterator<IL> last, const V& val) {
00323 GIL::gil_function_requires<GIL::MutablePixelLocatorConcept<IL> >();
00324 if (first.is_contiguous()) {
00325 std::fill(first.x(), last.x(), val);
00326 } else {
00327
00328 std::ptrdiff_t n=last-first;
00329 while (n>0) {
00330 std::ptrdiff_t numToDo=std::min<const std::ptrdiff_t>(n,(std::ptrdiff_t)(first.width()-first.x_pos()));
00331 fill_n(first.x(), numToDo, val);
00332 first+=numToDo;
00333 n-=numToDo;
00334 }
00335 }
00336 }
00337 }
00338
00339 ADOBE_GIL_NAMESPACE_BEGIN
00340
00343 template <typename V, typename Value> GIL_FORCEINLINE
00344 void fill_pixels(const V& img_view, const Value& val) {
00345 if (img_view.begin().is_contiguous()) {
00346 std::fill(img_view.begin().x(), img_view.end().x(), val);
00347 } else {
00348 for (int y=0; y<img_view.height(); ++y)
00349 std::fill(img_view.row_begin(y),img_view.row_end(y),val);
00350 }
00351 }
00352 ADOBE_GIL_NAMESPACE_END
00353
00354
00355
00361
00370
00371 ADOBE_GIL_NAMESPACE_BEGIN
00372
00373
00376 template <typename V, typename F>
00377 F for_each_pixel(const V& img, F fun) {
00378 if (img.begin().is_contiguous()) {
00379 return std::for_each(img.begin().x(), img.end().x(), fun);
00380 } else {
00381 for (int y=0; y<img.height(); ++y)
00382 fun = std::for_each(img.row_begin(y),img.row_end(y),fun);
00383 return fun;
00384 }
00385 }
00386
00389 template <typename View, typename F>
00390 F for_each_pixel_position(const View& img, F fun) {
00391 typename View::xy_locator loc=img.xy_at(0,0);
00392 for (int y=0; y<img.height(); ++y) {
00393 for (int x=0; x<img.width(); ++x, ++loc.x())
00394 fun(loc);
00395 loc.x()-=img.width(); ++loc.y();
00396 }
00397 return fun;
00398 }
00400
00401 ADOBE_GIL_NAMESPACE_END
00402
00408
00409 ADOBE_GIL_NAMESPACE_BEGIN
00410
00413 template <typename V, typename F>
00414 F generate_pixels(const V& img, F fun) {
00415 if (img.begin().is_contiguous())
00416 return std::generate(img.begin().x(), img.end().x(), fun);
00417 else {
00418 for (int y=0; y<img.height(); ++y)
00419 fun = std::generate(img.row_begin(y),img.row_end(y),fun);
00420 return fun;
00421 }
00422 }
00423
00424 ADOBE_GIL_NAMESPACE_END
00425
00431
00435
00436 ADOBE_GIL_NAMESPACE_BEGIN
00437
00438 template <typename I1, typename I2> GIL_FORCEINLINE bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2);
00439
00440
00441 namespace detail {
00444 template <typename I1, typename I2>
00445 struct equal_n_fn {
00446 GIL_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, I2 i2) const { return std::equal(i1,i1+n, i2); }
00447 };
00448
00452 template<typename T, typename Cs>
00453 struct equal_n_fn<const pixel<T,Cs>*, const pixel<T,Cs>*> {
00454 GIL_FORCEINLINE bool operator()(const pixel<T,Cs>* i1, std::ptrdiff_t n, const pixel<T,Cs>* i2) const {
00455 return memcmp(i1, i2, n*sizeof(pixel<T,Cs>))==0;
00456 }
00457 };
00458 template<typename T, typename Cs>
00459 struct equal_n_fn<pixel<T,Cs>*, pixel<T,Cs>*> : equal_n_fn<const pixel<T,Cs>*, const pixel<T,Cs>*> {};
00460
00464 template<typename IC, typename Cs>
00465 struct equal_n_fn<planar_ptr<IC,Cs>, planar_ptr<IC,Cs> > {
00466 GIL_FORCEINLINE bool operator()(const planar_ptr<IC,Cs> i1, std::ptrdiff_t n, const planar_ptr<IC,Cs> i2) const {
00467 ptrdiff_t numBytes=n*sizeof(typename std::iterator_traits<IC>::value_type);
00468
00469 for (int i=0; i<Cs::num_channels; ++i)
00470 if (memcmp(i1.channel_ptr(i), i2.channel_ptr(i), numBytes)!=0)
00471 return false;
00472 return true;
00473 }
00474 };
00475
00476
00477
00480 template <typename Loc, typename I2>
00481 struct equal_n_fn<GIL::pixel_image_iterator<Loc>,I2> {
00482 GIL_FORCEINLINE bool operator()(GIL::pixel_image_iterator<Loc> i1, std::ptrdiff_t n, I2 i2) const {
00483 GIL::gil_function_requires<GIL::PixelLocatorConcept<Loc> >();
00484 GIL::gil_function_requires<GIL::PixelIteratorConcept<I2> >();
00485 while (n>0) {
00486 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n, i1.width()-i1.x_pos());
00487 if (!equal_n(i1.x(), num, i2))
00488 return false;
00489 i1+=num;
00490 i2+=num;
00491 n-=num;
00492 }
00493 return true;
00494 }
00495 };
00496
00499 template <typename I1, typename Loc>
00500 struct equal_n_fn<I1,GIL::pixel_image_iterator<Loc> > {
00501 GIL_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, GIL::pixel_image_iterator<Loc> i2) const {
00502 GIL::gil_function_requires<GIL::PixelIteratorConcept<I1> >();
00503 GIL::gil_function_requires<GIL::PixelLocatorConcept<Loc> >();
00504 while (n>0) {
00505 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
00506 if (!equal_n(i1, num, i2.x()))
00507 return false;
00508 i1+=num;
00509 i2+=num;
00510 n-=num;
00511 }
00512 return true;
00513 }
00514 };
00515
00518 template <typename Loc1, typename Loc2>
00519 struct equal_n_fn<GIL::pixel_image_iterator<Loc1>,GIL::pixel_image_iterator<Loc2> > {
00520 GIL_FORCEINLINE bool operator()(GIL::pixel_image_iterator<Loc1> i1, std::ptrdiff_t n, GIL::pixel_image_iterator<Loc2> i2) const {
00521 GIL::gil_function_requires<GIL::PixelLocatorConcept<Loc1> >();
00522 GIL::gil_function_requires<GIL::PixelLocatorConcept<Loc2> >();
00523 if (i1.x_pos()!=i2.x_pos() || i1.width()!=i2.width()) {
00524 while(n-->0) {
00525 if (*i1++!=*i2++) return false;
00526 }
00527 }
00528 while (n>0) {
00529 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
00530 if (!equal_n(i1.x(), num, i2.x()))
00531 return false;
00532 i1+=num;
00533 i2+=num;
00534 n-=num;
00535 }
00536 return true;
00537 }
00538 };
00539 }
00540
00542 template <typename I1, typename I2> GIL_FORCEINLINE
00543 bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2) {
00544 return detail::equal_n_fn<I1,I2>()(i1,n,i2);
00545 }
00546 ADOBE_GIL_NAMESPACE_END
00547
00548 namespace std {
00560 template <typename Loc1, typename Loc2> GIL_FORCEINLINE
00561 bool equal(GIL::pixel_image_iterator<Loc1> first, GIL::pixel_image_iterator<Loc1> last, GIL::pixel_image_iterator<Loc2> first2) {
00562 GIL::gil_function_requires<GIL::PixelLocatorConcept<Loc1> >();
00563 GIL::gil_function_requires<GIL::PixelLocatorConcept<Loc2> >();
00564 std::ptrdiff_t n=last-first;
00565 if (first.is_contiguous()) {
00566 if (first2.is_contiguous())
00567 return GIL::detail::equal_n_fn<typename Loc1::x_iterator,typename Loc2::x_iterator>()(first.x(),n, first2.x());
00568 else
00569 return GIL::detail::equal_n_fn<typename Loc1::x_iterator,GIL::pixel_image_iterator<Loc2> >()(first.x(),n, first2);
00570 } else {
00571 if (first2.is_contiguous())
00572 return GIL::detail::equal_n_fn<GIL::pixel_image_iterator<Loc1>,typename Loc2::x_iterator>()(first,n, first2.x());
00573 else
00574 return GIL::detail::equal_n_fn<GIL::pixel_image_iterator<Loc1>,GIL::pixel_image_iterator<Loc2> >()(first,n,first2);
00575 }
00576 }
00577 }
00578
00579 ADOBE_GIL_NAMESPACE_BEGIN
00580
00581
00582 namespace detail {
00583 struct equal_pixels_fn : public binary_operation_obj<equal_pixels_fn,bool> {
00584 template <typename V1, typename V2>
00585 GIL_FORCEINLINE bool operator()(const V1& v1, const V2& v2) const {
00586 assert(v1.dimensions()==v2.dimensions());
00587 return std::equal(v1.begin(),v1.end(),v2.begin());
00588 }
00589 };
00590 }
00591
00594 template <typename V1, typename V2> GIL_FORCEINLINE
00595 bool equal_pixels(const V1& v1, const V2& v2) {
00596 return detail::equal_pixels_fn()(v1,v2);
00597 }
00598 ADOBE_GIL_NAMESPACE_END
00599
00600
00606
00610
00611 ADOBE_GIL_NAMESPACE_BEGIN
00612
00615 template <typename V1, typename V2, typename F> GIL_FORCEINLINE
00616 F transform_pixels(const V1& src,const V2& dst, F fun) {
00617 assert(src.dimensions()==dst.dimensions());
00618 for (int y=0; y<src.height(); ++y) {
00619 typename V1::x_iterator srcIt=src.row_begin(y);
00620 typename V2::x_iterator dstIt=dst.row_begin(y);
00621 for (int x=0; x<src.width(); ++x)
00622 dstIt[x]=fun(srcIt[x]);
00623 }
00624 return fun;
00625 }
00626
00629 template <typename V1, typename V2, typename V3, typename F> GIL_FORCEINLINE
00630 F transform_pixels(const V1& src1, const V2& src2,const V3& dst, F fun) {
00631 for (int y=0; y<dst.height(); ++y) {
00632 typename V1::x_iterator srcIt1=src1.row_begin(y);
00633 typename V2::x_iterator srcIt2=src2.row_begin(y);
00634 typename V3::x_iterator dstIt=dst.row_begin(y);
00635 for (int x=0; x<dst.width(); ++x)
00636 dstIt[x]=fun(srcIt1[x],srcIt2[x]);
00637 }
00638 return fun;
00639 }
00640
00643 template <typename V1, typename V2, typename F> GIL_FORCEINLINE
00644 F transform_pixel_positions(const V1& src,const V2& dst, F fun) {
00645 assert(src.dimensions()==dst.dimensions());
00646 typename V1::xy_locator loc=src.xy_at(0,0);
00647 for (int y=0; y<src.height(); ++y) {
00648 typename V2::x_iterator dstIt=dst.row_begin(y);
00649 for (int x=0; x<src.width(); ++x, ++loc.x())
00650 dstIt[x]=fun(loc);
00651 loc.x()-=src.width(); ++loc.y();
00652 }
00653 return fun;
00654 }
00655
00658 template <typename V1, typename V2, typename V3, typename F> GIL_FORCEINLINE
00659 F transform_pixel_positions(const V1& src1,const V2& src2,const V3& dst, F fun) {
00660 assert(src1.dimensions()==dst.dimensions());
00661 assert(src2.dimensions()==dst.dimensions());
00662 typename V1::xy_locator loc1=src1.xy_at(0,0);
00663 typename V2::xy_locator loc2=src2.xy_at(0,0);
00664 for (int y=0; y<src1.height(); ++y) {
00665 typename V3::x_iterator dstIt=dst.row_begin(y);
00666 for (int x=0; x<src1.width(); ++x, ++loc1.x(), ++loc2.x())
00667 dstIt[x]=fun(loc1,loc2);
00668 loc1.x()-=src1.width(); ++loc1.y();
00669 loc2.x()-=src2.width(); ++loc2.y();
00670 }
00671 return fun;
00672 }
00674
00675
00676
00677 ADOBE_GIL_NAMESPACE_END
00678
00679 #endif