00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef GIL_ALGORITHMS_H
00010 #define GIL_ALGORITHMS_H
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
00037
00038
00039
00040
00041
00042
00043
00044
00045
00047
00048
00049
00050
00051
00052
00054
00055
00056
00057
00058
00059
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00072
00073
00082 template <typename DERIVED, typename RESULT_T=void>
00083 struct binary_operation_obj {
00084 typedef RESULT_T result_type;
00085
00086 template <typename V1, typename V2> GIL_FORCEINLINE
00087 result_type operator()(const std::pair<const V1*,const V2*>& p) const {
00088 return apply(*p.first, *p.second, typename views_are_compatible<V1,V2>::type());
00089 }
00090
00091 template <typename V1, typename V2> GIL_FORCEINLINE
00092 result_type operator()(const V1& v1, const V2& v2) const {
00093 return apply(v1, v2, typename views_are_compatible<V1,V2>::type());
00094 }
00095
00096 result_type operator()(const error_t&) const { throw std::bad_cast(); }
00097 private:
00098
00099
00100 template <typename V1, typename V2>
00101 GIL_FORCEINLINE result_type apply(const V1& v1, const V2& v2, boost::mpl::false_) const {
00102 return ((const DERIVED*)this)->apply_incompatible(v1,v2);
00103 }
00104
00105
00106 template <typename V1, typename V2>
00107 GIL_FORCEINLINE result_type apply(const V1& v1, const V2& v2, boost::mpl::true_) const {
00108 return ((const DERIVED*)this)->apply_compatible(v1,v2);
00109 }
00110
00111
00112 template <typename V1, typename V2>
00113 GIL_FORCEINLINE result_type apply_incompatible(const V1& v1, const V2& v2) const {
00114 throw std::bad_cast();
00115 }
00116 };
00117 ADOBE_GIL_NAMESPACE_END
00118
00124
00128
00129 namespace std {
00133
00136 template<typename T, typename CS>
00137 GIL_FORCEINLINE GIL::pixel<T,CS>* copy(GIL::pixel<T,CS>* first, GIL::pixel<T,CS>* last, GIL::pixel<T,CS>* dst) {
00138 return (GIL::pixel<T,CS>*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst);
00139 }
00140
00143 template<typename T, typename CS>
00144 GIL_FORCEINLINE GIL::pixel<T,CS>* copy(const GIL::pixel<T,CS>* first, const GIL::pixel<T,CS>* last, GIL::pixel<T,CS>* dst) {
00145 return (GIL::pixel<T,CS>*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst);
00146 }
00147 }
00148
00149 ADOBE_GIL_NAMESPACE_BEGIN
00150 namespace detail {
00151 template <typename I, typename O> struct copy_fn {
00152 GIL_FORCEINLINE I operator()(I first, I last, O dst) const { return std::copy(first,last,dst); }
00153 };
00154 }
00155 ADOBE_GIL_NAMESPACE_END
00156
00157 namespace std {
00160 template<typename IC1, typename CS1, typename IC2, typename CS2> GIL_FORCEINLINE
00161 GIL::planar_ptr<IC2,CS2> copy(GIL::planar_ptr<IC1,CS1> first, GIL::planar_ptr<IC1,CS1> last, GIL::planar_ptr<IC2,CS2> dst) {
00162 GIL::gil_function_requires<GIL::ChannelsCompatibleConcept<typename std::iterator_traits<IC1>::value_type,typename std::iterator_traits<IC2>::value_type> >();
00163 GIL::gil_function_requires<GIL::ColorSpacesCompatibleConcept<CS1,CS2> >();
00164 for_each_channel(first,last,dst,GIL::detail::copy_fn<IC1,IC2>());
00165 return dst+(last-first);
00166 }
00167 }
00168
00169 ADOBE_GIL_NAMESPACE_BEGIN
00170 namespace detail {
00173 template <typename I, typename O>
00174 struct copier_n {
00175 GIL_FORCEINLINE void operator()(I src, std::ptrdiff_t n, O dst) const { std::copy(src,src+n, dst); }
00176 };
00177
00180 template <typename IL, typename O>
00181 struct copier_n<GIL::pixel_image_iterator<IL>,O> {
00182 GIL_FORCEINLINE void operator()(GIL::pixel_image_iterator<IL> src, std::ptrdiff_t n, O dst) const {
00183 GIL::gil_function_requires<GIL::PixelLocatorConcept<IL> >();
00184 GIL::gil_function_requires<GIL::MutablePixelIteratorConcept<O> >();
00185 while (n>0) {
00186 std::ptrdiff_t numToCopy=std::min<const std::ptrdiff_t>(n, src.width()-src.x_pos());
00187 adobe::copy_n(src.x(), numToCopy, dst);
00188 dst+=numToCopy;
00189 src+=numToCopy;
00190 n-=numToCopy;
00191 }
00192 }
00193 };
00194
00197 template <typename I, typename OL>
00198 struct copier_n<I,GIL::pixel_image_iterator<OL> > {
00199 GIL_FORCEINLINE void operator()(I src, std::ptrdiff_t n, GIL::pixel_image_iterator<OL> dst) const {
00200 GIL::gil_function_requires<GIL::PixelIteratorConcept<I> >();
00201 GIL::gil_function_requires<GIL::MutablePixelLocatorConcept<OL> >();
00202 while (n>0) {
00203 std::ptrdiff_t numToCopy=std::min<const std::ptrdiff_t>(n,dst.width()-dst.x_pos());
00204 adobe::copy_n(src, numToCopy, dst.x());
00205 dst+=numToCopy;
00206 src+=numToCopy;
00207 n-=numToCopy;
00208 }
00209 }
00210 };
00211
00214 template <typename IL, typename OL>
00215 struct copier_n<GIL::pixel_image_iterator<IL>,GIL::pixel_image_iterator<OL> > {
00216 GIL_FORCEINLINE void operator()(GIL::pixel_image_iterator<IL> src, std::ptrdiff_t n, GIL::pixel_image_iterator<OL> dst) const {
00217 GIL::gil_function_requires<GIL::PixelLocatorConcept<IL> >();
00218 GIL::gil_function_requires<GIL::MutablePixelLocatorConcept<OL> >();
00219 if (src.x_pos()!=dst.x_pos() || src.width()!=dst.width()) {
00220 while(n-->0) {
00221 *dst++=*src++;
00222 }
00223 }
00224 while (n>0) {
00225 std::ptrdiff_t numToCopy=std::min<const std::ptrdiff_t>(n,dst.width()-dst.x_pos());
00226 adobe::copy_n(src.x(), numToCopy, dst.x());
00227 dst+=numToCopy;
00228 src+=numToCopy;
00229 n-=numToCopy;
00230 }
00231 }
00232 };
00233 }
00234 ADOBE_GIL_NAMESPACE_END
00235
00236 namespace std {
00248 template <typename IL, typename OL>
00249 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) {
00250 GIL::gil_function_requires<GIL::PixelLocatorConcept<IL> >();
00251 GIL::gil_function_requires<GIL::MutablePixelLocatorConcept<OL> >();
00252 std::ptrdiff_t n=last-first;
00253 if (first.is_contiguous()) {
00254 if (dst.is_contiguous())
00255 GIL::detail::copier_n<typename IL::x_iterator,typename OL::x_iterator>()(first.x(),n, dst.x());
00256 else
00257 GIL::detail::copier_n<typename IL::x_iterator,GIL::pixel_image_iterator<OL> >()(first.x(),n, dst);
00258 } else {
00259 if (dst.is_contiguous())
00260 GIL::detail::copier_n<GIL::pixel_image_iterator<IL>,typename OL::x_iterator>()(first,n, dst.x());
00261 else
00262 GIL::detail::copier_n<GIL::pixel_image_iterator<IL>,GIL::pixel_image_iterator<OL> >()(first,n,dst);
00263 }
00264 return dst+n;
00265 }
00266 }
00267
00268 ADOBE_GIL_NAMESPACE_BEGIN
00269
00270
00273 template <typename V1, typename V2> GIL_FORCEINLINE
00274 void copy_pixels(const V1& src, const V2& dst) {
00275 assert(src.dimensions()==dst.dimensions());
00276 std::copy(src.begin(),src.end(),dst.begin());
00277 }
00278 ADOBE_GIL_NAMESPACE_END
00279
00285
00289
00290 ADOBE_GIL_NAMESPACE_BEGIN
00291 namespace detail {
00292 struct copy_and_convert_pixels_fn : public binary_operation_obj<copy_and_convert_pixels_fn> {
00293
00294 template <typename V1, typename V2> GIL_FORCEINLINE
00295 result_type apply_incompatible(const V1& src, const V2& dst) const {
00296 copy_pixels(color_converted_view<typename V2::value_type>(src),dst);
00297 }
00298
00299
00300 template <typename V1, typename V2> GIL_FORCEINLINE
00301 result_type apply_compatible(const V1& src, const V2& dst) const {
00302 copy_pixels(src,dst);
00303 }
00304 };
00305 }
00306
00309 template <typename V1, typename V2> GIL_FORCEINLINE
00310 void copy_and_convert_pixels(const V1& src, const V2& dst) {
00311 detail::copy_and_convert_pixels_fn()(src,dst);
00312 }
00313
00314 ADOBE_GIL_NAMESPACE_END
00315
00317
00318
00319
00321
00325
00326 namespace std {
00335 template <typename IL, typename V>
00336 void fill(GIL::pixel_image_iterator<IL> first, GIL::pixel_image_iterator<IL> last, const V& val) {
00337 GIL::gil_function_requires<GIL::MutablePixelLocatorConcept<IL> >();
00338 if (first.is_contiguous()) {
00339 std::fill(first.x(), last.x(), val);
00340 } else {
00341
00342 std::ptrdiff_t n=last-first;
00343 while (n>0) {
00344 std::ptrdiff_t numToDo=std::min<const std::ptrdiff_t>(n,(std::ptrdiff_t)(first.width()-first.x_pos()));
00345 fill_n(first.x(), numToDo, val);
00346 first+=numToDo;
00347 n-=numToDo;
00348 }
00349 }
00350 }
00351 }
00352
00353 ADOBE_GIL_NAMESPACE_BEGIN
00354
00357 template <typename V, typename VAL> GIL_FORCEINLINE
00358 void fill_pixels(const V& img_view, const VAL& val) {
00359 if (img_view.begin().is_contiguous()) {
00360 std::fill(img_view.begin().x(), img_view.end().x(), val);
00361 } else {
00362 for (int y=0; y<img_view.height(); ++y)
00363 std::fill(img_view.row_begin(y),img_view.row_end(y),val);
00364 }
00365 }
00366 ADOBE_GIL_NAMESPACE_END
00367
00368
00369
00375
00384
00385 ADOBE_GIL_NAMESPACE_BEGIN
00386
00387
00390 template <typename V, typename F>
00391 F for_each_pixel(const V& img, F fun) {
00392 if (img.begin().is_contiguous()) {
00393 return std::for_each(img.begin().x(), img.end().x(), fun);
00394 } else {
00395 for (int y=0; y<img.height(); ++y)
00396 fun = std::for_each(img.row_begin(y),img.row_end(y),fun);
00397 return fun;
00398 }
00399 }
00400
00403 template <typename VIEW, typename F>
00404 F for_each_pixel_position(const VIEW& img, F fun) {
00405 typename VIEW::xy_locator loc=img.xy_at(0,0);
00406 for (int y=0; y<img.height(); ++y) {
00407 for (int x=0; x<img.width(); ++x, ++loc.x())
00408 fun(loc);
00409 loc.x()-=img.width(); ++loc.y();
00410 }
00411 return fun;
00412 }
00414
00415 ADOBE_GIL_NAMESPACE_END
00416
00422
00426
00427 ADOBE_GIL_NAMESPACE_BEGIN
00428
00429 template <typename I1, typename I2> GIL_FORCEINLINE bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2);
00430
00431
00432 namespace detail {
00435 template <typename I1, typename I2>
00436 struct equal_n_fn {
00437 GIL_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, I2 i2) const { return std::equal(i1,i1+n, i2); }
00438 };
00439
00443 template<typename T, typename CS>
00444 struct equal_n_fn<const pixel<T,CS>*, const pixel<T,CS>*> {
00445 GIL_FORCEINLINE bool operator()(const pixel<T,CS>* i1, std::ptrdiff_t n, const pixel<T,CS>* i2) const {
00446 return memcmp(i1, i2, n*sizeof(pixel<T,CS>))==0;
00447 }
00448 };
00449 template<typename T, typename CS>
00450 struct equal_n_fn<pixel<T,CS>*, pixel<T,CS>*> : equal_n_fn<const pixel<T,CS>*, const pixel<T,CS>*> {};
00451
00455 template<typename IC, typename CS>
00456 struct equal_n_fn<planar_ptr<IC,CS>, planar_ptr<IC,CS> > {
00457 GIL_FORCEINLINE bool operator()(const planar_ptr<IC,CS> i1, std::ptrdiff_t n, const planar_ptr<IC,CS> i2) const {
00458 ptrdiff_t numBytes=n*sizeof(typename std::iterator_traits<IC>::value_type);
00459
00460 for (int i=0; i<CS::num_channels; ++i)
00461 if (memcmp(i1.channel_ptr(i), i2.channel_ptr(i), numBytes)!=0)
00462 return false;
00463 return true;
00464 }
00465 };
00466
00467
00468
00471 template <typename LOC, typename I2>
00472 struct equal_n_fn<GIL::pixel_image_iterator<LOC>,I2> {
00473 GIL_FORCEINLINE bool operator()(GIL::pixel_image_iterator<LOC> i1, std::ptrdiff_t n, I2 i2) const {
00474 GIL::gil_function_requires<GIL::PixelLocatorConcept<LOC> >();
00475 GIL::gil_function_requires<GIL::PixelIteratorConcept<I2> >();
00476 while (n>0) {
00477 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n, i1.width()-i1.x_pos());
00478 if (!equal_n(i1.x(), num, i2))
00479 return false;
00480 i1+=num;
00481 i2+=num;
00482 n-=num;
00483 }
00484 return true;
00485 }
00486 };
00487
00490 template <typename I1, typename LOC>
00491 struct equal_n_fn<I1,GIL::pixel_image_iterator<LOC> > {
00492 GIL_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, GIL::pixel_image_iterator<LOC> i2) const {
00493 GIL::gil_function_requires<GIL::PixelIteratorConcept<I1> >();
00494 GIL::gil_function_requires<GIL::PixelLocatorConcept<LOC> >();
00495 while (n>0) {
00496 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
00497 if (!equal_n(i1, num, i2.x()))
00498 return false;
00499 i1+=num;
00500 i2+=num;
00501 n-=num;
00502 }
00503 return true;
00504 }
00505 };
00506
00509 template <typename LOC1, typename LOC2>
00510 struct equal_n_fn<GIL::pixel_image_iterator<LOC1>,GIL::pixel_image_iterator<LOC2> > {
00511 GIL_FORCEINLINE bool operator()(GIL::pixel_image_iterator<LOC1> i1, std::ptrdiff_t n, GIL::pixel_image_iterator<LOC2> i2) const {
00512 GIL::gil_function_requires<GIL::PixelLocatorConcept<LOC1> >();
00513 GIL::gil_function_requires<GIL::PixelLocatorConcept<LOC2> >();
00514 if (i1.x_pos()!=i2.x_pos() || i1.width()!=i2.width()) {
00515 while(n-->0) {
00516 if (*i1++!=*i2++) return false;
00517 }
00518 }
00519 while (n>0) {
00520 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
00521 if (!equal_n(i1.x(), num, i2.x()))
00522 return false;
00523 i1+=num;
00524 i2+=num;
00525 n-=num;
00526 }
00527 return true;
00528 }
00529 };
00530 }
00531
00533 template <typename I1, typename I2> GIL_FORCEINLINE
00534 bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2) {
00535 return detail::equal_n_fn<I1,I2>()(i1,n,i2);
00536 }
00537 ADOBE_GIL_NAMESPACE_END
00538
00539 namespace std {
00551 template <typename LOC1, typename LOC2> GIL_FORCEINLINE
00552 bool equal(GIL::pixel_image_iterator<LOC1> first, GIL::pixel_image_iterator<LOC1> last, GIL::pixel_image_iterator<LOC2> first2) {
00553 GIL::gil_function_requires<GIL::PixelLocatorConcept<LOC1> >();
00554 GIL::gil_function_requires<GIL::PixelLocatorConcept<LOC2> >();
00555 std::ptrdiff_t n=last-first;
00556 if (first.is_contiguous()) {
00557 if (first2.is_contiguous())
00558 return GIL::detail::equal_n_fn<typename LOC1::x_iterator,typename LOC2::x_iterator>()(first.x(),n, first2.x());
00559 else
00560 return GIL::detail::equal_n_fn<typename LOC1::x_iterator,GIL::pixel_image_iterator<LOC2> >()(first.x(),n, first2);
00561 } else {
00562 if (first2.is_contiguous())
00563 return GIL::detail::equal_n_fn<GIL::pixel_image_iterator<LOC1>,typename LOC2::x_iterator>()(first,n, first2.x());
00564 else
00565 return GIL::detail::equal_n_fn<GIL::pixel_image_iterator<LOC1>,GIL::pixel_image_iterator<LOC2> >()(first,n,first2);
00566 }
00567 }
00568 }
00569
00570 ADOBE_GIL_NAMESPACE_BEGIN
00571
00572
00573 namespace detail {
00574 struct equal_pixels_fn : public binary_operation_obj<equal_pixels_fn,bool> {
00575 template <typename V1, typename V2>
00576 GIL_FORCEINLINE bool operator()(const V1& v1, const V2& v2) const {
00577 assert(v1.dimensions()==v2.dimensions());
00578 return std::equal(v1.begin(),v1.end(),v2.begin());
00579 }
00580 };
00581 }
00582
00585 template <typename V1, typename V2> GIL_FORCEINLINE
00586 bool equal_pixels(const V1& v1, const V2& v2) {
00587 return detail::equal_pixels_fn()(v1,v2);
00588 }
00589 ADOBE_GIL_NAMESPACE_END
00590
00591
00597
00601
00602 ADOBE_GIL_NAMESPACE_BEGIN
00603
00606 template <typename V1, typename V2, typename F> GIL_FORCEINLINE
00607 F transform_pixels(const V1& src,const V2& dst, F fun) {
00608 assert(src.dimensions()==dst.dimensions());
00609 for (int y=0; y<src.height(); ++y) {
00610 typename V1::x_iterator srcIt=src.row_begin(y);
00611 typename V2::x_iterator dstIt=dst.row_begin(y);
00612 for (int x=0; x<src.width(); ++x)
00613 dstIt[x]=fun(srcIt[x]);
00614 }
00615 return fun;
00616 }
00617
00620 template <typename V1, typename V2, typename V3, typename F> GIL_FORCEINLINE
00621 F transform_pixels(const V1& src1, const V2& src2,const V3& dst, F fun) {
00622 for (int y=0; y<dst.height(); ++y) {
00623 typename V1::x_iterator srcIt1=src1.row_begin(y);
00624 typename V2::x_iterator srcIt2=src2.row_begin(y);
00625 typename V3::x_iterator dstIt=dst.row_begin(y);
00626 for (int x=0; x<dst.width(); ++x)
00627 dstIt[x]=fun(srcIt1[x],srcIt2[x]);
00628 }
00629 return fun;
00630 }
00631
00634 template <typename V1, typename V2, typename F> GIL_FORCEINLINE
00635 F transform_pixel_positions(const V1& src,const V2& dst, F fun) {
00636 assert(src.dimensions()==dst.dimensions());
00637 typename V1::xy_locator loc=src.xy_at(0,0);
00638 for (int y=0; y<src.height(); ++y) {
00639 typename V2::x_iterator dstIt=dst.row_begin(y);
00640 for (int x=0; x<src.width(); ++x, ++loc.x())
00641 dstIt[x]=fun(loc);
00642 loc.x()-=src.width(); ++loc.y();
00643 }
00644 return fun;
00645 }
00646
00649 template <typename V1, typename V2, typename V3, typename F> GIL_FORCEINLINE
00650 F transform_pixel_positions(const V1& src1,const V2& src2,const V3& dst, F fun) {
00651 assert(src1.dimensions()==dst.dimensions());
00652 assert(src2.dimensions()==dst.dimensions());
00653 typename V1::xy_locator loc1=src1.xy_at(0,0);
00654 typename V2::xy_locator loc2=src2.xy_at(0,0);
00655 for (int y=0; y<src1.height(); ++y) {
00656 typename V3::x_iterator dstIt=dst.row_begin(y);
00657 for (int x=0; x<src1.width(); ++x, ++loc1.x(), ++loc2.x())
00658 dstIt[x]=fun(loc1,loc2);
00659 loc1.x()-=src1.width(); ++loc1.y();
00660 loc2.x()-=src2.width(); ++loc2.y();
00661 }
00662 return fun;
00663 }
00665
00666
00667
00668 ADOBE_GIL_NAMESPACE_END
00669
00670 #endif