00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef GIL_IMAGE_H
00013 #define GIL_IMAGE_H
00014
00023
00024 #include <cstddef>
00025 #include <memory>
00026 #include "gil_config.hpp"
00027 #include "image_view.hpp"
00028 #include "metafunctions.hpp"
00029 #include "algorithm.hpp"
00030
00031 namespace boost { namespace gil {
00032
00033 #ifdef _MSC_VER
00034 #pragma warning(push)
00035 #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)
00036 #endif
00037
00049
00050 template <typename Pixel, bool IsPlanar, typename Alloc=std::allocator<unsigned char> >
00051 class image {
00052 public:
00053 typedef typename Alloc::template rebind<unsigned char>::other allocator_type;
00054 typedef typename view_type_from_pixel<Pixel, IsPlanar>::type view_t;
00055 typedef typename view_t::const_t const_view_t;
00056 typedef typename view_t::point_t point_t;
00057 typedef typename view_t::coord_t coord_t;
00058 typedef typename view_t::value_type value_type;
00059 typedef coord_t x_coord_t;
00060 typedef coord_t y_coord_t;
00061
00062 const point_t& dimensions() const { return _view.dimensions(); }
00063 x_coord_t width() const { return _view.width(); }
00064 y_coord_t height() const { return _view.height(); }
00065
00066 explicit image(std::size_t alignment=1,
00067 const Alloc alloc_in = Alloc()) :
00068 _memory(0), _align(alignment), _alloc(alloc_in) {}
00069
00070
00071 image(const point_t& dimensions,
00072 std::size_t alignment=1) : _memory(0), _align(alignment) {
00073 allocate_and_default_construct(dimensions);
00074 }
00075 image(x_coord_t width, y_coord_t height,
00076 std::size_t alignment=1) : _memory(0), _align(alignment) {
00077 allocate_and_default_construct(point_t(width,height));
00078 }
00079 image(const point_t& dimensions,
00080 const Pixel& p_in,
00081 std::size_t alignment,
00082 const Alloc alloc_in = Alloc()) :
00083 _memory(0), _align(alignment), _alloc(alloc_in) {
00084 allocate_and_fill(dimensions, p_in);
00085 }
00086 image(x_coord_t width, y_coord_t height,
00087 const Pixel& p_in,
00088 std::size_t alignment,
00089 const Alloc alloc_in = Alloc()) :
00090 _memory(0), _align(alignment), _alloc(alloc_in) {
00091 allocate_and_fill(point_t(width,height),p_in);
00092 }
00093
00094 image(const image& img) :
00095 _memory(0), _align(img._align), _alloc(img._alloc) {
00096 allocate_and_copy(img.dimensions(),img._view);
00097 }
00098
00099 template <typename P2, bool IP2, typename Alloc2>
00100 image(const image<P2,IP2,Alloc2>& img) :
00101 _memory(0), _align(img._align), _alloc(img._alloc) {
00102 allocate_and_copy(img.dimensions(),img._view);
00103 }
00104 image& operator=(const image& img) {
00105 if (dimensions() == img.dimensions())
00106 copy_pixels(img._view,_view);
00107 else {
00108 image tmp(img);
00109 swap(tmp);
00110 }
00111 return *this;
00112 }
00113
00114 template <typename Img>
00115 image& operator=(const Img& img) {
00116 if (dimensions() == img.dimensions())
00117 copy_pixels(img._view,_view);
00118 else {
00119 image tmp(img);
00120 swap(tmp);
00121 }
00122 return *this;
00123 }
00124
00125 ~image() {
00126 destruct_pixels(_view);
00127 deallocate(_view.dimensions());
00128 }
00129
00130 Alloc& allocator() { return _alloc; }
00131 Alloc const& allocator() const { return _alloc; }
00132
00133 void swap(image& img) {
00134 using std::swap;
00135 swap(_align, img._align);
00136 swap(_memory,img._memory);
00137 swap(_view, img._view);
00138 swap(_alloc, img._alloc);
00139 }
00140
00141 void recreate(const point_t& dims, std::size_t alignment=1) {
00142 if (dims!=_view.dimensions() || _align!=alignment) {
00143 image tmp(dims, alignment);
00144 swap(tmp);
00145 }
00146 }
00147 void recreate(x_coord_t width, y_coord_t height, std::size_t alignment=1) {
00148 recreate(point_t(width,height),alignment);
00149 }
00150 void recreate(const point_t& dims,
00151 const Pixel& p_in, std::size_t alignment) {
00152 if (dims!=_view.dimensions() || _align!=alignment) {
00153 image tmp(dims, p_in, alignment);
00154 swap(tmp);
00155 }
00156 }
00157 void recreate(x_coord_t width, y_coord_t height,
00158 const Pixel& p_in, std::size_t alignment) {
00159 recreate(point_t(width,height),p_in,alignment);
00160 }
00161
00162 view_t _view;
00163 private:
00164 unsigned char* _memory;
00165 std::size_t _align;
00166 allocator_type _alloc;
00167
00168 void allocate_and_default_construct(const point_t& dimensions) {
00169 try {
00170 allocate_(dimensions,mpl::bool_<IsPlanar>());
00171 default_construct_pixels(_view);
00172 } catch(...) { deallocate(dimensions); throw; }
00173 }
00174
00175 void allocate_and_fill(const point_t& dimensions, const Pixel& p_in) {
00176 try {
00177 allocate_(dimensions,mpl::bool_<IsPlanar>());
00178 uninitialized_fill_pixels(_view, p_in);
00179 } catch(...) { deallocate(dimensions); throw; }
00180 }
00181
00182 template <typename View>
00183 void allocate_and_copy(const point_t& dimensions, const View& v) {
00184 try {
00185 allocate_(dimensions,mpl::bool_<IsPlanar>());
00186 uninitialized_copy_pixels(v,_view);
00187 } catch(...) { deallocate(dimensions); throw; }
00188 }
00189
00190 void deallocate(const point_t& dimensions) {
00191 if (_memory) _alloc.deallocate(_memory, total_allocated_size_in_bytes(dimensions));
00192 }
00193
00194 std::size_t total_allocated_size_in_bytes(const point_t& dimensions) const {
00195 std::size_t size_in_units = _total_allocated_size(dimensions, mpl::bool_<IsPlanar>());
00196
00197 return (size_in_units + byte_to_memunit<typename view_t::x_iterator>::value - 1) / byte_to_memunit<typename view_t::x_iterator>::value;
00198 }
00199
00200 std::size_t get_row_size(x_coord_t width) const {
00201 return align(width*memunit_step(typename view_t::x_iterator()),_align);
00202 }
00203
00204 std::size_t _total_allocated_size(const point_t& dimensions,mpl::false_) const {
00205 return get_row_size(dimensions.x)*dimensions.y+_align-1;
00206 }
00207 std::size_t _total_allocated_size(const point_t& dimensions,mpl::true_) const {
00208 std::size_t plane_size=get_row_size(dimensions.x)*dimensions.y;
00209 return plane_size*num_channels<view_t>::value+_align-1;
00210 }
00211
00212
00213 void allocate_(const point_t& dimensions, mpl::false_) {
00214 _memory=_alloc.allocate(total_allocated_size_in_bytes(dimensions));
00215 unsigned char* tmp=(unsigned char*)align((std::size_t)_memory,_align);
00216 _view=view_t(dimensions,typename view_t::locator(typename view_t::x_iterator(tmp),get_row_size(dimensions.x)));
00217 }
00218 void allocate_(const point_t& dimensions, mpl::true_) {
00219 std::size_t row_size=get_row_size(dimensions.x);
00220 std::size_t plane_size=row_size*dimensions.y;
00221 _memory=_alloc.allocate(total_allocated_size_in_bytes(dimensions));
00222 unsigned char* tmp=(unsigned char*)align((std::size_t)_memory,_align);
00223 typename view_t::x_iterator first;
00224 for (int i=0; i<num_channels<view_t>::value; ++i) {
00225 dynamic_at_c(first,i) = (typename channel_type<view_t>::type*)tmp;
00226 memunit_advance(dynamic_at_c(first,i), plane_size*i);
00227 }
00228 _view=view_t(dimensions, typename view_t::locator(first, row_size));
00229 }
00230 };
00231
00232 template <typename Pixel, bool IsPlanar, typename Alloc>
00233 void swap(image<Pixel, IsPlanar, Alloc>& im1,image<Pixel, IsPlanar, Alloc>& im2) {
00234 im1.swap(im2);
00235 }
00236
00237 template <typename Pixel1, bool IsPlanar1, typename Alloc1, typename Pixel2, bool IsPlanar2, typename Alloc2>
00238 bool operator==(const image<Pixel1,IsPlanar1,Alloc1>& im1,const image<Pixel2,IsPlanar2,Alloc2>& im2) {
00239 if ((void*)(&im1)==(void*)(&im2)) return true;
00240 if (const_view(im1).dimensions()!=const_view(im2).dimensions()) return false;
00241 return equal_pixels(const_view(im1),const_view(im2));
00242 }
00243 template <typename Pixel1, bool IsPlanar1, typename Alloc1, typename Pixel2, bool IsPlanar2, typename Alloc2>
00244 bool operator!=(const image<Pixel1,IsPlanar1,Alloc1>& im1,const image<Pixel2,IsPlanar2,Alloc2>& im2) {return !(im1==im2);}
00245
00249
00251
00253 template <typename Pixel, bool IsPlanar, typename Alloc> inline
00254 const typename image<Pixel,IsPlanar,Alloc>::view_t& view(image<Pixel,IsPlanar,Alloc>& img) { return img._view; }
00255
00257 template <typename Pixel, bool IsPlanar, typename Alloc> inline
00258 const typename image<Pixel,IsPlanar,Alloc>::const_view_t const_view(const image<Pixel,IsPlanar,Alloc>& img) {
00259 return static_cast<const typename image<Pixel,IsPlanar,Alloc>::const_view_t>(img._view);
00260 }
00262
00264
00266
00267 template <typename Pixel, bool IsPlanar, typename Alloc>
00268 struct channel_type<image<Pixel,IsPlanar,Alloc> > : public channel_type<Pixel> {};
00269
00270 template <typename Pixel, bool IsPlanar, typename Alloc>
00271 struct color_space_type<image<Pixel,IsPlanar,Alloc> > : public color_space_type<Pixel> {};
00272
00273 template <typename Pixel, bool IsPlanar, typename Alloc>
00274 struct channel_mapping_type<image<Pixel,IsPlanar,Alloc> > : public channel_mapping_type<Pixel> {};
00275
00276 template <typename Pixel, bool IsPlanar, typename Alloc>
00277 struct is_planar<image<Pixel,IsPlanar,Alloc> > : public mpl::bool_<IsPlanar> {};
00278
00279 #ifdef _MSC_VER
00280 #pragma warning(pop)
00281 #endif
00282
00283 } }
00284
00285 #endif