|
Boost-Commit : |
From: lbourdev_at_[hidden]
Date: 2007-11-16 22:38:25
Author: lbourdev
Date: 2007-11-16 22:38:25 EST (Fri, 16 Nov 2007)
New Revision: 41165
URL: http://svn.boost.org/trac/boost/changeset/41165
Log:
Updated to version 2.1.2
Added support for more compilers.
Added new flag GIL_NONWORD_POINTER_ALIGNMENT_SUPPORTED to indicate whether dereferencing on non-word
boundary is supported. Enabling this flag improves performance.
Fixed two bugs related to non-byte-aligned images. The image alignment parameter is now specified in
bytes, and has a default of 0, which means "packed" alignment. In particular, for non-byte-aligned
images alignment of 0 means there are no padding bits at the ends of rows.
Added the allocator as an optional parameter to image constructors and image recreate methods.
Text files modified:
trunk/boost/gil/channel.hpp | 49 ++++++++++++++++++-----
trunk/boost/gil/color_convert.hpp | 3
trunk/boost/gil/gil_config.hpp | 7 ++
trunk/boost/gil/image.hpp | 83 ++++++++++++++++++++-------------------
trunk/boost/gil/metafunctions.hpp | 2
trunk/libs/gil/test/image.cpp | 20 ++++++--
trunk/libs/gil/test/pixel_iterator.cpp | 1
7 files changed, 104 insertions(+), 61 deletions(-)
Modified: trunk/boost/gil/channel.hpp
==============================================================================
--- trunk/boost/gil/channel.hpp (original)
+++ trunk/boost/gil/channel.hpp 2007-11-16 22:38:25 EST (Fri, 16 Nov 2007)
@@ -253,6 +253,20 @@
};
namespace detail {
+
+template <std::size_t K>
+struct static_copy_bytes {
+ void operator()(const unsigned char* from, unsigned char* to) const {
+ *to = *from;
+ static_copy_bytes<K-1>()(++from,++to);
+ }
+};
+
+template <>
+struct static_copy_bytes<0> {
+ void operator()(const unsigned char* from, unsigned char* to) const {}
+};
+
template <typename Derived, typename BitField, int NumBits, bool Mutable>
class packed_channel_reference_base {
protected:
@@ -292,8 +306,21 @@
data_ptr_t operator &() const {return _data_ptr;}
protected:
static const integer_t max_val = (1<<NumBits) - 1;
- const bitfield_t& const_data() const { return *static_cast<const bitfield_t*>(_data_ptr); }
- bitfield_t& data() const { return *static_cast< bitfield_t*>(_data_ptr); }
+
+#ifdef GIL_NONWORD_POINTER_ALIGNMENT_SUPPORTED
+ const bitfield_t& get_data() const { return *static_cast<const bitfield_t*>(_data_ptr); }
+ void set_data(const bitfield_t& val) const { *static_cast< bitfield_t*>(_data_ptr) = val; }
+#else
+ bitfield_t get_data() const {
+ bitfield_t ret;
+ static_copy_bytes<sizeof(bitfield_t) >()(gil_reinterpret_cast_c<const unsigned char*>(_data_ptr),gil_reinterpret_cast<unsigned char*>(&ret));
+ return ret;
+ }
+ void set_data(const bitfield_t& val) const {
+ static_copy_bytes<sizeof(bitfield_t) >()(gil_reinterpret_cast_c<const unsigned char*>(&val),gil_reinterpret_cast<unsigned char*>(_data_ptr));
+ }
+#endif
+
private:
void set(integer_t value) const { // can this be done faster??
const integer_t num_values = max_val+1;
@@ -351,7 +378,7 @@
unsigned first_bit() const { return FirstBit; }
- integer_t get() const { return integer_t((this->const_data()&channel_mask) >> FirstBit); }
+ integer_t get() const { return integer_t((this->get_data()&channel_mask) >> FirstBit); }
};
/// \ingroup PackedChannelReferenceModel
@@ -372,18 +399,18 @@
packed_channel_reference(const packed_channel_reference& ref) : parent_t(ref._data_ptr) {}
const packed_channel_reference& operator=(integer_t value) const { assert(value<=parent_t::max_val); set_unsafe(value); return *this; }
- const packed_channel_reference& operator=(const mutable_reference& ref) const { set_from_reference(ref.data()); return *this; }
- const packed_channel_reference& operator=(const const_reference& ref) const { set_from_reference(ref.const_data()); return *this; }
+ const packed_channel_reference& operator=(const mutable_reference& ref) const { set_from_reference(ref.get_data()); return *this; }
+ const packed_channel_reference& operator=(const const_reference& ref) const { set_from_reference(ref.get_data()); return *this; }
template <bool Mutable1>
const packed_channel_reference& operator=(const packed_dynamic_channel_reference<BitField,NumBits,Mutable1>& ref) const { set_unsafe(ref.get()); return *this; }
unsigned first_bit() const { return FirstBit; }
- integer_t get() const { return integer_t((this->const_data()&channel_mask) >> FirstBit); }
- void set_unsafe(integer_t value) const { this->data() = (this->const_data() & ~channel_mask) | (value<<FirstBit); }
+ integer_t get() const { return integer_t((this->get_data()&channel_mask) >> FirstBit); }
+ void set_unsafe(integer_t value) const { this->set_data((this->get_data() & ~channel_mask) | (value<<FirstBit)); }
private:
- void set_from_reference(const BitField& other_bits) const { this->data() = (this->const_data() & ~channel_mask) | (other_bits & channel_mask); }
+ void set_from_reference(const BitField& other_bits) const { this->set_data((this->get_data() & ~channel_mask) | (other_bits & channel_mask)); }
};
} } // namespace boost::gil
@@ -463,7 +490,7 @@
integer_t get() const {
const BitField channel_mask = parent_t::max_val<<_first_bit;
- return (this->const_data()&channel_mask) >> _first_bit;
+ return (this->get_data()&channel_mask) >> _first_bit;
}
};
@@ -498,11 +525,11 @@
integer_t get() const {
const BitField channel_mask = parent_t::max_val<<_first_bit;
- return (this->const_data()&channel_mask) >> _first_bit;
+ return (this->get_data()&channel_mask) >> _first_bit;
}
void set_unsafe(integer_t value) const {
const BitField channel_mask = parent_t::max_val<<_first_bit;
- this->data() = (this->const_data() & ~channel_mask) | value<<_first_bit;
+ this->set_data((this->get_data() & ~channel_mask) | value<<_first_bit);
}
};
} } // namespace boost::gil
Modified: trunk/boost/gil/color_convert.hpp
==============================================================================
--- trunk/boost/gil/color_convert.hpp (original)
+++ trunk/boost/gil/color_convert.hpp 2007-11-16 22:38:25 EST (Fri, 16 Nov 2007)
@@ -32,7 +32,6 @@
#include "rgb.hpp"
#include "rgba.hpp"
#include "cmyk.hpp"
-#include "image_view_factory.hpp"
#include "metafunctions.hpp"
#include "utilities.hpp"
#include "color_base_algorithm.hpp"
@@ -229,7 +228,7 @@
return get_color(p,alpha_t());
}
template <typename Pixel>
-typename channel_type<Pixel>::type alpha_or_max_impl(const Pixel& p, mpl::false_) {
+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
Modified: trunk/boost/gil/gil_config.hpp
==============================================================================
--- trunk/boost/gil/gil_config.hpp (original)
+++ trunk/boost/gil/gil_config.hpp 2007-11-16 22:38:25 EST (Fri, 16 Nov 2007)
@@ -23,7 +23,7 @@
#include <boost/config.hpp>
-#define GIL_VERSION "2.1.1"
+#define GIL_VERSION "2.1.2"
#ifdef _DEBUG
# define GIL_FORCEINLINE inline
@@ -41,5 +41,10 @@
#endif
#endif
+// Enable GIL_NONWORD_POINTER_ALIGNMENT_SUPPORTED if your platform supports dereferencing on non-word memory boundary.
+// Enabling the flag results in performance improvement
+#if !defined(__hpux) && !defined(sun) && !defined(__sun) && !defined(__osf__)
+ #define GIL_NONWORD_POINTER_ALIGNMENT_SUPPORTED
+#endif
#endif
Modified: trunk/boost/gil/image.hpp
==============================================================================
--- trunk/boost/gil/image.hpp (original)
+++ trunk/boost/gil/image.hpp 2007-11-16 22:38:25 EST (Fri, 16 Nov 2007)
@@ -63,42 +63,44 @@
x_coord_t width() const { return _view.width(); }
y_coord_t height() const { return _view.height(); }
- explicit image(std::size_t alignment=1,
+ explicit image(std::size_t alignment=0,
const Alloc alloc_in = Alloc()) :
- _memory(0), _align(alignment), _alloc(alloc_in) {}
+ _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=1) : _memory(0), _align(alignment) {
+ 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=1) : _memory(0), _align(alignment) {
+ 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(alignment), _alloc(alloc_in) {
+ _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(alignment), _alloc(alloc_in) {
+ _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(img._align), _alloc(img._alloc) {
+ _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(img._align), _alloc(img._alloc) {
+ _memory(0), _align_in_bytes(img._align_in_bytes), _alloc(img._alloc) {
allocate_and_copy(img.dimensions(),img._view);
}
image& operator=(const image& img) {
@@ -132,37 +134,37 @@
void swap(image& img) { // required by MutableContainerConcept
using std::swap;
- swap(_align, img._align);
- swap(_memory,img._memory);
- swap(_view, img._view);
- swap(_alloc, img._alloc);
+ 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=1) {
- if (dims!=_view.dimensions() || _align!=alignment) {
- image tmp(dims, alignment);
+ 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=1) {
- recreate(point_t(width,height),alignment);
+ 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) {
- if (dims!=_view.dimensions() || _align!=alignment) {
- image tmp(dims, p_in, alignment);
+ 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) {
- recreate(point_t(width,height),p_in,alignment);
+ 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;
+ std::size_t _align_in_bytes;
allocator_type _alloc;
void allocate_and_default_construct(const point_t& dimensions) {
@@ -192,34 +194,35 @@
}
std::size_t total_allocated_size_in_bytes(const point_t& dimensions) const {
- std::size_t size_in_units = _total_allocated_size(dimensions, mpl::bool_<IsPlanar>());
- // return the size rounded up to the nearest byte
- return (size_in_units + byte_to_memunit<typename view_t::x_iterator>::value - 1) / byte_to_memunit<typename view_t::x_iterator>::value;
- }
+ std::size_t size_in_units = get_row_size_in_memunits(dimensions.x)*dimensions.y;
+ if (IsPlanar)
+ size_in_units = size_in_units*num_channels<view_t>::value;
- std::size_t get_row_size(x_coord_t width) const { // number of units per row
- return align(width*memunit_step(typename view_t::x_iterator()),_align);
+ // return the size rounded up to the nearest byte
+ return (size_in_units + byte_to_memunit<typename view_t::x_iterator>::value - 1) / byte_to_memunit<typename view_t::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 _total_allocated_size(const point_t& dimensions,mpl::false_) const {
- return get_row_size(dimensions.x)*dimensions.y+_align-1;
+ 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;
}
- std::size_t _total_allocated_size(const point_t& dimensions,mpl::true_) const {
- std::size_t plane_size=get_row_size(dimensions.x)*dimensions.y;
- return plane_size*num_channels<view_t>::value+_align-1;
- }
-
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=(unsigned char*)align((std::size_t)_memory,_align);
- _view=view_t(dimensions,typename view_t::locator(typename view_t::x_iterator(tmp),get_row_size(dimensions.x)));
+ 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(dimensions.x);
+ 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=(unsigned char*)align((std::size_t)_memory,_align);
+ 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;
Modified: trunk/boost/gil/metafunctions.hpp
==============================================================================
--- trunk/boost/gil/metafunctions.hpp (original)
+++ trunk/boost/gil/metafunctions.hpp 2007-11-16 22:38:25 EST (Fri, 16 Nov 2007)
@@ -338,7 +338,7 @@
struct bit_aligned_image_type {
private:
BOOST_STATIC_CONSTANT(int, bit_size = (mpl::accumulate<ChannelBitSizeVector, mpl::int_<0>, mpl::plus<mpl::_1, mpl::_2> >::type::value));
- typedef typename detail::min_fast_uint<bit_size>::type bitfield_t;
+ typedef typename detail::min_fast_uint<bit_size+7>::type bitfield_t;
typedef const bit_aligned_pixel_reference<bitfield_t, ChannelBitSizeVector, Layout, true> bit_alignedref_t;
public:
typedef image<bit_alignedref_t,false,Alloc> type;
Modified: trunk/libs/gil/test/image.cpp
==============================================================================
--- trunk/libs/gil/test/image.cpp (original)
+++ trunk/libs/gil/test/image.cpp 2007-11-16 22:38:25 EST (Fri, 16 Nov 2007)
@@ -291,14 +291,22 @@
histogram_test(mandel,"virtual_");
}
+// Test alignment and packed images
void image_test::packed_image_test() {
- typedef packed_image3_type<boost::uint16_t, 5,6,5, rgb_layout_t>::type rgb565_image_t;
+ typedef bit_aligned_image3_type<1,3,1, bgr_layout_t>::type bgr131_image_t;
+ typedef bgr131_image_t::value_type bgr131_pixel_t;
+ bgr131_pixel_t fill_val(1,3,1);
- rgb565_image_t img565(sample_view.dimensions());
- copy_and_convert_pixels(sample_view, view(img565));
+ bgr131_image_t bgr131_img(3,10);
+ fill_pixels(view(bgr131_img), fill_val);
-// TODO: Commented out because there is an error with packed images under GCC 4.1.2, but not under VC8
-// check_view(color_converted_view<rgb8_pixel_t>(const_view(img565)),"packed565");
+ bgr131_image_t bgr131a_img(3,10,1);
+ copy_pixels(const_view(bgr131_img), view(bgr131a_img));
+
+ bgr131_image_t bgr131b_img(3,10,4);
+ copy_pixels(const_view(bgr131_img), view(bgr131b_img));
+
+ error_if(bgr131_img!=bgr131a_img || bgr131a_img!=bgr131b_img);
}
void image_test::dynamic_image_test() {
@@ -339,7 +347,7 @@
image_all_test<rgb8_planar_image_t>("planarrgb8_");
image_all_test<gray8_image_t>("gray8_");
- typedef const bit_aligned_pixel_reference<boost::uint8_t, mpl::vector3_c<int,1,2,1>, bgr_layout_t, true> bgr121_ref_t;
+ typedef const bit_aligned_pixel_reference<boost::uint8_t, mpl::vector3_c<int,1,2,1>, bgr_layout_t, true> bgr121_ref_t;
typedef image<bgr121_ref_t,false> bgr121_image_t;
image_all_test<bgr121_image_t>("bgr121_");
Modified: trunk/libs/gil/test/pixel_iterator.cpp
==============================================================================
--- trunk/libs/gil/test/pixel_iterator.cpp (original)
+++ trunk/libs/gil/test/pixel_iterator.cpp 2007-11-16 22:38:25 EST (Fri, 16 Nov 2007)
@@ -22,6 +22,7 @@
#include <boost/gil/step_iterator.hpp>
#include <boost/gil/typedefs.hpp>
#include <boost/gil/color_convert.hpp>
+#include <boost/gil/image_view_factory.hpp>
#include <boost/mpl/vector.hpp>
using namespace boost::gil;
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