Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r65879 - sandbox/gil/boost/gil
From: dsaritz_at_[hidden]
Date: 2010-10-10 12:42:08


Author: psiha
Date: 2010-10-10 12:42:02 EDT (Sun, 10 Oct 2010)
New Revision: 65879
URL: http://svn.boost.org/trac/boost/changeset/65879

Log:
Adding base GIL files (from the trunk) with various local optimizations.
Added:
   sandbox/gil/boost/gil/algorithm.hpp (contents, props changed)
   sandbox/gil/boost/gil/color_convert.hpp (contents, props changed)
   sandbox/gil/boost/gil/image.hpp (contents, props changed)
   sandbox/gil/boost/gil/locator.hpp (contents, props changed)
   sandbox/gil/boost/gil/utilities.hpp (contents, props changed)

Added: sandbox/gil/boost/gil/algorithm.hpp
==============================================================================
--- (empty file)
+++ sandbox/gil/boost/gil/algorithm.hpp 2010-10-10 12:42:02 EDT (Sun, 10 Oct 2010)
@@ -0,0 +1,1029 @@
+/*
+ Copyright 2005-2007 Adobe Systems Incorporated
+
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+
+ See http://opensource.adobe.com/gil for most recent version including documentation.
+*/
+
+
+/*************************************************************************************************/
+
+#ifndef GIL_ALGORITHM_HPP
+#define GIL_ALGORITHM_HPP
+
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <algorithm>
+#include <iterator>
+#include <memory>
+#include <typeinfo>
+#include "gil_config.hpp"
+#include "gil_concept.hpp"
+#include "color_base_algorithm.hpp"
+#include "image_view.hpp"
+#include "image_view_factory.hpp"
+#include "bit_aligned_pixel_iterator.hpp"
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief Some basic STL-style algorithms when applied to image views
+/// \author Lubomir Bourdev and Hailin Jin \n
+/// Adobe Systems Incorporated
+/// \date 2005-2008 \n Last updated on March 12, 2008
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+//#ifdef _MSC_VER
+//#pragma warning(push)
+//#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)
+//#endif
+
+namespace boost { namespace gil {
+
+//forward declarations
+template <typename ChannelPtr, typename ColorSpace>
+struct planar_pixel_iterator;
+template <typename Iterator>
+class memory_based_step_iterator;
+template <typename StepIterator>
+class memory_based_2d_locator;
+
+// a tag denoting incompatible arguments
+struct error_t {};
+
+/// \defgroup ImageViewSTLAlgorithms STL-like Algorithms
+/// \ingroup ImageViewAlgorithm
+/// \brief Image view-equivalents of STL algorithms
+///
+/// Image views provide 1D iteration of their pixels via \p begin() and \p end() methods,
+/// which makes it possible to use STL algorithms with them. However, using nested loops
+/// over X and Y is in many cases more efficient. The algorithms in this section resemble
+/// STL algorithms, but they abstract away the nested loops and take views (as opposed to ranges) as input.
+///
+/// Most algorithms check whether the image views are 1D-traversable. A 1D-traversable image view has no gaps
+/// 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
+/// it will move to the first pixel of the next row. When image views are 1D-traversable, the algorithms use
+/// a single loop and run more efficiently. If one or more of the input views are not 1D-traversable, the algorithms
+/// fall-back to an X-loop nested inside a Y-loop.
+///
+/// The algorithms typically delegate the work to their corresponding STL algorithms. For example, \p copy_pixels calls
+/// \p std::copy either for each row, or, when the images are 1D-traversable, once for all pixels.
+///
+/// In addition, overloads are sometimes provided for the STL algorithms. For example, std::copy for planar iterators
+/// is overloaded to perform \p std::copy for each of the planes. \p std::copy over bitwise-copiable pixels results in
+/// std::copy over unsigned char, which STL typically implements via \p memmove.
+///
+/// As a result \p copy_pixels may result in a single call to \p memmove for interleaved 1D-traversable views,
+/// or one per each plane of planar 1D-traversable views, or one per each row of interleaved non-1D-traversable images, etc.
+
+
+/// \defgroup STLOptimizations Performance overloads of STL algorithms
+/// \ingroup ImageViewAlgorithm
+/// \brief overloads of STL algorithms allowing more efficient implementation when used with GIL constructs
+
+/// \brief A generic binary operation on views
+/// \ingroup ImageViewSTLAlgorithms
+///
+/// Use this class as a convenience superclass when defining an operation for any image views.
+/// Many operations have different behavior when the two views are compatible. This class checks
+/// for compatibility and invokes apply_compatible(V1,V2) or apply_incompatible(V1,V2) of the subclass.
+/// You must provide apply_compatible(V1,V2) method in your subclass, but apply_incompatible(V1,V2)
+/// is not required and the default throws std::bad_cast.
+template <typename Derived, typename Result=void>
+struct binary_operation_obj {
+ typedef Result result_type;
+
+ template <typename V1, typename V2> GIL_FORCEINLINE
+ result_type operator()(const std::pair<const V1*,const V2*>& p) const {
+ return apply(*p.first, *p.second, typename views_are_compatible<V1,V2>::type());
+ }
+
+ template <typename V1, typename V2> GIL_FORCEINLINE
+ result_type operator()(const V1& v1, const V2& v2) const {
+ return apply(v1, v2, typename views_are_compatible<V1,V2>::type());
+ }
+
+ result_type operator()(const error_t&) const { throw std::bad_cast(); }
+private:
+
+ // dispatch from apply overload to a function with distinct name
+ template <typename V1, typename V2>
+ GIL_FORCEINLINE result_type apply(const V1& v1, const V2& v2, mpl::false_) const {
+ return ((const Derived*)this)->apply_incompatible(v1,v2);
+ }
+
+ // dispatch from apply overload to a function with distinct name
+ template <typename V1, typename V2>
+ GIL_FORCEINLINE result_type apply(const V1& v1, const V2& v2, mpl::true_) const {
+ return ((const Derived*)this)->apply_compatible(v1,v2);
+ }
+
+ // function with distinct name - it can be overloaded by subclasses
+ template <typename V1, typename V2>
+ GIL_FORCEINLINE result_type apply_incompatible(const V1& v1, const V2& v2) const {
+ throw std::bad_cast();
+ }
+};
+} } // namespace boost::gil
+
+//////////////////////////////////////////////////////////////////////////////////////
+///
+/// std::copy and gil::copy_pixels
+///
+//////////////////////////////////////////////////////////////////////////////////////
+
+/// \defgroup ImageViewSTLAlgorithmsCopyPixels copy_pixels
+/// \ingroup ImageViewSTLAlgorithms
+/// \brief std::copy for image views
+
+namespace std {
+
+/// \ingroup STLOptimizations
+/// \brief Copy when both src and dst are interleaved and of the same type can be just memmove
+template<typename T, typename Cs>
+GIL_FORCEINLINE boost::gil::pixel<T,Cs>*
+copy(boost::gil::pixel<T,Cs>* first, boost::gil::pixel<T,Cs>* last,
+ boost::gil::pixel<T,Cs>* dst) {
+ return (boost::gil::pixel<T,Cs>*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst);
+}
+
+/// \ingroup STLOptimizations
+/// \brief Copy when both src and dst are interleaved and of the same type can be just memmove
+template<typename T, typename Cs>
+GIL_FORCEINLINE boost::gil::pixel<T,Cs>*
+copy(const boost::gil::pixel<T,Cs>* first, const boost::gil::pixel<T,Cs>* last,
+ boost::gil::pixel<T,Cs>* dst) {
+ return (boost::gil::pixel<T,Cs>*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst);
+}
+} // namespace std
+
+namespace boost { namespace gil {
+namespace detail {
+template <typename I, typename O> struct copy_fn {
+ GIL_FORCEINLINE I operator()(I first, I last, O dst) const { return std::copy(first,last,dst); }
+};
+} // namespace detail
+} } // namespace boost::gil
+
+namespace std {
+/// \ingroup STLOptimizations
+/// \brief Copy when both src and dst are planar pointers is copy for each channel
+template<typename Cs, typename IC1, typename IC2> GIL_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) {
+ boost::gil::gil_function_requires<boost::gil::ChannelsCompatibleConcept<typename std::iterator_traits<IC1>::value_type,typename std::iterator_traits<IC2>::value_type> >();
+ static_for_each(first,last,dst,boost::gil::detail::copy_fn<IC1,IC2>());
+ return dst+(last-first);
+}
+} // namespace std
+
+namespace boost { namespace gil {
+namespace detail {
+/// Does a copy-n. If the inputs contain image iterators, performs a copy at each row using the row iterators
+/// \ingroup CopyPixels
+template <typename I, typename O>
+struct copier_n {
+ GIL_FORCEINLINE void operator()(I src, typename std::iterator_traits<I>::difference_type n, O dst) const { std::copy(src,src+n, dst); }
+};
+
+/// Source range is delimited by image iterators
+template <typename IL, typename O> // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept
+struct copier_n<iterator_from_2d<IL>,O> {
+ typedef typename std::iterator_traits<iterator_from_2d<IL> >::difference_type diff_t;
+ GIL_FORCEINLINE void operator()(iterator_from_2d<IL> src, diff_t n, O dst) const {
+ gil_function_requires<PixelLocatorConcept<IL> >();
+ gil_function_requires<MutablePixelIteratorConcept<O> >();
+ while (n>0) {
+ typedef typename iterator_from_2d<IL>::difference_type diff_t;
+ diff_t l=src.width()-src.x_pos();
+ diff_t numToCopy=(n<l ? n:l);
+ detail::copy_n(src.x(), numToCopy, dst);
+ dst+=numToCopy;
+ src+=numToCopy;
+ n-=numToCopy;
+ }
+ }
+};
+
+/// Destination range is delimited by image iterators
+template <typename I, typename OL> // I Models ConstPixelIteratorConcept, OL Models PixelLocatorConcept
+struct copier_n<I,iterator_from_2d<OL> > {
+ typedef typename std::iterator_traits<I>::difference_type diff_t;
+ GIL_FORCEINLINE void operator()(I src, diff_t n, iterator_from_2d<OL> dst) const {
+ gil_function_requires<PixelIteratorConcept<I> >();
+ gil_function_requires<MutablePixelLocatorConcept<OL> >();
+ while (n>0) {
+ diff_t l=dst.width()-dst.x_pos();
+ diff_t numToCopy=(n<l ? n:l);
+ detail::copy_n(src, numToCopy, dst.x());
+ dst+=numToCopy;
+ src+=numToCopy;
+ n-=numToCopy;
+ }
+ }
+};
+
+/// Both source and destination ranges are delimited by image iterators
+template <typename IL, typename OL>
+struct copier_n<iterator_from_2d<IL>,iterator_from_2d<OL> > {
+ typedef typename iterator_from_2d<IL>::difference_type diff_t;
+ GIL_FORCEINLINE void operator()(iterator_from_2d<IL> src, diff_t n, iterator_from_2d<OL> dst) const {
+ gil_function_requires<PixelLocatorConcept<IL> >();
+ gil_function_requires<MutablePixelLocatorConcept<OL> >();
+ if (src.x_pos()!=dst.x_pos() || src.width()!=dst.width()) {
+ while(n-->0) {
+ *dst++=*src++;
+ }
+ }
+ while (n>0) {
+ diff_t l=dst.width()-dst.x_pos();
+ diff_t numToCopy=(n<l ? n : l);
+ detail::copy_n(src.x(), numToCopy, dst.x());
+ dst+=numToCopy;
+ src+=numToCopy;
+ n-=numToCopy;
+ }
+ }
+};
+
+template <typename SrcIterator, typename DstIterator>
+GIL_FORCEINLINE DstIterator copy_with_2d_iterators(SrcIterator first, SrcIterator last, DstIterator dst) {
+ typedef typename SrcIterator::x_iterator src_x_iterator;
+ typedef typename DstIterator::x_iterator dst_x_iterator;
+
+ typename SrcIterator::difference_type n = last - first;
+
+ if (first.is_1d_traversable()) {
+ if (dst.is_1d_traversable())
+ copier_n<src_x_iterator,dst_x_iterator>()(first.x(),n, dst.x());
+ else
+ copier_n<src_x_iterator,DstIterator >()(first.x(),n, dst);
+ } else {
+ if (dst.is_1d_traversable())
+ copier_n<SrcIterator,dst_x_iterator>()(first,n, dst.x());
+ else
+ copier_n<SrcIterator,DstIterator>()(first,n,dst);
+ }
+ return dst+n;
+}
+
+} // namespace detail
+} } // namespace boost::gil
+
+namespace std {
+/// \ingroup STLOptimizations
+/// \brief std::copy(I1,I1,I2) with I1 and I2 being a iterator_from_2d
+template <typename IL, typename OL>
+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) {
+ return boost::gil::detail::copy_with_2d_iterators(first,last,dst);
+}
+
+} // namespace std
+
+namespace boost { namespace gil {
+
+
+/// \ingroup ImageViewSTLAlgorithmsCopyPixels
+/// \brief std::copy for image views
+template <typename View1, typename View2> GIL_FORCEINLINE
+void copy_pixels(const View1& src, const View2& dst) {
+ assert(src.dimensions()==dst.dimensions());
+ detail::copy_with_2d_iterators(src.begin(),src.end(),dst.begin());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+///
+/// copy_and_convert_pixels
+///
+//////////////////////////////////////////////////////////////////////////////////////
+
+/// \defgroup ImageViewSTLAlgorithmsCopyAndConvertPixels copy_and_convert_pixels
+/// \ingroup ImageViewSTLAlgorithms
+/// \brief copies src view into dst view, color converting if necessary.
+///
+/// Versions taking static and runtime views are provided. Versions taking user-defined color convered are provided.
+
+namespace detail {
+template <typename CC>
+class copy_and_convert_pixels_fn : public binary_operation_obj<copy_and_convert_pixels_fn<CC> > {
+private:
+ CC _cc;
+public:
+ typedef typename binary_operation_obj<copy_and_convert_pixels_fn<CC> >::result_type result_type;
+ copy_and_convert_pixels_fn() {}
+ copy_and_convert_pixels_fn(CC cc_in) : _cc(cc_in) {}
+ // when the two color spaces are incompatible, a color conversion is performed
+ template <typename V1, typename V2> GIL_FORCEINLINE
+ result_type apply_incompatible(const V1& src, const V2& dst) const {
+ copy_pixels(color_converted_view<typename V2::value_type>(src,_cc),dst);
+ }
+
+ // If the two color spaces are compatible, copy_and_convert is just copy
+ template <typename V1, typename V2> GIL_FORCEINLINE
+ result_type apply_compatible(const V1& src, const V2& dst) const {
+ copy_pixels(src,dst);
+ }
+};
+} // namespace detail
+
+/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels
+template <typename V1, typename V2,typename CC>
+GIL_FORCEINLINE
+void copy_and_convert_pixels(const V1& src, const V2& dst,CC cc) {
+ detail::copy_and_convert_pixels_fn<CC> ccp(cc);
+ ccp(src,dst);
+}
+
+struct default_color_converter;
+
+/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels
+template <typename View1, typename View2>
+GIL_FORCEINLINE
+void copy_and_convert_pixels(const View1& src, const View2& dst) {
+ detail::copy_and_convert_pixels_fn<default_color_converter> ccp;
+ ccp(src,dst);
+}
+
+} } // namespace boost::gil
+
+//////////////////////////////////////////////////////////////////////////////////////
+//
+// std::fill and gil::fill_pixels
+//
+//////////////////////////////////////////////////////////////////////////////////////
+
+/// \defgroup ImageViewSTLAlgorithmsFillPixels fill_pixels
+/// \ingroup ImageViewSTLAlgorithms
+/// \brief std::fill for image views
+
+
+namespace std {
+/// \ingroup STLOptimizations
+/// \brief std::fill(I,I,V) with I being a iterator_from_2d
+///
+/// Invoked when one calls std::fill(I,I,V) with I being a iterator_from_2d (which is
+/// a 1D iterator over the pixels in an image). For contiguous images (i.e. images that have
+/// no alignment gap at the end of each row) it is more efficient to use the underlying
+/// pixel iterator that does not check for the end of rows. For non-contiguous images fill
+/// resolves to fill of each row using the underlying pixel iterator, which is still faster
+template <typename IL, typename V>
+void fill(boost::gil::iterator_from_2d<IL> first, boost::gil::iterator_from_2d<IL> last, const V& val) {
+ boost::gil::gil_function_requires<boost::gil::MutablePixelLocatorConcept<IL> >();
+ if (first.is_1d_traversable()) {
+ std::fill(first.x(), last.x(), val);
+ } else {
+ // fill row by row
+ std::ptrdiff_t n=last-first;
+ while (n>0) {
+ std::ptrdiff_t numToDo=std::min<const std::ptrdiff_t>(n,(std::ptrdiff_t)(first.width()-first.x_pos()));
+ fill_n(first.x(), numToDo, val);
+ first+=numToDo;
+ n-=numToDo;
+ }
+ }
+}
+} // namespace std
+
+namespace boost { namespace gil {
+
+namespace detail {
+/// struct to do std::fill
+struct std_fill_t {
+ template <typename It, typename P>
+ void operator()(It first, It last, const P& p_in) {
+ std::fill(first,last,p_in);
+ }
+};
+/// std::fill for planar iterators
+template <typename It, typename P>
+GIL_FORCEINLINE
+void fill_aux(It first, It last, const P& p, mpl::true_) {
+ static_for_each(first,last,p,std_fill_t());
+}
+/// std::fill for interleaved iterators
+template <typename It, typename P>
+GIL_FORCEINLINE
+void fill_aux(It first, It last, const P& p,mpl::false_) {
+ std::fill(first,last,p);
+}
+} // namespace detail
+
+/// \ingroup ImageViewSTLAlgorithmsFillPixels
+/// \brief std::fill for image views
+template <typename View, typename Value> GIL_FORCEINLINE
+void fill_pixels(const View& img_view, const Value& val) {
+ if (img_view.is_1d_traversable())
+ detail::fill_aux(img_view.begin().x(), img_view.end().x(),
+ val,is_planar<View>());
+ else
+ for (std::ptrdiff_t y=0; y<img_view.height(); ++y)
+ detail::fill_aux(img_view.row_begin(y),img_view.row_end(y),
+ val,is_planar<View>());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+///
+/// destruct_pixels
+///
+//////////////////////////////////////////////////////////////////////////////////////
+
+/// \defgroup ImageViewSTLAlgorithmsDestructPixels destruct_pixels
+/// \ingroup ImageViewSTLAlgorithms
+/// \brief invokes the destructor on every pixel of an image view
+
+
+namespace detail {
+
+template <typename It> GIL_FORCEINLINE
+void destruct_range_impl(It first, It last, mpl::true_) {
+ typedef typename std::iterator_traits<It>::value_type value_t;
+ if (boost::has_trivial_destructor<value_t>::value)
+ return;
+ while (first!=last) {
+ first->~value_t();
+ ++first;
+ }
+}
+template <typename It> GIL_FORCEINLINE
+void destruct_range_impl(It, It, mpl::false_) {}
+
+template <typename It> GIL_FORCEINLINE
+void destruct_range(It first, It last) {
+ destruct_range_impl(first,last,typename is_pointer<It>::type());
+}
+
+struct std_destruct_t {
+ template <typename It> void operator()(It first, It last) const { destruct_range(first,last); }
+};
+
+/// destruct for planar iterators
+template <typename It>
+GIL_FORCEINLINE
+void destruct_aux(It first, It last, mpl::true_) {
+ static_for_each(first,last,std_destruct_t());
+}
+/// destruct for interleaved iterators
+template <typename It>
+GIL_FORCEINLINE
+void destruct_aux(It first, It last, mpl::false_) {
+ destruct_range(first,last);
+}
+
+} // namespace detail
+
+/// \ingroup ImageViewSTLAlgorithmsDestructPixels
+/// \brief Invokes the in-place destructor on every pixel of the view
+template <typename View> GIL_FORCEINLINE
+void destruct_pixels(const View& img_view) {
+ // Implementation note:
+ // The 'skip' in/through destruct_aux() is not enough as MSVC++ 10 still
+ // generates code for the bloated img_view.end() call.
+ // (10.10.2010.) (Domagoj Saric)
+ if ( view_is_basic<View>::value )
+ return;
+ if (img_view.is_1d_traversable())
+ detail::destruct_aux(img_view.begin().x(), img_view.end().x(),
+ is_planar<View>());
+ else
+ for (std::ptrdiff_t y=0; y<img_view.height(); ++y)
+ detail::destruct_aux(img_view.row_begin(y),img_view.row_end(y),
+ is_planar<View>());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+///
+/// uninitialized_fill_pixels
+///
+//////////////////////////////////////////////////////////////////////////////////////
+
+/// \defgroup ImageViewSTLAlgorithmsUninitializedFillPixels uninitialized_fill_pixels
+/// \ingroup ImageViewSTLAlgorithms
+/// \brief std::uninitialized_fill for image views
+
+
+namespace detail {
+
+/// std::uninitialized_fill for planar iterators
+/// If an exception is thrown destructs any in-place copy-constructed objects
+template <typename It, typename P>
+GIL_FORCEINLINE
+void uninitialized_fill_aux(It first, It last,
+ const P& p, mpl::true_) {
+ int channel=0;
+ try {
+ typedef typename std::iterator_traits<It>::value_type pixel_t;
+ while (channel < num_channels<pixel_t>::value) {
+ std::uninitialized_fill(dynamic_at_c(first,channel), dynamic_at_c(last,channel),
+ dynamic_at_c(p,channel));
+ ++channel;
+ }
+ } catch (...) {
+ for (int c=0; c<channel; ++c)
+ destruct_range(dynamic_at_c(first,c), dynamic_at_c(last,c));
+ throw;
+ }
+}
+
+/// std::uninitialized_fill for interleaved iterators
+/// If an exception is thrown destructs any in-place copy-constructed objects
+template <typename It, typename P>
+GIL_FORCEINLINE
+void uninitialized_fill_aux(It first, It last,
+ const P& p,mpl::false_) {
+ std::uninitialized_fill(first,last,p);
+}
+
+} // namespace detail
+
+/// \ingroup ImageViewSTLAlgorithmsUninitializedFillPixels
+/// \brief std::uninitialized_fill for image views.
+/// Does not support planar heterogeneous views.
+/// If an exception is thrown destructs any in-place copy-constructed pixels
+template <typename View, typename Value>
+void uninitialized_fill_pixels(const View& img_view, const Value& val) {
+ if (img_view.is_1d_traversable())
+ detail::uninitialized_fill_aux(img_view.begin().x(), img_view.end().x(),
+ val,is_planar<View>());
+ else {
+ typename View::y_coord_t y;
+ try {
+ for (y=0; y<img_view.height(); ++y)
+ detail::uninitialized_fill_aux(img_view.row_begin(y),img_view.row_end(y),
+ val,is_planar<View>());
+ } catch(...) {
+ for (typename View::y_coord_t y0=0; y0<y; ++y0)
+ detail::destruct_aux(img_view.row_begin(y0),img_view.row_end(y0), is_planar<View>());
+ throw;
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+///
+/// default_construct_pixels
+///
+//////////////////////////////////////////////////////////////////////////////////////
+
+/// \defgroup ImageViewSTLAlgorithmsDefaultConstructPixels default_construct_pixels
+/// \ingroup ImageViewSTLAlgorithms
+/// \brief invokes the default constructor on every pixel of an image view
+
+namespace detail {
+
+template <typename It> GIL_FORCEINLINE
+void default_construct_range_impl(It first, It last, mpl::true_) {
+ typedef typename std::iterator_traits<It>::value_type value_t;
+ It first1=first;
+ try {
+ while (first!=last) {
+ new (first) value_t();
+ ++first;
+ }
+ } catch (...) {
+ destruct_range(first1,first);
+ throw;
+ }
+}
+
+template <typename It> GIL_FORCEINLINE
+void default_construct_range_impl(It, It, mpl::false_) {}
+
+template <typename It> GIL_FORCEINLINE
+void default_construct_range(It first, It last) { default_construct_range_impl(first, last, typename is_pointer<It>::type()); }
+
+/// uninitialized_default_construct for planar iterators
+template <typename It>
+GIL_FORCEINLINE
+void default_construct_aux(It first, It last, mpl::true_) {
+ int channel=0;
+ try {
+ typedef typename std::iterator_traits<It>::value_type pixel_t;
+ while (channel < num_channels<pixel_t>::value) {
+ default_construct_range(dynamic_at_c(first,channel), dynamic_at_c(last,channel));
+ ++channel;
+ }
+ } catch (...) {
+ for (int c=0; c<channel; ++c)
+ destruct_range(dynamic_at_c(first,c), dynamic_at_c(last,c));
+ throw;
+ }
+}
+
+/// uninitialized_default_construct for interleaved iterators
+template <typename It>
+GIL_FORCEINLINE
+void default_construct_aux(It first, It last, mpl::false_) {
+ default_construct_range(first,last);
+}
+
+template <typename View, bool IsPlanar>
+struct has_trivial_pixel_constructor : public boost::has_trivial_constructor<typename View::value_type> {};
+template <typename View>
+struct has_trivial_pixel_constructor<View, true> : public boost::has_trivial_constructor<typename channel_type<View>::type> {};
+
+} // namespace detail
+
+/// \ingroup ImageViewSTLAlgorithmsDefaultConstructPixels
+/// \brief 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
+template <typename View>
+void default_construct_pixels(const View& img_view) {
+ if (detail::has_trivial_pixel_constructor<View, is_planar<View>::value>::value)
+ return;
+
+ if (img_view.is_1d_traversable())
+ detail::default_construct_aux(img_view.begin().x(), img_view.end().x(), is_planar<View>());
+ else {
+ typename View::y_coord_t y;
+ try {
+ for (y=0; y<img_view.height(); ++y)
+ detail::default_construct_aux(img_view.row_begin(y),img_view.row_end(y), is_planar<View>());
+ } catch(...) {
+ for (typename View::y_coord_t y0=0; y0<y; ++y0)
+ detail::destruct_aux(img_view.row_begin(y0),img_view.row_end(y0), is_planar<View>());
+ throw;
+ }
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+///
+/// uninitialized_copy_pixels
+///
+//////////////////////////////////////////////////////////////////////////////////////
+
+/// \defgroup ImageViewSTLAlgorithmsUninitializedCopyPixels uninitialized_copy_pixels
+/// \ingroup ImageViewSTLAlgorithms
+/// \brief std::uninitialized_copy for image views
+
+namespace detail {
+
+/// std::uninitialized_copy for pairs of planar iterators
+template <typename It1, typename It2>
+GIL_FORCEINLINE
+void uninitialized_copy_aux(It1 first1, It1 last1,
+ It2 first2, mpl::true_) {
+ int channel=0;
+ try {
+ typedef typename std::iterator_traits<It1>::value_type pixel_t;
+ while (channel < num_channels<pixel_t>::value) {
+ std::uninitialized_copy(dynamic_at_c(first1,channel), dynamic_at_c(last1,channel), dynamic_at_c(first2,channel));
+ ++channel;
+ }
+ } catch (...) {
+ It2 last2=first2;
+ std::advance(last2, std::distance(first1,last1));
+ for (int c=0; c<channel; ++c)
+ destruct_range(dynamic_at_c(first2,c), dynamic_at_c(last2,c));
+ throw;
+ }
+}
+/// std::uninitialized_copy for interleaved or mixed iterators
+template <typename It1, typename It2>
+GIL_FORCEINLINE
+void uninitialized_copy_aux(It1 first1, It1 last1,
+ It2 first2,mpl::false_) {
+ std::uninitialized_copy(first1,last1,first2);
+}
+} // namespace detail
+
+/// \ingroup ImageViewSTLAlgorithmsUninitializedCopyPixels
+/// \brief std::uninitialized_copy for image views.
+/// Does not support planar heterogeneous views.
+/// If an exception is thrown destructs any in-place copy-constructed objects
+template <typename View1, typename View2>
+void uninitialized_copy_pixels(const View1& view1, const View2& view2) {
+ typedef mpl::bool_<is_planar<View1>::value && is_planar<View2>::value> is_planar;
+ assert(view1.dimensions()==view2.dimensions());
+ if (view1.is_1d_traversable() && view2.is_1d_traversable())
+ detail::uninitialized_copy_aux(view1.begin().x(), view1.end().x(),
+ view2.begin().x(),
+ is_planar());
+ else {
+ typename View1::y_coord_t y;
+ try {
+ for (y=0; y<view1.height(); ++y)
+ detail::uninitialized_copy_aux(view1.row_begin(y), view1.row_end(y),
+ view2.row_begin(y),
+ is_planar());
+ } catch(...) {
+ for (typename View1::y_coord_t y0=0; y0<y; ++y0)
+ detail::destruct_aux(view2.row_begin(y0),view2.row_end(y0), is_planar());
+ throw;
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+///
+/// for_each_pixel
+///
+//////////////////////////////////////////////////////////////////////////////////////
+
+/// \defgroup ImageViewSTLAlgorithmsForEachPixel for_each_pixel
+/// \ingroup ImageViewSTLAlgorithms
+/// \brief std::for_each for image views
+///
+/// For contiguous images (i.e. images that have no alignment gap at the end of each row) it is
+/// more efficient to use the underlying pixel iterator that does not check for the end of rows.
+/// For non-contiguous images for_each_pixel resolves to for_each of each row using the underlying
+/// pixel iterator, which is still faster
+
+/// \ingroup ImageViewSTLAlgorithmsForEachPixel
+template <typename V, typename F>
+F for_each_pixel(const V& img, F fun) {
+ typename V::x_iterator begin( img.x_at( 0, 0 ) );
+ typename V::x_iterator const end ( img.x_at( 0, img.height() ) );
+ if ( img.is_1d_traversable() ) {
+ return std::for_each( begin, end, fun );
+ } else {
+ typename V::y_iterator current_row_end( img.col_begin( img.width() ) );
+ while ( begin != end )
+ {
+ fun = std::for_each( begin, current_row_end.base(), fun );
+ memunit_advance( begin, current_row_end.step() );
+ ++current_row_end;
+ }
+ return fun;
+ }
+}
+
+/// \defgroup ImageViewSTLAlgorithmsForEachPixelPosition for_each_pixel_position
+/// \ingroup ImageViewSTLAlgorithms
+/// \brief adobe::for_each_position for image views (passes locators, instead of pixel references, to the function object)
+
+/// \ingroup ImageViewSTLAlgorithmsForEachPixelPosition
+template <typename View, typename F>
+F for_each_pixel_position(const View& img, F fun) {
+ typename View::xy_locator loc=img.xy_at(0,0);
+ for (std::ptrdiff_t y=0; y<img.height(); ++y) {
+ for (std::ptrdiff_t x=0; x<img.width(); ++x, ++loc.x())
+ fun(loc);
+ loc.x()-=img.width(); ++loc.y();
+ }
+ return fun;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+///
+/// generate_pixels
+///
+//////////////////////////////////////////////////////////////////////////////////////
+
+/// \defgroup ImageViewSTLAlgorithmsGeneratePixels generate_pixels
+/// \ingroup ImageViewSTLAlgorithms
+/// \brief std::generate for image views
+
+/// \ingroup ImageViewSTLAlgorithmsGeneratePixels
+/// \brief std::generate for image views
+template <typename View, typename F>
+void generate_pixels(const View& v, F fun) {
+ if (v.is_1d_traversable()) {
+ std::generate(v.begin().x(), v.end().x(), fun);
+ } else {
+ for (std::ptrdiff_t y=0; y<v.height(); ++y)
+ std::generate(v.row_begin(y),v.row_end(y),fun);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+///
+/// std::equal and gil::equal_pixels for GIL constructs
+///
+//////////////////////////////////////////////////////////////////////////////////////
+
+/// \defgroup ImageViewSTLAlgorithmsEqualPixels equal_pixels
+/// \ingroup ImageViewSTLAlgorithms
+/// \brief std::equal for image views
+
+template <typename I1, typename I2> GIL_FORCEINLINE bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2);
+
+namespace detail {
+
+template <typename I1, typename I2>
+struct equal_n_fn {
+ GIL_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, I2 i2) const { return std::equal(i1,i1+n, i2); }
+};
+
+/// Equal when both ranges are interleaved and of the same type.
+/// GIL pixels are bitwise comparable, so memcmp is used. User-defined pixels that are not bitwise comparable need to provide an overload
+template<typename T, typename Cs>
+struct equal_n_fn<const pixel<T,Cs>*, const pixel<T,Cs>*> {
+ GIL_FORCEINLINE bool operator()(const pixel<T,Cs>* i1, std::ptrdiff_t n, const pixel<T,Cs>* i2) const {
+ return memcmp(i1, i2, n*sizeof(pixel<T,Cs>))==0;
+ }
+};
+template<typename T, typename Cs>
+struct equal_n_fn<pixel<T,Cs>*, pixel<T,Cs>*> : equal_n_fn<const pixel<T,Cs>*, const pixel<T,Cs>*> {};
+
+/// EqualPixels
+/// Equal when both ranges are planar pointers of the same type. memcmp is invoked for each channel plane
+/// User-defined channels that are not bitwise comparable need to provide an overload
+template<typename IC, typename Cs>
+struct equal_n_fn<planar_pixel_iterator<IC,Cs>, planar_pixel_iterator<IC,Cs> > {
+ GIL_FORCEINLINE bool operator()(const planar_pixel_iterator<IC,Cs> i1, std::ptrdiff_t n, const planar_pixel_iterator<IC,Cs> i2) const {
+ ptrdiff_t numBytes=n*sizeof(typename std::iterator_traits<IC>::value_type);
+
+ for (std::ptrdiff_t i=0; i<mpl::size<Cs>::value; ++i)
+ if (memcmp(dynamic_at_c(i1,i), dynamic_at_c(i2,i), numBytes)!=0)
+ return false;
+ return true;
+ }
+};
+
+
+/// Source range is delimited by image iterators
+template <typename Loc, typename I2> // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept
+struct equal_n_fn<boost::gil::iterator_from_2d<Loc>,I2> {
+ GIL_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc> i1, std::ptrdiff_t n, I2 i2) const {
+ gil_function_requires<boost::gil::PixelLocatorConcept<Loc> >();
+ gil_function_requires<boost::gil::PixelIteratorConcept<I2> >();
+ while (n>0) {
+ std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n, i1.width()-i1.x_pos());
+ if (!equal_n(i1.x(), num, i2))
+ return false;
+ i1+=num;
+ i2+=num;
+ n-=num;
+ }
+ return true;
+ }
+};
+
+/// Destination range is delimited by image iterators
+template <typename I1, typename Loc> // I Models PixelIteratorConcept, OL Models PixelLocatorConcept
+struct equal_n_fn<I1,boost::gil::iterator_from_2d<Loc> > {
+ GIL_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc> i2) const {
+ gil_function_requires<boost::gil::PixelIteratorConcept<I1> >();
+ gil_function_requires<boost::gil::PixelLocatorConcept<Loc> >();
+ while (n>0) {
+ std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
+ if (!equal_n(i1, num, i2.x()))
+ return false;
+ i1+=num;
+ i2+=num;
+ n-=num;
+ }
+ return true;
+ }
+};
+
+/// Both source and destination ranges are delimited by image iterators
+template <typename Loc1, typename Loc2>
+struct equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2> > {
+ GIL_FORCEINLINE bool operator()(boost::gil::iterator_from_2d<Loc1> i1, std::ptrdiff_t n, boost::gil::iterator_from_2d<Loc2> i2) const {
+ gil_function_requires<boost::gil::PixelLocatorConcept<Loc1> >();
+ gil_function_requires<boost::gil::PixelLocatorConcept<Loc2> >();
+ if (i1.x_pos()!=i2.x_pos() || i1.width()!=i2.width()) {
+ while(n-->0) {
+ if (*i1++!=*i2++) return false;
+ }
+ }
+ while (n>0) {
+ std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
+ if (!equal_n(i1.x(), num, i2.x()))
+ return false;
+ i1+=num;
+ i2+=num;
+ n-=num;
+ }
+ return true;
+ }
+};
+} // namespace detail
+
+template <typename I1, typename I2> GIL_FORCEINLINE
+bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2) {
+ return detail::equal_n_fn<I1,I2>()(i1,n,i2);
+}
+} } // namespace boost::gil
+
+namespace std {
+/// \ingroup STLOptimizations
+/// \brief std::equal(I1,I1,I2) with I1 and I2 being a iterator_from_2d
+///
+/// Invoked when one calls std::equal(I1,I1,I2) with I1 and I2 being a iterator_from_2d (which is
+/// a 1D iterator over the pixels in an image). Attempts to demote the source and destination
+/// iterators to simpler/faster types if the corresponding range is contiguous.
+/// For contiguous images (i.e. images that have
+/// no alignment gap at the end of each row) it is more efficient to use the underlying
+/// pixel iterator that does not check for the end of rows. If the underlying pixel iterator
+/// happens to be a fundamental planar/interleaved pointer, the call may further resolve
+/// to memcmp. Otherwise it resolves to copying each row using the underlying pixel iterator
+template <typename Loc1, typename Loc2> GIL_FORCEINLINE
+bool equal(boost::gil::iterator_from_2d<Loc1> first, boost::gil::iterator_from_2d<Loc1> last, boost::gil::iterator_from_2d<Loc2> first2) {
+ boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc1> >();
+ boost::gil::gil_function_requires<boost::gil::PixelLocatorConcept<Loc2> >();
+ std::ptrdiff_t n=last-first;
+ if (first.is_1d_traversable()) {
+ if (first2.is_1d_traversable())
+ return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,typename Loc2::x_iterator>()(first.x(),n, first2.x());
+ else
+ return boost::gil::detail::equal_n_fn<typename Loc1::x_iterator,boost::gil::iterator_from_2d<Loc2> >()(first.x(),n, first2);
+ } else {
+ if (first2.is_1d_traversable())
+ return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,typename Loc2::x_iterator>()(first,n, first2.x());
+ else
+ return boost::gil::detail::equal_n_fn<boost::gil::iterator_from_2d<Loc1>,boost::gil::iterator_from_2d<Loc2> >()(first,n,first2);
+ }
+}
+} // namespace std
+
+namespace boost { namespace gil {
+
+/// \ingroup ImageViewSTLAlgorithmsEqualPixels
+/// \brief std::equal for image views
+template <typename View1, typename View2> GIL_FORCEINLINE
+bool equal_pixels(const View1& v1, const View2& v2) {
+ assert(v1.dimensions()==v2.dimensions());
+ return std::equal(v1.begin(),v1.end(),v2.begin()); // std::equal has overloads with GIL iterators for optimal performance
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+///
+/// transform_pixels
+///
+//////////////////////////////////////////////////////////////////////////////////////
+
+/// \defgroup ImageViewSTLAlgorithmsTransformPixels transform_pixels
+/// \ingroup ImageViewSTLAlgorithms
+/// \brief std::transform for image views
+
+/// \ingroup ImageViewSTLAlgorithmsTransformPixels
+/// \brief std::transform for image views
+template <typename View1, typename View2, typename F> GIL_FORCEINLINE
+F transform_pixels(const View1& src,const View2& dst, F fun) {
+ assert(src.dimensions()==dst.dimensions());
+ for (std::ptrdiff_t y=0; y<src.height(); ++y) {
+ typename View1::x_iterator srcIt=src.row_begin(y);
+ typename View2::x_iterator dstIt=dst.row_begin(y);
+ for (std::ptrdiff_t x=0; x<src.width(); ++x)
+ dstIt[x]=fun(srcIt[x]);
+ }
+ return fun;
+}
+
+/// \ingroup ImageViewSTLAlgorithmsTransformPixels
+/// \brief transform_pixels with two sources
+template <typename View1, typename View2, typename View3, typename F> GIL_FORCEINLINE
+F transform_pixels(const View1& src1, const View2& src2,const View3& dst, F fun) {
+ for (std::ptrdiff_t y=0; y<dst.height(); ++y) {
+ typename View1::x_iterator srcIt1=src1.row_begin(y);
+ typename View2::x_iterator srcIt2=src2.row_begin(y);
+ typename View3::x_iterator dstIt=dst.row_begin(y);
+ for (std::ptrdiff_t x=0; x<dst.width(); ++x)
+ dstIt[x]=fun(srcIt1[x],srcIt2[x]);
+ }
+ return fun;
+}
+
+/// \defgroup ImageViewSTLAlgorithmsTransformPixelPositions transform_pixel_positions
+/// \ingroup ImageViewSTLAlgorithms
+/// \brief adobe::transform_positions for image views (passes locators, instead of pixel references, to the function object)
+
+/// \ingroup ImageViewSTLAlgorithmsTransformPixelPositions
+/// \brief Like transform_pixels but passes to the function object pixel locators instead of pixel references
+template <typename View1, typename View2, typename F> GIL_FORCEINLINE
+F transform_pixel_positions(const View1& src,const View2& dst, F fun) {
+ assert(src.dimensions()==dst.dimensions());
+ typename View1::xy_locator loc=src.xy_at(0,0);
+ for (std::ptrdiff_t y=0; y<src.height(); ++y) {
+ typename View2::x_iterator dstIt=dst.row_begin(y);
+ for (std::ptrdiff_t x=0; x<src.width(); ++x, ++loc.x())
+ dstIt[x]=fun(loc);
+ loc.x()-=src.width(); ++loc.y();
+ }
+ return fun;
+}
+
+/// \ingroup ImageViewSTLAlgorithmsTransformPixelPositions
+/// \brief transform_pixel_positions with two sources
+template <typename View1, typename View2, typename View3, typename F> GIL_FORCEINLINE
+F transform_pixel_positions(const View1& src1,const View2& src2,const View3& dst, F fun) {
+ assert(src1.dimensions()==dst.dimensions());
+ assert(src2.dimensions()==dst.dimensions());
+ typename View1::xy_locator loc1=src1.xy_at(0,0);
+ typename View2::xy_locator loc2=src2.xy_at(0,0);
+ for (std::ptrdiff_t y=0; y<src1.height(); ++y) {
+ typename View3::x_iterator dstIt=dst.row_begin(y);
+ for (std::ptrdiff_t x=0; x<src1.width(); ++x, ++loc1.x(), ++loc2.x())
+ dstIt[x]=fun(loc1,loc2);
+ loc1.x()-=src1.width(); ++loc1.y();
+ loc2.x()-=src2.width(); ++loc2.y();
+ }
+ return fun;
+}
+
+} } // namespace boost::gil
+
+//#ifdef _MSC_VER
+//#pragma warning(pop)
+//#endif
+
+#endif

Added: sandbox/gil/boost/gil/color_convert.hpp
==============================================================================
--- (empty file)
+++ sandbox/gil/boost/gil/color_convert.hpp 2010-10-10 12:42:02 EDT (Sun, 10 Oct 2010)
@@ -0,0 +1,321 @@
+/*
+ Copyright 2005-2007 Adobe Systems Incorporated
+
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+
+ See http://opensource.adobe.com/gil for most recent version including documentation.
+*/
+/*************************************************************************************************/
+
+#ifndef GIL_COLOR_CONVERT_HPP
+#define GIL_COLOR_CONVERT_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief GIL default color space conversions
+/// \author Lubomir Bourdev and Hailin Jin \n
+/// Adobe Systems Incorporated
+/// \date 2005-2007 \n Last updated on January 30, 2007
+///
+/// Support for fast and simple color conversion. Accurate color conversion using color
+/// profiles can be supplied separately in a dedicated module
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <functional>
+#include "gil_config.hpp"
+#include "channel_algorithm.hpp"
+#include "pixel.hpp"
+#include "gray.hpp"
+#include "rgb.hpp"
+#include "rgba.hpp"
+#include "cmyk.hpp"
+#include "metafunctions.hpp"
+#include "utilities.hpp"
+#include "color_base_algorithm.hpp"
+
+namespace boost { namespace gil {
+
+// Forward-declare
+template <typename P> struct channel_type;
+
+////////////////////////////////////////////////////////////////////////////////////////
+///
+/// COLOR SPACE CONVERSION
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+/// \ingroup ColorConvert
+/// \brief Color Convertion function object. To be specialized for every src/dst color space
+template <typename C1, typename C2>
+struct default_color_converter_impl {};
+
+/// \ingroup ColorConvert
+/// \brief When the color space is the same, color convertion performs channel depth conversion
+template <typename C>
+struct default_color_converter_impl<C,C> {
+ template <typename P1, typename P2>
+ void operator()(const P1& src, P2& dst) const {
+ static_for_each(src,dst,default_channel_converter());
+ }
+};
+
+namespace detail {
+
+/// red * .3 + green * .59 + blue * .11 + .5
+
+// The default implementation of to_luminance uses float0..1 as the intermediate channel type
+template <typename RedChannel, typename GreenChannel, typename BlueChannel, typename GrayChannelValue>
+struct rgb_to_luminance_fn {
+ GrayChannelValue operator()(const RedChannel& red, const GreenChannel& green, const BlueChannel& blue) const {
+ return channel_convert<GrayChannelValue>( bits32f(
+ channel_convert<bits32f>(red )*0.30f +
+ channel_convert<bits32f>(green)*0.59f +
+ channel_convert<bits32f>(blue )*0.11f) );
+ }
+};
+
+// performance specialization for unsigned char
+template <typename GrayChannelValue>
+struct rgb_to_luminance_fn<uint8_t,uint8_t,uint8_t, GrayChannelValue> {
+ GrayChannelValue operator()(uint8_t red, uint8_t green, uint8_t blue) const {
+ return channel_convert<GrayChannelValue>(uint8_t(
+ ((uint32_t(red )*4915 + uint32_t(green)*9667 + uint32_t(blue )*1802) + 8192) >> 14));
+ }
+};
+
+template <typename GrayChannel, typename RedChannel, typename GreenChannel, typename BlueChannel>
+typename channel_traits<GrayChannel>::value_type rgb_to_luminance(const RedChannel& red, const GreenChannel& green, const BlueChannel& blue) {
+ return rgb_to_luminance_fn<RedChannel,GreenChannel,BlueChannel,
+ typename channel_traits<GrayChannel>::value_type>()(red,green,blue);
+}
+
+} // namespace detail
+
+/// \ingroup ColorConvert
+/// \brief Gray to RGB
+template <>
+struct default_color_converter_impl<gray_t,rgb_t> {
+ template <typename P1, typename P2>
+ void operator()(const P1& src, P2& dst) const {
+ get_color(dst,red_t()) =
+ channel_convert<typename color_element_type<P2, red_t >::type>(get_color(src,gray_color_t()));
+ get_color(dst,green_t())=
+ channel_convert<typename color_element_type<P2, green_t>::type>(get_color(src,gray_color_t()));
+ get_color(dst,blue_t()) =
+ channel_convert<typename color_element_type<P2, blue_t >::type>(get_color(src,gray_color_t()));
+ }
+};
+
+/// \ingroup ColorConvert
+/// \brief Gray to CMYK
+template <>
+struct default_color_converter_impl<gray_t,cmyk_t> {
+ template <typename P1, typename P2>
+ void operator()(const P1& src, P2& dst) const {
+ get_color(dst,cyan_t())=
+ channel_traits<typename color_element_type<P2, cyan_t >::type>::min_value();
+ get_color(dst,magenta_t())=
+ channel_traits<typename color_element_type<P2, magenta_t>::type>::min_value();
+ get_color(dst,yellow_t())=
+ channel_traits<typename color_element_type<P2, yellow_t >::type>::min_value();
+ get_color(dst,black_t())=
+ channel_convert<typename color_element_type<P2, black_t >::type>(get_color(src,gray_color_t()));
+ }
+};
+
+/// \ingroup ColorConvert
+/// \brief RGB to Gray
+template <>
+struct default_color_converter_impl<rgb_t,gray_t> {
+ template <typename P1, typename P2>
+ void operator()(const P1& src, P2& dst) const {
+ get_color(dst,gray_color_t()) =
+ detail::rgb_to_luminance<typename color_element_type<P2,gray_color_t>::type>(
+ get_color(src,red_t()), get_color(src,green_t()), get_color(src,blue_t())
+ );
+ }
+};
+
+
+/// \ingroup ColorConvert
+/// \brief RGB to CMYK (not the fastest code in the world)
+///
+/// k = min(1 - r, 1 - g, 1 - b)
+/// c = (1 - r - k) / (1 - k)
+/// m = (1 - g - k) / (1 - k)
+/// y = (1 - b - k) / (1 - k)
+template <>
+struct default_color_converter_impl<rgb_t,cmyk_t> {
+ template <typename P1, typename P2>
+ void operator()(const P1& src, P2& dst) const {
+ typedef typename channel_type<P2>::type T2;
+ get_color(dst,cyan_t()) = channel_invert(channel_convert<T2>(get_color(src,red_t()))); // c = 1 - r
+ get_color(dst,magenta_t()) = channel_invert(channel_convert<T2>(get_color(src,green_t()))); // m = 1 - g
+ get_color(dst,yellow_t()) = channel_invert(channel_convert<T2>(get_color(src,blue_t()))); // y = 1 - b
+ get_color(dst,black_t()) = (std::min)(get_color(dst,cyan_t()),
+ (std::min)(get_color(dst,magenta_t()),
+ get_color(dst,yellow_t()))); // k = minimum(c, m, y)
+ T2 x = channel_traits<T2>::max_value()-get_color(dst,black_t()); // x = 1 - k
+ if (x>0.0001f) {
+ float x1 = channel_traits<T2>::max_value()/float(x);
+ get_color(dst,cyan_t()) = (T2)((get_color(dst,cyan_t()) - get_color(dst,black_t()))*x1); // c = (c - k) / x
+ get_color(dst,magenta_t()) = (T2)((get_color(dst,magenta_t()) - get_color(dst,black_t()))*x1); // m = (m - k) / x
+ get_color(dst,yellow_t()) = (T2)((get_color(dst,yellow_t()) - get_color(dst,black_t()))*x1); // y = (y - k) / x
+ } else {
+ get_color(dst,cyan_t())=get_color(dst,magenta_t())=get_color(dst,yellow_t())=0;
+ }
+ }
+};
+
+/// \ingroup ColorConvert
+/// \brief CMYK to RGB (not the fastest code in the world)
+///
+/// r = 1 - min(1, c*(1-k)+k)
+/// g = 1 - min(1, m*(1-k)+k)
+/// b = 1 - min(1, y*(1-k)+k)
+template <>
+struct default_color_converter_impl<cmyk_t,rgb_t> {
+ template <typename P1, typename P2>
+ void operator()(const P1& src, P2& dst) const {
+ typedef typename channel_type<P1>::type T1;
+ typedef typename mpl::if_
+ <
+ is_integral<T1>,
+ typename detail::min_fast_uint<sizeof( T1 ) * 8 + 1>::type,
+ T1
+ >::type T1_AUX;
+ get_color(dst,red_t()) =
+ channel_convert<typename color_element_type<P2,red_t>::type>
+ (
+ //channel_invert(T1(get_color(src,cyan_t())*channel_invert(get_color(src,black_t()))/channel_traits<T1>::max_value() + get_color(src,black_t())))
+ T1(channel_invert(get_color(src,cyan_t()))*channel_invert(get_color(src,black_t()))/channel_traits<T1>::max_value())
+ );
+ get_color(dst,green_t())=
+ channel_convert<typename color_element_type<P2,green_t>::type>(
+ //channel_invert(T1(get_color(src,magenta_t())*channel_invert(get_color(src,black_t()))/channel_traits<T1>::max_value() + get_color(src,black_t())))
+ T1(channel_invert(get_color(src,magenta_t()))*channel_invert(get_color(src,black_t()))/channel_traits<T1>::max_value())
+ );
+ get_color(dst,blue_t()) =
+ channel_convert<typename color_element_type<P2,blue_t>::type>(
+ //channel_invert(T1(get_color(src,yellow_t())*channel_invert(get_color(src,black_t()))/channel_traits<T1>::max_value() + get_color(src,black_t())))
+ T1(channel_invert(get_color(src,yellow_t()))*channel_invert(get_color(src,black_t()))/channel_traits<T1>::max_value())
+ );
+ }
+};
+
+
+/// \ingroup ColorConvert
+/// \brief CMYK to Gray
+///
+/// gray = (1 - 0.212c - 0.715m - 0.0722y) * (1 - k)
+template <>
+struct default_color_converter_impl<cmyk_t,gray_t> {
+ template <typename P1, typename P2>
+ void operator()(const P1& src, P2& dst) const {
+ get_color(dst,gray_color_t())=
+ channel_convert<typename color_element_type<P2,gray_t>::type>(
+ channel_multiply(
+ channel_invert(
+ detail::rgb_to_luminance<typename color_element_type<P1,black_t>::type>(
+ get_color(src,cyan_t()),
+ get_color(src,magenta_t()),
+ get_color(src,yellow_t())
+ )
+ ),
+ channel_invert(get_color(src,black_t()))));
+ }
+};
+
+namespace detail {
+template <typename Pixel>
+typename channel_type<Pixel>::type alpha_or_max_impl(const Pixel& p, mpl::true_) {
+ return get_color(p,alpha_t());
+}
+template <typename Pixel>
+typename channel_type<Pixel>::type alpha_or_max_impl(const Pixel& , mpl::false_) {
+ return channel_traits<typename channel_type<Pixel>::type>::max_value();
+}
+} // namespace detail
+
+// Returns max_value if the pixel has no alpha channel. Otherwise returns the alpha.
+template <typename Pixel>
+typename channel_type<Pixel>::type alpha_or_max(const Pixel& p) {
+ return detail::alpha_or_max_impl(p, mpl::contains<typename color_space_type<Pixel>::type,alpha_t>());
+}
+
+
+/// \ingroup ColorConvert
+/// \brief Converting any pixel type to RGBA. Note: Supports homogeneous pixels only.
+template <typename C1>
+struct default_color_converter_impl<C1,rgba_t> {
+ template <typename P1, typename P2>
+ void operator()(const P1& src, P2& dst) const {
+ typedef typename channel_type<P2>::type T2;
+ pixel<T2,rgb_layout_t> tmp;
+ default_color_converter_impl<C1,rgb_t>()(src,tmp);
+ get_color(dst,red_t()) =get_color(tmp,red_t());
+ get_color(dst,green_t())=get_color(tmp,green_t());
+ get_color(dst,blue_t()) =get_color(tmp,blue_t());
+ get_color(dst,alpha_t())=channel_convert<T2>(alpha_or_max(src));
+ }
+};
+
+/// \ingroup ColorConvert
+/// \brief Converting RGBA to any pixel type. Note: Supports homogeneous pixels only.
+///
+/// Done by multiplying the alpha to get to RGB, then converting the RGB to the target pixel type
+/// Note: This may be slower if the compiler doesn't optimize out constructing/destructing a temporary RGB pixel.
+/// Consider rewriting if performance is an issue
+template <typename C2>
+struct default_color_converter_impl<rgba_t,C2> {
+ template <typename P1, typename P2>
+ void operator()(const P1& src, P2& dst) const {
+ typedef typename channel_type<P1>::type T1;
+ default_color_converter_impl<rgb_t,C2>()(
+ pixel<T1,rgb_layout_t>(channel_multiply(get_color(src,red_t()), get_color(src,alpha_t())),
+ channel_multiply(get_color(src,green_t()),get_color(src,alpha_t())),
+ channel_multiply(get_color(src,blue_t()), get_color(src,alpha_t())))
+ ,dst);
+ }
+};
+
+/// \ingroup ColorConvert
+/// \brief Unfortunately RGBA to RGBA must be explicitly provided - otherwise we get ambiguous specialization error.
+template <>
+struct default_color_converter_impl<rgba_t,rgba_t> {
+ template <typename P1, typename P2>
+ void operator()(const P1& src, P2& dst) const {
+ static_for_each(src,dst,default_channel_converter());
+ }
+};
+
+/// @defgroup ColorConvert Color Space Converion
+/// \ingroup ColorSpaces
+/// \brief Support for conversion between pixels of different color spaces and channel depths
+
+/// \ingroup PixelAlgorithm ColorConvert
+/// \brief class for color-converting one pixel to another
+struct default_color_converter {
+ template <typename SrcP, typename DstP>
+ void operator()(const SrcP& src,DstP& dst) const {
+ typedef typename color_space_type<SrcP>::type SrcColorSpace;
+ typedef typename color_space_type<DstP>::type DstColorSpace;
+ default_color_converter_impl<SrcColorSpace,DstColorSpace>()(src,dst);
+ }
+};
+
+/// \ingroup PixelAlgorithm
+/// \brief helper function for converting one pixel to another using GIL default color-converters
+/// where ScrP models HomogeneousPixelConcept
+/// DstP models HomogeneousPixelValueConcept
+template <typename SrcP, typename DstP>
+inline void color_convert(const SrcP& src, DstP& dst) {
+ default_color_converter()(src,dst);
+}
+
+} } // namespace boost::gil
+
+#endif

Added: sandbox/gil/boost/gil/image.hpp
==============================================================================
--- (empty file)
+++ sandbox/gil/boost/gil/image.hpp 2010-10-10 12:42:02 EDT (Sun, 10 Oct 2010)
@@ -0,0 +1,312 @@
+/*
+ Copyright 2005-2007 Adobe Systems Incorporated
+
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+
+ See http://opensource.adobe.com/gil for most recent version including documentation.
+*/
+/*************************************************************************************************/
+
+#ifndef GIL_IMAGE_H
+#define GIL_IMAGE_H
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief Templated image
+/// \author Lubomir Bourdev and Hailin Jin \n
+/// Adobe Systems Incorporated
+/// \date 2005-2007 \n Last updated on February 12, 2007
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <cstddef>
+#include <memory>
+#include "gil_config.hpp"
+#include "image_view.hpp"
+#include "metafunctions.hpp"
+#include "algorithm.hpp"
+
+namespace boost { namespace gil {
+
+//#ifdef _MSC_VER
+//#pragma warning(push)
+//#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)
+//#endif
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \ingroup ImageModel PixelBasedModel
+/// \brief container interface over image view. Models ImageConcept, PixelBasedConcept
+///
+/// A 2D container whose elements are pixels. It is templated over the pixel type, a boolean
+/// indicating whether it should be planar, and an optional allocator.
+///
+/// Note that its element type does not have to be a pixel. \p image can be instantiated with any Regular element,
+/// in which case it models the weaker RandomAccess2DImageConcept and does not model PixelBasedConcept
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+template< typename Pixel, bool IsPlanar = false, typename Alloc=std::allocator<unsigned char> >
+class image {
+public:
+ typedef typename Alloc::template rebind<unsigned char>::other allocator_type;
+ typedef typename view_type_from_pixel<Pixel, IsPlanar>::type view_t;
+ typedef typename view_t::const_t const_view_t;
+ typedef typename view_t::point_t point_t;
+ typedef typename view_t::coord_t coord_t;
+ typedef typename view_t::value_type value_type;
+ typedef coord_t x_coord_t;
+ typedef coord_t y_coord_t;
+
+ const point_t& dimensions() const { return _view.dimensions(); }
+ x_coord_t width() const { return _view.width(); }
+ y_coord_t height() const { return _view.height(); }
+
+ explicit image(std::size_t alignment=0,
+ const Alloc alloc_in = Alloc()) :
+ _memory(0), _align_in_bytes(alignment), _alloc(alloc_in) {}
+
+ // Create with dimensions and optional initial value and alignment
+ image(const point_t& dimensions,
+ std::size_t alignment=0,
+ const Alloc alloc_in = Alloc()) : _memory(0), _align_in_bytes(alignment), _alloc(alloc_in) {
+ allocate_and_default_construct(dimensions);
+ }
+ image(x_coord_t width, y_coord_t height,
+ std::size_t alignment=0,
+ const Alloc alloc_in = Alloc()) : _memory(0), _align_in_bytes(alignment), _alloc(alloc_in) {
+ allocate_and_default_construct(point_t(width,height));
+ }
+ image(const point_t& dimensions,
+ const Pixel& p_in,
+ std::size_t alignment,
+ const Alloc alloc_in = Alloc()) :
+ _memory(0), _align_in_bytes(alignment), _alloc(alloc_in) {
+ allocate_and_fill(dimensions, p_in);
+ }
+ image(x_coord_t width, y_coord_t height,
+ const Pixel& p_in,
+ std::size_t alignment,
+ const Alloc alloc_in = Alloc()) :
+ _memory(0), _align_in_bytes(alignment), _alloc(alloc_in) {
+ allocate_and_fill(point_t(width,height),p_in);
+ }
+
+ image(const image& img) :
+ _memory(0), _align_in_bytes(img._align_in_bytes), _alloc(img._alloc) {
+ allocate_and_copy(img.dimensions(),img._view);
+ }
+
+ template <typename P2, bool IP2, typename Alloc2>
+ image(const image<P2,IP2,Alloc2>& img) :
+ _memory(0), _align_in_bytes(img._align_in_bytes), _alloc(img._alloc) {
+ allocate_and_copy(img.dimensions(),img._view);
+ }
+ image& operator=(const image& img) {
+ if (dimensions() == img.dimensions())
+ copy_pixels(img._view,_view);
+ else {
+ image tmp(img);
+ swap(tmp);
+ }
+ return *this;
+ }
+
+ template <typename Img>
+ image& operator=(const Img& img) {
+ if (dimensions() == img.dimensions())
+ copy_pixels(img._view,_view);
+ else {
+ image tmp(img);
+ swap(tmp);
+ }
+ return *this;
+ }
+
+ ~image() {
+ destruct_pixels(_view);
+ deallocate(_view.dimensions());
+ }
+
+ Alloc& allocator() { return _alloc; }
+ Alloc const& allocator() const { return _alloc; }
+
+ void swap(image& img) { // required by MutableContainerConcept
+ using std::swap;
+ swap(_align_in_bytes, img._align_in_bytes);
+ swap(_memory, img._memory);
+ swap(_view, img._view);
+ swap(_alloc, img._alloc);
+ }
+
+ void recreate(const point_t& dims, std::size_t alignment=0, const Alloc alloc_in = Alloc()) {
+ if (dims!=_view.dimensions() || _align_in_bytes!=alignment || alloc_in!=_alloc) {
+ image tmp(dims, alignment, alloc_in);
+ swap(tmp);
+ }
+ }
+ void recreate(x_coord_t width, y_coord_t height, std::size_t alignment=0, const Alloc alloc_in = Alloc()) {
+ recreate(point_t(width,height),alignment,alloc_in);
+ }
+ void recreate(const point_t& dims,
+ const Pixel& p_in, std::size_t alignment, const Alloc alloc_in = Alloc()) {
+ if (dims!=_view.dimensions() || _align_in_bytes!=alignment || alloc_in!=_alloc) {
+ image tmp(dims, p_in, alignment, alloc_in);
+ swap(tmp);
+ }
+ }
+ void recreate(x_coord_t width, y_coord_t height,
+ const Pixel& p_in, std::size_t alignment, const Alloc alloc_in = Alloc()) {
+ recreate(point_t(width,height),p_in,alignment,alloc_in);
+ }
+
+ view_t _view; // contains pointer to the pixels, the image size and ways to navigate pixels
+private:
+ unsigned char* _memory;
+ std::size_t _align_in_bytes;
+ allocator_type _alloc;
+
+ void allocate_and_default_construct(const point_t& dimensions) {
+ try {
+ allocate_(dimensions,mpl::bool_<IsPlanar>());
+ // Implementation note:
+ // The 'skip' in/through default_construct_pixels() is not enough
+ // as MSVC++ 10 is unable to inline functions with try-catch blocks.
+ // (10.10.2010.) (Domagoj Saric)
+ if (!detail::has_trivial_pixel_constructor<view_t, is_planar<view_t>::value>::value)
+ default_construct_pixels(_view);
+ } catch(...) {
+ __assume
+ (
+ !view_is_basic<view_t> ::value &&
+ !detail::has_trivial_pixel_constructor<view_t, is_planar<view_t>::value>::value
+ );
+ deallocate(dimensions);
+ throw;
+ }
+ }
+
+ void allocate_and_fill(const point_t& dimensions, const Pixel& p_in) {
+ try {
+ allocate_(dimensions,mpl::bool_<IsPlanar>());
+ uninitialized_fill_pixels(_view, p_in);
+ } catch(...) { deallocate(dimensions); throw; }
+ }
+
+ template <typename View>
+ void allocate_and_copy(const point_t& dimensions, const View& v) {
+ try {
+ allocate_(dimensions,mpl::bool_<IsPlanar>());
+ uninitialized_copy_pixels(v,_view);
+ } catch(...) { deallocate(dimensions); throw; }
+ }
+
+ void deallocate(const point_t& dimensions) {
+ if (_memory) _alloc.deallocate(_memory, total_allocated_size_in_bytes(dimensions));
+ }
+
+ std::size_t total_allocated_size_in_bytes(const point_t& dimensions) const {
+
+ typedef typename view_t::x_iterator x_iterator;
+
+ // when value_type is a non-pixel, like int or float, num_channels< ... > doesn't work.
+ const std::size_t _channels_in_image = mpl::eval_if< is_pixel< value_type >
+ , num_channels< view_t >
+ , mpl::int_< 1 >
+ >::type::value;
+
+ std::size_t size_in_units = get_row_size_in_memunits(dimensions.x)*dimensions.y;
+
+ if (IsPlanar)
+ size_in_units = size_in_units * _channels_in_image ;
+
+ // return the size rounded up to the nearest byte
+ return ( size_in_units + byte_to_memunit< x_iterator >::value - 1 )
+ / byte_to_memunit<x_iterator>::value
+ + ( _align_in_bytes > 0 ? _align_in_bytes - 1 : 0 ); // add extra padding in case we need to align the first image pixel
+ }
+
+ std::size_t get_row_size_in_memunits(x_coord_t width) const { // number of units per row
+ std::size_t size_in_memunits = width*memunit_step(typename view_t::x_iterator());
+ if (_align_in_bytes>0) {
+ std::size_t alignment_in_memunits=_align_in_bytes*byte_to_memunit<typename view_t::x_iterator>::value;
+ return align(size_in_memunits, alignment_in_memunits);
+ }
+ return size_in_memunits;
+ }
+
+ void allocate_(const point_t& dimensions, mpl::false_) { // if it throws and _memory!=0 the client must deallocate _memory
+ _memory=_alloc.allocate(total_allocated_size_in_bytes(dimensions));
+ unsigned char* tmp=(_align_in_bytes>0) ? (unsigned char*)align((std::size_t)_memory,_align_in_bytes) : _memory;
+ _view=view_t(dimensions,typename view_t::locator(typename view_t::x_iterator(tmp),get_row_size_in_memunits(dimensions.x)));
+ }
+
+ void allocate_(const point_t& dimensions, mpl::true_) { // if it throws and _memory!=0 the client must deallocate _memory
+ std::size_t row_size=get_row_size_in_memunits(dimensions.x);
+ std::size_t plane_size=row_size*dimensions.y;
+ _memory=_alloc.allocate(total_allocated_size_in_bytes(dimensions));
+ unsigned char* tmp=(_align_in_bytes>0) ? (unsigned char*)align((std::size_t)_memory,_align_in_bytes) : _memory;
+ typename view_t::x_iterator first;
+ for (int i=0; i<num_channels<view_t>::value; ++i) {
+ dynamic_at_c(first,i) = (typename channel_type<view_t>::type*)tmp;
+ memunit_advance(dynamic_at_c(first,i), plane_size*i);
+ }
+ _view=view_t(dimensions, typename view_t::locator(first, row_size));
+ }
+};
+
+template <typename Pixel, bool IsPlanar, typename Alloc>
+void swap(image<Pixel, IsPlanar, Alloc>& im1,image<Pixel, IsPlanar, Alloc>& im2) {
+ im1.swap(im2);
+}
+
+template <typename Pixel1, bool IsPlanar1, typename Alloc1, typename Pixel2, bool IsPlanar2, typename Alloc2>
+bool operator==(const image<Pixel1,IsPlanar1,Alloc1>& im1,const image<Pixel2,IsPlanar2,Alloc2>& im2) {
+ if ((void*)(&im1)==(void*)(&im2)) return true;
+ if (const_view(im1).dimensions()!=const_view(im2).dimensions()) return false;
+ return equal_pixels(const_view(im1),const_view(im2));
+}
+template <typename Pixel1, bool IsPlanar1, typename Alloc1, typename Pixel2, bool IsPlanar2, typename Alloc2>
+bool operator!=(const image<Pixel1,IsPlanar1,Alloc1>& im1,const image<Pixel2,IsPlanar2,Alloc2>& im2) {return !(im1==im2);}
+
+///@{
+/// \name view, const_view
+/// \brief Get an image view from an image
+
+/// \ingroup ImageModel
+
+/// \brief Returns the non-constant-pixel view of an image
+template <typename Pixel, bool IsPlanar, typename Alloc> inline
+const typename image<Pixel,IsPlanar,Alloc>::view_t& view(image<Pixel,IsPlanar,Alloc>& img) { return img._view; }
+
+/// \brief Returns the constant-pixel view of an image
+template <typename Pixel, bool IsPlanar, typename Alloc> inline
+const typename image<Pixel,IsPlanar,Alloc>::const_view_t const_view(const image<Pixel,IsPlanar,Alloc>& img) {
+ return static_cast<const typename image<Pixel,IsPlanar,Alloc>::const_view_t>(img._view);
+}
+///@}
+
+/////////////////////////////
+// PixelBasedConcept
+/////////////////////////////
+
+template <typename Pixel, bool IsPlanar, typename Alloc>
+struct channel_type<image<Pixel,IsPlanar,Alloc> > : public channel_type<Pixel> {};
+
+template <typename Pixel, bool IsPlanar, typename Alloc>
+struct color_space_type<image<Pixel,IsPlanar,Alloc> > : public color_space_type<Pixel> {};
+
+template <typename Pixel, bool IsPlanar, typename Alloc>
+struct channel_mapping_type<image<Pixel,IsPlanar,Alloc> > : public channel_mapping_type<Pixel> {};
+
+template <typename Pixel, bool IsPlanar, typename Alloc>
+struct is_planar<image<Pixel,IsPlanar,Alloc> > : public mpl::bool_<IsPlanar> {};
+
+//#ifdef _MSC_VER
+//#pragma warning(pop)
+//#endif
+
+} } // namespace boost::gil
+
+#endif

Added: sandbox/gil/boost/gil/locator.hpp
==============================================================================
--- (empty file)
+++ sandbox/gil/boost/gil/locator.hpp 2010-10-10 12:42:02 EDT (Sun, 10 Oct 2010)
@@ -0,0 +1,395 @@
+/*
+ Copyright 2005-2007 Adobe Systems Incorporated
+
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+
+ See http://opensource.adobe.com/gil for most recent version including documentation.
+*/
+
+/*************************************************************************************************/
+
+#ifndef GIL_LOCATOR_H
+#define GIL_LOCATOR_H
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief pixel 2D locator
+/// \author Lubomir Bourdev and Hailin Jin \n
+/// Adobe Systems Incorporated
+/// \date 2005-2007 \n September 20, 2006
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <cstddef>
+#include <cassert>
+#include "pixel_iterator.hpp"
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// Pixel 2D LOCATOR
+////////////////////////////////////////////////////////////////////////////////////////
+
+
+namespace boost { namespace gil {
+
+//forward declarations
+template <typename P> ptrdiff_t memunit_step(const P*);
+template <typename P> P* memunit_advanced(const P* p, ptrdiff_t diff);
+template <typename P> P& memunit_advanced_ref(P* p, ptrdiff_t diff);
+template <typename Iterator, typename D> struct iterator_add_deref;
+template <typename T> class point2;
+namespace detail {
+ // helper class specialized for each axis of pixel_2d_locator
+ template <std::size_t D, typename Loc> class locator_axis;
+}
+template <typename T> struct dynamic_x_step_type;
+template <typename T> struct dynamic_y_step_type;
+
+template <typename T> struct channel_type;
+template <typename T> struct color_space_type;
+template <typename T> struct channel_mapping_type;
+template <typename T> struct is_planar;
+template <typename T> struct num_channels;
+
+// The type of a locator or a view that has X and Y swapped. By default it is the same
+template <typename T> struct transposed_type {
+ typedef T type;
+};
+
+/// \class pixel_2d_locator_base
+/// \brief base class for models of PixelLocatorConcept
+/// \ingroup PixelLocatorModel PixelBasedModel
+///
+/// Pixel locator is similar to a pixel iterator, but allows for 2D navigation of pixels within an image view.
+/// It has a 2D difference_type and supports random access operations like:
+/// \code
+/// difference_type offset2(2,3);
+/// locator+=offset2;
+/// locator[offset2]=my_pixel;
+/// \endcode
+///
+/// In addition, each coordinate acts as a random-access iterator that can be modified separately:
+/// "++locator.x()" or "locator.y()+=10" thereby moving the locator horizontally or vertically.
+///
+/// It is called a locator because it doesn't implement the complete interface of a random access iterator.
+/// For example, increment and decrement operations don't make sense (no way to specify dimension).
+/// Also 2D difference between two locators cannot be computed without knowledge of the X position within the image.
+///
+/// This base class provides most of the methods and typedefs needed to create a model of a locator. GIL provides two
+/// locator models as subclasses of \p pixel_2d_locator_base. A memory-based locator, \p memory_based_2d_locator and a virtual
+/// locator, \p virtual_2d_locator.
+/// The minimum functionality a subclass must provide is this:
+/// \code
+/// class my_locator : public pixel_2d_locator_base<my_locator, ..., ...> { // supply the types for x-iterator and y-iterator
+/// typedef ... const_t; // read-only locator
+///
+/// template <typename Deref> struct add_deref {
+/// typedef ... type; // locator that invokes the Deref dereference object upon pixel access
+/// static type make(const my_locator& loc, const Deref& d);
+/// };
+///
+/// my_locator();
+/// my_locator(const my_locator& pl);
+///
+/// // constructors with dynamic step in y (and x). Only valid for locators with dynamic steps
+/// my_locator(const my_locator& loc, coord_t y_step);
+/// my_locator(const my_locator& loc, coord_t x_step, coord_t y_step, bool transpose);
+///
+/// bool operator==(const my_locator& p) const;
+///
+/// // return _references_ to horizontal/vertical iterators. Advancing them moves this locator
+/// x_iterator& x();
+/// y_iterator& y();
+/// x_iterator const& x() const;
+/// y_iterator const& y() const;
+///
+/// // return the vertical distance to another locator. Some models need the horizontal distance to compute it
+/// y_coord_t y_distance_to(const my_locator& loc2, x_coord_t xDiff) const;
+///
+/// // return true iff incrementing an x-iterator located at the last column will position it at the first
+/// // column of the next row. Some models need the image width to determine that.
+/// bool is_1d_traversable(x_coord_t width) const;
+/// };
+/// \endcode
+///
+/// Models may choose to override some of the functions in the base class with more efficient versions.
+///
+
+template <typename Loc, typename XIterator, typename YIterator> // The concrete subclass, the X-iterator and the Y-iterator
+class pixel_2d_locator_base {
+public:
+ typedef XIterator x_iterator;
+ typedef YIterator y_iterator;
+
+ // typedefs required by ConstRandomAccessNDLocatorConcept
+ static const std::size_t num_dimensions=2;
+ typedef typename std::iterator_traits<x_iterator>::value_type value_type;
+ typedef typename std::iterator_traits<x_iterator>::reference reference; // result of dereferencing
+ typedef typename std::iterator_traits<x_iterator>::difference_type coord_t; // 1D difference type (same for all dimensions)
+ typedef point2<coord_t> difference_type; // result of operator-(locator,locator)
+ typedef difference_type point_t;
+ template <std::size_t D> struct axis {
+ typedef typename detail::locator_axis<D,Loc>::coord_t coord_t;
+ typedef typename detail::locator_axis<D,Loc>::iterator iterator;
+ };
+
+// typedefs required by ConstRandomAccess2DLocatorConcept
+ typedef typename point_t::template axis<0>::coord_t x_coord_t;
+ typedef typename point_t::template axis<1>::coord_t y_coord_t;
+
+ bool operator!=(const Loc& p) const { return !(concrete()==p); }
+
+ x_iterator x_at(x_coord_t dx, y_coord_t dy) const { Loc tmp=concrete(); tmp+=point_t(dx,dy); return tmp.x(); }
+ x_iterator x_at(const difference_type& d) const { Loc tmp=concrete(); tmp+=d; return tmp.x(); }
+ y_iterator y_at(x_coord_t dx, y_coord_t dy) const { Loc tmp=concrete(); tmp+=point_t(dx,dy); return tmp.y(); }
+ y_iterator y_at(const difference_type& d) const { Loc tmp=concrete(); tmp+=d; return tmp.y(); }
+ Loc xy_at(x_coord_t dx, y_coord_t dy) const { Loc tmp=concrete(); tmp+=point_t(dx,dy); return tmp; }
+ Loc xy_at(const difference_type& d) const { Loc tmp=concrete(); tmp+=d; return tmp; }
+
+ template <std::size_t D> typename axis<D>::iterator& axis_iterator() { return detail::locator_axis<D,Loc>()(concrete()); }
+ template <std::size_t D> typename axis<D>::iterator const& axis_iterator() const { return detail::locator_axis<D,Loc>()(concrete()); }
+ template <std::size_t D> typename axis<D>::iterator axis_iterator(const point_t& p) const { return detail::locator_axis<D,Loc>()(concrete(),p); }
+
+ reference operator()(x_coord_t dx, y_coord_t dy) const { return *x_at(dx,dy); }
+ reference operator[](const difference_type& d) const { return *x_at(d.x,d.y); }
+
+ reference operator*() const { return *concrete().x(); }
+
+ Loc& operator+=(const difference_type& d) { concrete().x()+=d.x; concrete().y()+=d.y; return concrete(); }
+ Loc& operator-=(const difference_type& d) { concrete().x()-=d.x; concrete().y()-=d.y; return concrete(); }
+
+ Loc operator+(const difference_type& d) const { return xy_at(d); }
+ Loc operator-(const difference_type& d) const { return xy_at(-d); }
+
+ // Some locators can cache 2D coordinates for faster subsequent access. By default there is no caching
+ typedef difference_type cached_location_t;
+ cached_location_t cache_location(const difference_type& d) const { return d; }
+ cached_location_t cache_location(x_coord_t dx, y_coord_t dy)const { return difference_type(dx,dy); }
+
+private:
+ Loc& concrete() { return (Loc&)*this; }
+ const Loc& concrete() const { return (const Loc&)*this; }
+
+ template <typename X> friend class pixel_2d_locator;
+};
+
+// helper classes for each axis of pixel_2d_locator_base
+namespace detail {
+ template <typename Loc>
+ class locator_axis<0,Loc> {
+ typedef typename Loc::point_t point_t;
+ public:
+ typedef typename point_t::template axis<0>::coord_t coord_t;
+ typedef typename Loc::x_iterator iterator;
+
+ inline iterator& operator()( Loc& loc) const { return loc.x(); }
+ inline iterator const& operator()(const Loc& loc) const { return loc.x(); }
+ inline iterator operator()( Loc& loc, const point_t& d) const { return loc.x_at(d); }
+ inline iterator operator()(const Loc& loc, const point_t& d) const { return loc.x_at(d); }
+ };
+
+ template <typename Loc>
+ class locator_axis<1,Loc> {
+ typedef typename Loc::point_t point_t;
+ public:
+ typedef typename point_t::template axis<1>::coord_t coord_t;
+ typedef typename Loc::y_iterator iterator;
+
+ inline iterator& operator()( Loc& loc) const { return loc.y(); }
+ inline iterator const& operator()(const Loc& loc) const { return loc.y(); }
+ inline iterator operator()( Loc& loc, const point_t& d) const { return loc.y_at(d); }
+ inline iterator operator()(const Loc& loc, const point_t& d) const { return loc.y_at(d); }
+ };
+}
+
+template <typename Loc, typename XIt, typename YIt>
+struct channel_type<pixel_2d_locator_base<Loc,XIt,YIt> > : public channel_type<XIt> {};
+
+template <typename Loc, typename XIt, typename YIt>
+struct color_space_type<pixel_2d_locator_base<Loc,XIt,YIt> > : public color_space_type<XIt> {};
+
+template <typename Loc, typename XIt, typename YIt>
+struct channel_mapping_type<pixel_2d_locator_base<Loc,XIt,YIt> > : public channel_mapping_type<XIt> {};
+
+template <typename Loc, typename XIt, typename YIt>
+struct is_planar<pixel_2d_locator_base<Loc,XIt,YIt> > : public is_planar<XIt> {};
+
+/// \class memory_based_2d_locator
+/// \brief Memory-based pixel locator. Models: PixelLocatorConcept,HasDynamicXStepTypeConcept,HasDynamicYStepTypeConcept,HasTransposedTypeConcept
+/// \ingroup PixelLocatorModel PixelBasedModel
+///
+/// The class takes a step iterator as a parameter. The step iterator provides navigation along the vertical axis
+/// while its base iterator provides horizontal navigation.
+///
+/// Each instantiation is optimal in terms of size and efficiency.
+/// For example, xy locator over interleaved rgb image results in a step iterator consisting of
+/// one std::ptrdiff_t for the row size and one native pointer (8 bytes total). ++locator.x() resolves to pointer
+/// increment. At the other extreme, a 2D navigation of the even pixels of a planar CMYK image results in a step
+/// iterator consisting of one std::ptrdiff_t for the doubled row size, and one step iterator consisting of
+/// one std::ptrdiff_t for the horizontal step of two and a CMYK planar_pixel_iterator consisting of 4 pointers (24 bytes).
+/// In this case ++locator.x() results in four native pointer additions.
+///
+/// Note also that \p memory_based_2d_locator does not require that its element type be a pixel. It could be
+/// instantiated with an iterator whose \p value_type models only \p Regular. In this case the locator
+/// models the weaker RandomAccess2DLocatorConcept, and does not model PixelBasedConcept.
+/// Many generic algorithms don't require the elements to be pixels.
+////////////////////////////////////////////////////////////////////////////////////////
+
+template <typename StepIterator>
+class memory_based_2d_locator : public pixel_2d_locator_base<memory_based_2d_locator<StepIterator>, typename iterator_adaptor_get_base<StepIterator>::type, StepIterator> {
+ typedef memory_based_2d_locator<StepIterator> this_t;
+ GIL_CLASS_REQUIRE(StepIterator, boost::gil, StepIteratorConcept)
+public:
+ typedef pixel_2d_locator_base<memory_based_2d_locator<StepIterator>, typename iterator_adaptor_get_base<StepIterator>::type, StepIterator> parent_t;
+ typedef memory_based_2d_locator<typename const_iterator_type<StepIterator>::type> const_t; // same as this type, but over const values
+
+ typedef typename parent_t::coord_t coord_t;
+ typedef typename parent_t::x_coord_t x_coord_t;
+ typedef typename parent_t::y_coord_t y_coord_t;
+ typedef typename parent_t::x_iterator x_iterator;
+ typedef typename parent_t::y_iterator y_iterator;
+ typedef typename parent_t::difference_type difference_type;
+ typedef typename parent_t::reference reference;
+
+ template <typename Deref> struct add_deref {
+ typedef memory_based_2d_locator<typename iterator_add_deref<StepIterator,Deref>::type> type;
+ static type make(const memory_based_2d_locator<StepIterator>& loc, const Deref& nderef) {
+ return type(iterator_add_deref<StepIterator,Deref>::make(loc.y(),nderef));
+ }
+ };
+
+ memory_based_2d_locator() {}
+ memory_based_2d_locator(const StepIterator& yit) : _p(yit) {}
+ template <typename SI> memory_based_2d_locator(const memory_based_2d_locator<SI>& loc, coord_t y_step) : _p(loc.x(), loc.row_size()*y_step) {}
+ template <typename SI> memory_based_2d_locator(const memory_based_2d_locator<SI>& loc, coord_t x_step, coord_t y_step, bool transpose=false)
+ : _p(make_step_iterator(loc.x(),(transpose ? loc.row_size() : loc.pixel_size())*x_step),
+ (transpose ? loc.pixel_size() : loc.row_size())*y_step ) {}
+
+ memory_based_2d_locator(x_iterator xit, std::ptrdiff_t row_bytes) : _p(xit,row_bytes) {}
+ template <typename X> memory_based_2d_locator(const memory_based_2d_locator<X>& pl) : _p(pl._p) {}
+ memory_based_2d_locator(const memory_based_2d_locator& pl) : _p(pl._p) {}
+
+ bool operator==(const this_t& p) const { return _p==p._p; }
+
+ x_iterator const& x() const { return _p.base(); }
+ y_iterator const& y() const { return _p; }
+ x_iterator& x() { return _p.base(); }
+ y_iterator& y() { return _p; }
+
+ // These are faster versions of functions already provided in the superclass
+ x_iterator x_at (x_coord_t dx, y_coord_t dy) const { return memunit_advanced(x(), offset(dx,dy)); }
+ x_iterator x_at (const difference_type& d) const { return memunit_advanced(x(), offset(d.x,d.y)); }
+ this_t xy_at (x_coord_t dx, y_coord_t dy) const { return this_t(x_at( dx , dy ), row_size()); }
+ this_t xy_at (const difference_type& d) const { return this_t(x_at( d.x, d.y), row_size()); }
+ reference operator()(x_coord_t dx, y_coord_t dy) const { return memunit_advanced_ref(x(),offset(dx,dy)); }
+ reference operator[](const difference_type& d) const { return memunit_advanced_ref(x(),offset(d.x,d.y)); }
+ this_t& operator+=(const difference_type& d) { memunit_advance(x(),offset(d.x,d.y)); return *this; }
+ this_t& operator-=(const difference_type& d) { memunit_advance(x(),offset(-d.x,-d.y)); return *this; }
+
+ // Memory-based locators can have 1D caching of 2D relative coordinates
+ typedef std::ptrdiff_t cached_location_t; // type used to store relative location (to allow for more efficient repeated access)
+ cached_location_t cache_location(const difference_type& d) const { return offset(d.x,d.y); }
+ cached_location_t cache_location(x_coord_t dx, y_coord_t dy)const { return offset(dx,dy); }
+ reference operator[](const cached_location_t& loc) const { return memunit_advanced_ref(x(),loc); }
+
+ // Only make sense for memory-based locators
+ std::ptrdiff_t row_size() const { return memunit_step(y()); } // distance in mem units (bytes or bits) between adjacent rows
+ std::ptrdiff_t pixel_size() const { return memunit_step(x()); } // distance in mem units (bytes or bits) between adjacent pixels on the same row
+
+ //bool is_1d_traversable(x_coord_t width) const { return row_size()-pixel_size()*width==0; } // is there no gap at the end of each row?
+ bool is_1d_traversable( x_coord_t const width ) const
+ {
+ /// \todo The ** case might not be safe for algorithms that expect an
+ /// exact number of elements/iterations or are not stable for all input
+ /// values (that might happen at the padding tail at the end of rows) so
+ /// this must be reconsidered and reimplemented.
+ /// (10.10.2010.) (Domagoj Saric)
+ bool const compile_time_detection
+ (
+ ( pixel_size() == 1 ) ||
+ ( pixel_size() % sizeof( void * ) == 0 ) ||
+ ( // ...**...
+ ( pixel_size() % 2 == 0 ) &&
+ ( pixel_size() < sizeof( void * ) )
+ )
+ );
+
+ // Use unsigned division and use 32/16 division to avoid the
+ // unnecessary cdq x86 instruction.
+ //( static_cast<unsigned int>( row_size() * 8 ) % static_cast<unsigned short>( pixel_size() * 8 ) == 0 )
+ bool const run_time_detection
+ (
+ (
+ static_cast<unsigned int >( row_size () )
+ -
+ static_cast<unsigned short>( pixel_size() )
+ *
+ static_cast<unsigned int >( width )
+ ) == 0
+ );
+
+ return compile_time_detection || run_time_detection;
+ }
+
+ // Returns the vertical distance (it2.y-it1.y) between two x_iterators given the difference of their x positions
+ std::ptrdiff_t y_distance_to(const this_t& p2, x_coord_t xDiff) const {
+ std::ptrdiff_t rowDiff=memunit_distance(x(),p2.x())-pixel_size()*xDiff;
+ assert(( rowDiff % row_size())==0);
+ return rowDiff / row_size();
+ }
+
+private:
+ template <typename X> friend class memory_based_2d_locator;
+ std::ptrdiff_t offset(x_coord_t x, y_coord_t y) const { return y*row_size() + x*pixel_size(); }
+ StepIterator _p;
+};
+
+/////////////////////////////
+// PixelBasedConcept
+/////////////////////////////
+
+template <typename SI>
+struct color_space_type<memory_based_2d_locator<SI> > : public color_space_type<typename memory_based_2d_locator<SI>::parent_t> {
+};
+
+template <typename SI>
+struct channel_mapping_type<memory_based_2d_locator<SI> > : public channel_mapping_type<typename memory_based_2d_locator<SI>::parent_t> {
+};
+
+template <typename SI>
+struct is_planar<memory_based_2d_locator<SI> > : public is_planar<typename memory_based_2d_locator<SI>::parent_t> {
+};
+
+template <typename SI>
+struct channel_type<memory_based_2d_locator<SI> > : public channel_type<typename memory_based_2d_locator<SI>::parent_t> {
+};
+
+/////////////////////////////
+// HasDynamicXStepTypeConcept
+/////////////////////////////
+
+// Take the base iterator of SI (which is typically a step iterator) and change it to have a step in x
+template <typename SI>
+struct dynamic_x_step_type<memory_based_2d_locator<SI> > {
+private:
+ typedef typename iterator_adaptor_get_base<SI>::type base_iterator_t;
+ typedef typename dynamic_x_step_type<base_iterator_t>::type base_iterator_step_t;
+ typedef typename iterator_adaptor_rebind<SI, base_iterator_step_t>::type dynamic_step_base_t;
+public:
+ typedef memory_based_2d_locator<dynamic_step_base_t> type;
+};
+
+/////////////////////////////
+// HasDynamicYStepTypeConcept
+/////////////////////////////
+
+template <typename SI>
+struct dynamic_y_step_type<memory_based_2d_locator<SI> > {
+ typedef memory_based_2d_locator<SI> type;
+};
+
+} } // namespace boost::gil
+
+#endif

Added: sandbox/gil/boost/gil/utilities.hpp
==============================================================================
--- (empty file)
+++ sandbox/gil/boost/gil/utilities.hpp 2010-10-10 12:42:02 EDT (Sun, 10 Oct 2010)
@@ -0,0 +1,333 @@
+/*
+ Copyright 2005-2007 Adobe Systems Incorporated
+
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+
+ See http://opensource.adobe.com/gil for most recent version including documentation.
+*/
+
+/*************************************************************************************************/
+
+#ifndef GIL_UTILITIES_H
+#define GIL_UTILITIES_H
+
+#include "gil_config.hpp"
+#include <functional>
+#include <boost/config/no_tr1/cmath.hpp>
+#include <cstddef>
+#include <algorithm>
+#include <utility>
+#include <iterator>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/distance.hpp>
+#include <boost/mpl/begin.hpp>
+#include <boost/mpl/find.hpp>
+#include <boost/mpl/range_c.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief Various utilities not specific to the image library. Some are non-standard STL extensions or generic iterator adaptors
+/// \author Lubomir Bourdev and Hailin Jin \n
+/// Adobe Systems Incorporated
+/// \date 2005-2007 \n Last updated on September 18, 2007
+///
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+namespace boost { namespace gil {
+
+/**
+\addtogroup PointModel
+
+Example:
+\code
+point2<std::ptrdiff_t> p(3,2);
+assert((p[0] == p.x) && (p[1] == p.y));
+assert(axis_value<0>(p) == 3);
+assert(axis_value<1>(p) == 2);
+\endcode
+*/
+
+////////////////////////////////////////////////////////////////////////////////////////
+// CLASS point2
+///
+/// \brief 2D point both axes of which have the same dimension type
+/// \ingroup PointModel
+/// Models: Point2DConcept
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+class point2 {
+public:
+ typedef T value_type;
+ template <std::size_t D> struct axis { typedef value_type coord_t; };
+ static const std::size_t num_dimensions=2;
+
+ point2() : x(0), y(0) {}
+ point2(T newX, T newY) : x(newX), y(newY) {}
+ point2(const point2& p) : x(p.x), y(p.y) {}
+ #ifndef BOOST_MSVC
+ ~point2() {} // This creates (fake) EH states which bug the MSVC++ optimizer...
+ #endif // BOOST_MSVC
+
+ point2& operator=(const point2& p) { x=p.x; y=p.y; return *this; }
+
+ point2 operator<<(std::ptrdiff_t shift) const { return point2(x<<shift,y<<shift); }
+ point2 operator>>(std::ptrdiff_t shift) const { return point2(x>>shift,y>>shift); }
+ point2& operator+=(const point2& p) { x+=p.x; y+=p.y; return *this; }
+ point2& operator-=(const point2& p) { x-=p.x; y-=p.y; return *this; }
+ point2& operator/=(double t) { x/=t; y/=t; return *this; }
+
+ const T& operator[](std::size_t i) const { return this->*mem_array[i]; }
+ T& operator[](std::size_t i) { return this->*mem_array[i]; }
+
+ T x,y;
+private:
+ // this static array of pointers to member variables makes operator[] safe and doesn't seem to exhibit any performance penalty
+ static T point2<T>::* const mem_array[num_dimensions];
+};
+
+template <typename T>
+T point2<T>::* const point2<T>::mem_array[point2<T>::num_dimensions] = { &point2<T>::x, &point2<T>::y };
+
+/// \ingroup PointModel
+template <typename T> GIL_FORCEINLINE
+bool operator==(const point2<T>& p1, const point2<T>& p2) { return (p1.x==p2.x && p1.y==p2.y); }
+/// \ingroup PointModel
+template <typename T> GIL_FORCEINLINE
+bool operator!=(const point2<T>& p1, const point2<T>& p2) { return p1.x!=p2.x || p1.y!=p2.y; }
+/// \ingroup PointModel
+template <typename T> GIL_FORCEINLINE
+point2<T> operator+(const point2<T>& p1, const point2<T>& p2) { return point2<T>(p1.x+p2.x,p1.y+p2.y); }
+/// \ingroup PointModel
+template <typename T> GIL_FORCEINLINE
+point2<T> operator-(const point2<T>& p) { return point2<T>(-p.x,-p.y); }
+/// \ingroup PointModel
+template <typename T> GIL_FORCEINLINE
+point2<T> operator-(const point2<T>& p1, const point2<T>& p2) { return point2<T>(p1.x-p2.x,p1.y-p2.y); }
+/// \ingroup PointModel
+template <typename T> GIL_FORCEINLINE
+point2<double> operator/(const point2<T>& p, double t) { return t==0 ? point2<double>(0,0):point2<double>(p.x/t,p.y/t); }
+/// \ingroup PointModel
+template <typename T> GIL_FORCEINLINE
+point2<T> operator*(const point2<T>& p, std::ptrdiff_t t) { return point2<T>(p.x*t,p.y*t); }
+/// \ingroup PointModel
+template <typename T> GIL_FORCEINLINE
+point2<T> operator*(std::ptrdiff_t t, const point2<T>& p) { return point2<T>(p.x*t,p.y*t); }
+
+/// \ingroup PointModel
+template <std::size_t K, typename T> GIL_FORCEINLINE
+const T& axis_value(const point2<T>& p) { return p[K]; }
+
+/// \ingroup PointModel
+template <std::size_t K, typename T> GIL_FORCEINLINE
+ T& axis_value( point2<T>& p) { return p[K]; }
+
+////////////////////////////////////////////////////////////////////////////////////////
+///
+/// Rounding of real numbers / points to integers / integer points
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+inline std::ptrdiff_t iround(float x ) { return static_cast<std::ptrdiff_t>(x + (x < 0.0f ? -0.5f : 0.5f)); }
+inline std::ptrdiff_t iround(double x) { return static_cast<std::ptrdiff_t>(x + (x < 0.0 ? -0.5 : 0.5)); }
+inline std::ptrdiff_t ifloor(float x ) { return static_cast<std::ptrdiff_t>(std::floor(x)); }
+inline std::ptrdiff_t ifloor(double x) { return static_cast<std::ptrdiff_t>(std::floor(x)); }
+inline std::ptrdiff_t iceil(float x ) { return static_cast<std::ptrdiff_t>(std::ceil(x)); }
+inline std::ptrdiff_t iceil(double x) { return static_cast<std::ptrdiff_t>(std::ceil(x)); }
+
+/**
+\addtogroup PointAlgorithm
+
+Example:
+\code
+assert(iround(point2<double>(3.1, 3.9)) == point2<std::ptrdiff_t>(3,4));
+\endcode
+*/
+
+/// \ingroup PointAlgorithm
+inline point2<std::ptrdiff_t> iround(const point2<float >& p) { return point2<std::ptrdiff_t>(iround(p.x),iround(p.y)); }
+/// \ingroup PointAlgorithm
+inline point2<std::ptrdiff_t> iround(const point2<double>& p) { return point2<std::ptrdiff_t>(iround(p.x),iround(p.y)); }
+/// \ingroup PointAlgorithm
+inline point2<std::ptrdiff_t> ifloor(const point2<float >& p) { return point2<std::ptrdiff_t>(ifloor(p.x),ifloor(p.y)); }
+/// \ingroup PointAlgorithm
+inline point2<std::ptrdiff_t> ifloor(const point2<double>& p) { return point2<std::ptrdiff_t>(ifloor(p.x),ifloor(p.y)); }
+/// \ingroup PointAlgorithm
+inline point2<std::ptrdiff_t> iceil (const point2<float >& p) { return point2<std::ptrdiff_t>(iceil(p.x), iceil(p.y)); }
+/// \ingroup PointAlgorithm
+inline point2<std::ptrdiff_t> iceil (const point2<double>& p) { return point2<std::ptrdiff_t>(iceil(p.x), iceil(p.y)); }
+
+////////////////////////////////////////////////////////////////////////////////////////
+///
+/// computing size with alignment
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+inline T align(T val, std::size_t alignment) {
+ return val+(alignment - val%alignment)%alignment;
+}
+
+/// \brief Helper base class for pixel dereference adaptors.
+/// \ingroup PixelDereferenceAdaptorModel
+///
+template <typename ConstT, typename Value, typename Reference, typename ConstReference,
+ typename ArgType, typename ResultType, bool IsMutable>
+struct deref_base : public std::unary_function<ArgType, ResultType> {
+ typedef ConstT const_t;
+ typedef Value value_type;
+ typedef Reference reference;
+ typedef ConstReference const_reference;
+ BOOST_STATIC_CONSTANT(bool, is_mutable = IsMutable);
+};
+
+/// \brief Composes two dereference function objects. Similar to std::unary_compose but needs to pull some typedefs from the component types. Models: PixelDereferenceAdaptorConcept
+/// \ingroup PixelDereferenceAdaptorModel
+///
+template <typename D1, typename D2>
+class deref_compose : public deref_base<
+ deref_compose<typename D1::const_t, typename D2::const_t>,
+ typename D1::value_type, typename D1::reference, typename D1::const_reference,
+ typename D2::argument_type, typename D1::result_type, D1::is_mutable && D2::is_mutable>
+{
+public:
+ D1 _fn1;
+ D2 _fn2;
+
+ typedef typename D2::argument_type argument_type;
+ typedef typename D1::result_type result_type;
+
+ deref_compose() {}
+ deref_compose(const D1& x, const D2& y) : _fn1(x), _fn2(y) {}
+ deref_compose(const deref_compose& dc) : _fn1(dc._fn1), _fn2(dc._fn2) {}
+ template <typename _D1, typename _D2> deref_compose(const deref_compose<_D1,_D2>& dc) : _fn1(dc._fn1), _fn2(dc._fn2) {}
+
+ result_type operator()(argument_type x) const { return _fn1(_fn2(x)); }
+ result_type operator()(argument_type x) { return _fn1(_fn2(x)); }
+};
+
+// reinterpret_cast is implementation-defined. Static cast is not.
+template <typename OutPtr, typename In> GIL_FORCEINLINE
+ OutPtr gil_reinterpret_cast( In* p) { return static_cast<OutPtr>(static_cast<void*>(p)); }
+
+template <typename OutPtr, typename In> GIL_FORCEINLINE
+const OutPtr gil_reinterpret_cast_c(const In* p) { return static_cast<const OutPtr>(static_cast<const void*>(p)); }
+
+namespace detail {
+
+////////////////////////////////////////////////////////////////////////////////////////
+///
+/// \brief copy_n taken from SGI STL.
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+template <class InputIter, class Size, class OutputIter>
+std::pair<InputIter, OutputIter> _copy_n(InputIter first, Size count,
+ OutputIter result,
+ std::input_iterator_tag) {
+ for ( ; count > 0; --count) {
+ *result = *first;
+ ++first;
+ ++result;
+ }
+ return std::pair<InputIter, OutputIter>(first, result);
+}
+
+template <class RAIter, class Size, class OutputIter>
+inline std::pair<RAIter, OutputIter>
+_copy_n(RAIter first, Size count, OutputIter result, std::random_access_iterator_tag) {
+ RAIter last = first + count;
+ return std::pair<RAIter, OutputIter>(last, std::copy(first, last, result));
+}
+
+template <class InputIter, class Size, class OutputIter>
+inline std::pair<InputIter, OutputIter>
+_copy_n(InputIter first, Size count, OutputIter result) {
+ return _copy_n(first, count, result, typename std::iterator_traits<InputIter>::iterator_category());
+}
+
+template <class InputIter, class Size, class OutputIter>
+inline std::pair<InputIter, OutputIter>
+copy_n(InputIter first, Size count, OutputIter result) {
+ return detail::_copy_n(first, count, result);
+}
+
+/// \brief identity taken from SGI STL.
+template <typename T>
+struct identity : public std::unary_function<T,T> {
+ const T& operator()(const T& val) const { return val; }
+};
+
+/*************************************************************************************************/
+
+/// \brief plus function object whose arguments may be of different type.
+template <typename T1, typename T2>
+struct plus_asymmetric : public std::binary_function<T1,T2,T1> {
+ T1 operator()(T1 f1, T2 f2) const {
+ return f1+f2;
+ }
+};
+
+/*************************************************************************************************/
+
+/// \brief operator++ wrapped in a function object
+template <typename T>
+struct inc : public std::unary_function<T,T> {
+ T operator()(T x) const { return ++x; }
+};
+
+/*************************************************************************************************/
+
+/// \brief operator-- wrapped in a function object
+template <typename T>
+struct dec : public std::unary_function<T,T> {
+ T operator()(T x) const { return --x; }
+};
+
+/// \brief Returns the index corresponding to the first occurrance of a given given type in
+// a given MPL RandomAccessSequence (or size if the type is not present)
+template <typename Types, typename T>
+struct type_to_index
+ : public mpl::distance<typename mpl::begin<Types>::type,
+ typename mpl::find<Types,T>::type>::type {};
+} // namespace detail
+
+
+
+/// \ingroup ColorSpaceAndLayoutModel
+/// \brief Represents a color space and ordering of channels in memory
+template <typename ColorSpace, typename ChannelMapping = mpl::range_c<int,0,mpl::size<ColorSpace>::value> >
+struct layout {
+ typedef ColorSpace color_space_t;
+ typedef ChannelMapping channel_mapping_t;
+};
+
+/// \brief A version of swap that also works with reference proxy objects
+template <typename Value, typename T1, typename T2> // where value_type<T1> == value_type<T2> == Value
+void swap_proxy(T1& left, T2& right) {
+ Value tmp = left;
+ left = right;
+ right = tmp;
+}
+
+/// \brief Run-time detection of whether the underlying architecture is little endian
+inline bool little_endian() {
+ short tester = 0x0001;
+ return *(char*)&tester!=0;
+}
+/// \brief Run-time detection of whether the underlying architecture is big endian
+inline bool big_endian() {
+ return !little_endian();
+}
+
+} } // namespace boost::gil
+
+#endif


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk