From ce31c5ccb7aa4f926e27ab4d66d786e1ba2df2bc Mon Sep 17 00:00:00 2001 From: Christian Henning Date: Sun, 3 Feb 2013 20:13:47 +0000 Subject: [PATCH] #6681 [SVN r82703] --- include/boost/gil/algorithm.hpp | 99 +++++++++++++++++++++++++------- include/boost/gil/color_base.hpp | 8 +++ include/boost/gil/image.hpp | 83 ++++++++++++++++---------- 3 files changed, 138 insertions(+), 52 deletions(-) diff --git a/include/boost/gil/algorithm.hpp b/include/boost/gil/algorithm.hpp index 56a44ab69..292c09a45 100644 --- a/include/boost/gil/algorithm.hpp +++ b/include/boost/gil/algorithm.hpp @@ -21,6 +21,11 @@ #include #include #include + +#include +#include +#include + #include "gil_config.hpp" #include "gil_concept.hpp" #include "color_base_algorithm.hpp" @@ -438,21 +443,35 @@ void fill_pixels(const View& img_view, const Value& val) { namespace detail { template GIL_FORCEINLINE -void destruct_range_impl(It first, It last, mpl::true_) { - typedef typename std::iterator_traits::value_type value_t; - if (boost::has_trivial_destructor::value) - return; +void destruct_range_impl( It first + , It last + , typename enable_if< mpl::and_< is_pointer< It > + , mpl::not_< boost::has_trivial_destructor< typename std::iterator_traits::value_type > > + > + >::type* /*ptr*/ = 0 + ) +{ while (first!=last) { first->~value_t(); ++first; } } + template GIL_FORCEINLINE -void destruct_range_impl(It, It, mpl::false_) {} +void destruct_range_impl( It + , It + , typename enable_if< mpl::or_< mpl::not_< is_pointer< It > > + , boost::has_trivial_destructor< typename std::iterator_traits< It >::value_type > + > + >::type* /* ptr */ = 0) +{} template GIL_FORCEINLINE void destruct_range(It first, It last) { - destruct_range_impl(first,last,typename is_pointer::type()); + + destruct_range_impl( first + , last + ); } struct std_destruct_t { @@ -620,28 +639,66 @@ struct has_trivial_pixel_constructor : public boost::has_trivial_con } // namespace detail +namespace detail { + +template< typename View, bool B > GIL_FORCEINLINE +void default_construct_pixels_impl( const View& img_view + , boost::enable_if< is_same< mpl::bool_< B > + , mpl::false_ + > + >* /* ptr */ = 0 + ) +{ + if( img_view.is_1d_traversable() ) + { + detail::default_construct_aux( img_view.begin().x() + , img_view.end().x() + , is_planar() + ); + } + 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() + ); + } + } 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() + ); + } + + throw; + } + } + +} + +} // 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 void default_construct_pixels(const View& img_view) { - if (detail::has_trivial_pixel_constructor::value>::value) - return; - if (img_view.is_1d_traversable()) - detail::default_construct_aux(img_view.begin().x(), img_view.end().x(), is_planar()); - else { - typename View::y_coord_t y; - try { - for (y=0; y()); - } catch(...) { - for (typename View::y_coord_t y0=0; y0()); - throw; - } - } + detail::default_construct_pixels_impl< View + , detail::has_trivial_pixel_constructor< View + , is_planar< View >::value + >::value + >( img_view ); } diff --git a/include/boost/gil/color_base.hpp b/include/boost/gil/color_base.hpp index 016ddfbcd..028d38fc9 100644 --- a/include/boost/gil/color_base.hpp +++ b/include/boost/gil/color_base.hpp @@ -67,6 +67,10 @@ struct mapping_transform /// \brief A homogeneous color base holding one color element. Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept /// If the element type models Regular, this class models HomogeneousColorBaseValueConcept. +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +#pragma warning(push) +#pragma warning(disable:4512) //assignment operator could not be generated +#endif /// \brief A homogeneous color base holding one color element. Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept /// \ingroup ColorBaseModelHomogeneous @@ -327,6 +331,10 @@ public: } }; +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +#pragma warning(pop) +#endif + // The following way of casting adjacent channels (the contents of color_base) into an array appears to be unsafe // -- there is no guarantee that the compiler won't add any padding between adjacent channels. // Note, however, that GIL _must_ be compiled with compiler settings ensuring there is no padding in the color base structs. diff --git a/include/boost/gil/image.hpp b/include/boost/gil/image.hpp index 414997a86..cb3bfb561 100644 --- a/include/boost/gil/image.hpp +++ b/include/boost/gil/image.hpp @@ -1,6 +1,6 @@ /* 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). @@ -13,7 +13,7 @@ #define GIL_IMAGE_H //////////////////////////////////////////////////////////////////////////////////////// -/// \file +/// \file /// \brief Templated image /// \author Lubomir Bourdev and Hailin Jin \n /// Adobe Systems Incorporated @@ -23,6 +23,11 @@ #include #include + +#include +#include +#include + #include "gil_config.hpp" #include "image_view.hpp" #include "metafunctions.hpp" @@ -38,16 +43,16 @@ namespace boost { namespace gil { //////////////////////////////////////////////////////////////////////////////////////// /// \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, +/// 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 > +template< typename Pixel, bool IsPlanar = false, typename Alloc=std::allocator > class image { public: typedef typename Alloc::template rebind::other allocator_type; @@ -64,7 +69,7 @@ public: y_coord_t height() const { return _view.height(); } explicit image(std::size_t alignment=0, - const Alloc alloc_in = Alloc()) : + const Alloc alloc_in = Alloc()) : _memory(0), _align_in_bytes(alignment), _alloc(alloc_in) {} // Create with dimensions and optional initial value and alignment @@ -78,7 +83,7 @@ public: 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, + image(const point_t& dimensions, const Pixel& p_in, std::size_t alignment, const Alloc alloc_in = Alloc()) : @@ -99,7 +104,7 @@ public: } template - image(const image& img) : + image(const image& img) : _memory(0), _align_in_bytes(img._align_in_bytes), _alloc(img._alloc) { allocate_and_copy(img.dimensions(),img._view); } @@ -136,9 +141,9 @@ public: using std::swap; swap(_align_in_bytes, img._align_in_bytes); swap(_memory, img._memory); - swap(_view, img._view); + 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) { @@ -149,14 +154,14 @@ public: 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, + 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, + 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); } @@ -167,14 +172,14 @@ private: std::size_t _align_in_bytes; allocator_type _alloc; - void allocate_and_default_construct(const point_t& dimensions) { + void allocate_and_default_construct(const point_t& dimensions) { try { allocate_(dimensions,mpl::bool_()); default_construct_pixels(_view); } catch(...) { deallocate(dimensions); throw; } } - void allocate_and_fill(const point_t& dimensions, const Pixel& p_in) { + void allocate_and_fill(const point_t& dimensions, const Pixel& p_in) { try { allocate_(dimensions,mpl::bool_()); uninitialized_fill_pixels(_view, p_in); @@ -182,20 +187,36 @@ private: } template - void allocate_and_copy(const point_t& dimensions, const View& v) { + void allocate_and_copy(const point_t& dimensions, const View& v) { try { allocate_(dimensions,mpl::bool_()); uninitialized_copy_pixels(v,_view); } catch(...) { deallocate(dimensions); throw; } } - void deallocate(const point_t& dimensions) { + void deallocate(const point_t& dimensions) { if (_memory) _alloc.deallocate(_memory, total_allocated_size_in_bytes(dimensions)); } + std::size_t is_planar_impl( const std::size_t size_in_units + , const std::size_t channels_in_image + , mpl::true_ + ) const + { + return size_in_units * channels_in_image; + } + + std::size_t is_planar_impl( const std::size_t size_in_units + , const std::size_t + , mpl::false_ + ) const + { + return size_in_units; + } + std::size_t total_allocated_size_in_bytes(const point_t& dimensions) const { - typedef typename view_t::x_iterator x_iterator; + 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 > @@ -203,14 +224,14 @@ private: , 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 ; + std::size_t size_in_units = is_planar_impl( get_row_size_in_memunits( dimensions.x ) * dimensions.y + , _channels_in_image + , typename boost::conditional< IsPlanar, mpl::true_, mpl::false_ >::type() + ); // return the size rounded up to the nearest byte - return ( size_in_units + byte_to_memunit< x_iterator >::value - 1 ) - / byte_to_memunit::value + return ( size_in_units + byte_to_memunit< x_iterator >::value - 1 ) + / byte_to_memunit::value + ( _align_in_bytes > 0 ? _align_in_bytes - 1 : 0 ); // add extra padding in case we need to align the first image pixel } @@ -222,7 +243,7 @@ private: } 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; @@ -234,7 +255,7 @@ private: 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; + typename view_t::x_iterator first; for (int i=0; i::value; ++i) { dynamic_at_c(first,i) = (typename channel_type::type*)tmp; memunit_advance(dynamic_at_c(first,i), plane_size*i); @@ -245,7 +266,7 @@ private: template void swap(image& im1,image& im2) { - im1.swap(im2); + im1.swap(im2); } template @@ -264,13 +285,13 @@ bool operator!=(const image& im1,const image inline +template inline const typename image::view_t& view(image& img) { return img._view; } /// \brief Returns the constant-pixel view of an image -template inline -const typename image::const_view_t const_view(const image& img) { - return static_cast::const_view_t>(img._view); +template inline +const typename image::const_view_t const_view(const image& img) { + return static_cast::const_view_t>(img._view); } ///@} @@ -279,7 +300,7 @@ const typename image::const_view_t const_view(const image< ///////////////////////////// template -struct channel_type > : public channel_type {}; +struct channel_type > : public channel_type {}; template struct color_space_type > : public color_space_type {};