Generic Image Library: image.hpp Source File

Modules | Alphabetical List | Class List | Directories | File List | GIL Home Page # image.hpp Go to the documentation of this file.
    00001 /*
    00002     Copyright 2005-2007 Adobe Systems Incorporated
    00003
    00004     Use, modification and distribution are subject to the Boost Software License,
    00005     Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
    00006     http://www.boost.org/LICENSE_1_0.txt).
    00007
    00008     See http://opensource.adobe.com/gil for most recent version including documentation.
    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=0,
    00067                    const Alloc alloc_in = Alloc()) :
    00068         _memory(0), _align_in_bytes(alignment), _alloc(alloc_in) {}
    00069
    00070     // Create with dimensions and optional initial value and alignment
    00071     image(const point_t& dimensions,
    00072           std::size_t alignment=0,
    00073           const Alloc alloc_in = Alloc()) : _memory(0), _align_in_bytes(alignment), _alloc(alloc_in) {
    00074         allocate_and_default_construct(dimensions);
    00075     }
    00076     image(x_coord_t width, y_coord_t height,
    00077           std::size_t alignment=0,
    00078           const Alloc alloc_in = Alloc()) : _memory(0), _align_in_bytes(alignment), _alloc(alloc_in) {
    00079         allocate_and_default_construct(point_t(width,height));
    00080     }
    00081     image(const point_t& dimensions,
    00082           const Pixel& p_in,
    00083           std::size_t alignment,
    00084           const Alloc alloc_in = Alloc())  :
    00085         _memory(0), _align_in_bytes(alignment), _alloc(alloc_in) {
    00086         allocate_and_fill(dimensions, p_in);
    00087     }
    00088     image(x_coord_t width, y_coord_t height,
    00089           const Pixel& p_in,
    00090           std::size_t alignment,
    00091           const Alloc alloc_in = Alloc())  :
    00092         _memory(0), _align_in_bytes(alignment), _alloc(alloc_in) {
    00093         allocate_and_fill(point_t(width,height),p_in);
    00094     }
    00095
    00096     image(const image& img) :
    00097         _memory(0), _align_in_bytes(img._align_in_bytes), _alloc(img._alloc) {
    00098         allocate_and_copy(img.dimensions(),img._view);
    00099     }
    00100
    00101     template <typename P2, bool IP2, typename Alloc2>
    00102     image(const image<P2,IP2,Alloc2>& img) :
    00103         _memory(0), _align_in_bytes(img._align_in_bytes), _alloc(img._alloc) {
    00104        allocate_and_copy(img.dimensions(),img._view);
    00105     }
    00106     image& operator=(const image& img) {
    00107         if (dimensions() == img.dimensions())
    00108             copy_pixels(img._view,_view);
    00109         else {
    00110             image tmp(img);
    00111             swap(tmp);
    00112         }
    00113         return *this;
    00114     }
    00115
    00116     template <typename Img>
    00117     image& operator=(const Img& img) {
    00118         if (dimensions() == img.dimensions())
    00119             copy_pixels(img._view,_view);
    00120         else {
    00121             image tmp(img);
    00122             swap(tmp);
    00123         }
    00124         return *this;
    00125     }
    00126
    00127     ~image() {
    00128         destruct_pixels(_view);
    00129         deallocate(_view.dimensions());
    00130     }
    00131
    00132     Alloc&       allocator() { return _alloc; }
    00133     Alloc const& allocator() const { return _alloc; }
    00134
    00135     void swap(image& img) { // required by MutableContainerConcept
    00136         using std::swap;
    00137         swap(_align_in_bytes, img._align_in_bytes);
    00138         swap(_memory,         img._memory);
    00139         swap(_view,           img._view);
    00140         swap(_alloc,          img._alloc);
    00141     }
    00142
    00143     void recreate(const point_t& dims, std::size_t alignment=0, const Alloc alloc_in = Alloc()) {
    00144         if (dims!=_view.dimensions() || _align_in_bytes!=alignment || alloc_in!=_alloc) {
    00145             image tmp(dims, alignment, alloc_in);
    00146             swap(tmp);
    00147         }
    00148     }
    00149     void recreate(x_coord_t width, y_coord_t height, std::size_t alignment=0, const Alloc alloc_in = Alloc()) {
    00150         recreate(point_t(width,height),alignment,alloc_in);
    00151     }
    00152     void recreate(const point_t& dims,
    00153                   const Pixel& p_in, std::size_t alignment, const Alloc alloc_in = Alloc()) {
    00154         if (dims!=_view.dimensions() || _align_in_bytes!=alignment || alloc_in!=_alloc) {
    00155             image tmp(dims, p_in, alignment, alloc_in);
    00156             swap(tmp);
    00157         }
    00158     }
    00159     void recreate(x_coord_t width, y_coord_t height,
    00160                   const Pixel& p_in, std::size_t alignment, const Alloc alloc_in = Alloc()) {
    00161         recreate(point_t(width,height),p_in,alignment,alloc_in);
    00162     }
    00163
    00164     view_t       _view;      // contains pointer to the pixels, the image size and ways to navigate pixels
    00165 private:
    00166     unsigned char* _memory;
    00167     std::size_t    _align_in_bytes;
    00168     allocator_type _alloc;
    00169
    00170     void allocate_and_default_construct(const point_t& dimensions) {
    00171         try {
    00172             allocate_(dimensions,mpl::bool_<IsPlanar>());
    00173             default_construct_pixels(_view);
    00174         } catch(...) { deallocate(dimensions); throw; }
    00175     }
    00176
    00177     void allocate_and_fill(const point_t& dimensions, const Pixel& p_in) {
    00178         try {
    00179             allocate_(dimensions,mpl::bool_<IsPlanar>());
    00180             uninitialized_fill_pixels(_view, p_in);
    00181         } catch(...) { deallocate(dimensions); throw; }
    00182     }
    00183
    00184     template <typename View>
    00185     void allocate_and_copy(const point_t& dimensions, const View& v) {
    00186         try {
    00187             allocate_(dimensions,mpl::bool_<IsPlanar>());
    00188             uninitialized_copy_pixels(v,_view);
    00189         } catch(...) { deallocate(dimensions); throw; }
    00190     }
    00191
    00192     void deallocate(const point_t& dimensions) {
    00193         if (_memory) _alloc.deallocate(_memory, total_allocated_size_in_bytes(dimensions));
    00194     }
    00195
    00196     std::size_t total_allocated_size_in_bytes(const point_t& dimensions) const {
    00197         std::size_t size_in_units = get_row_size_in_memunits(dimensions.x)*dimensions.y;
    00198         if (IsPlanar)
    00199             size_in_units = size_in_units*num_channels<view_t>::value;
    00200
    00201         // return the size rounded up to the nearest byte
    00202         return (size_in_units + byte_to_memunit<typename view_t::x_iterator>::value - 1) / byte_to_memunit<typename view_t::x_iterator>::value
    00203             + (_align_in_bytes>0 ? _align_in_bytes-1:0);    // add extra padding in case we need to align the first image pixel
    00204     }
    00205
    00206     std::size_t get_row_size_in_memunits(x_coord_t width) const {   // number of units per row
    00207         std::size_t size_in_memunits = width*memunit_step(typename view_t::x_iterator());
    00208         if (_align_in_bytes>0) {
    00209             std::size_t alignment_in_memunits=_align_in_bytes*byte_to_memunit<typename view_t::x_iterator>::value;
    00210             return align(size_in_memunits, alignment_in_memunits);
    00211         }
    00212         return size_in_memunits;
    00213     }
    00214
    00215     void allocate_(const point_t& dimensions, mpl::false_) {  // if it throws and _memory!=0 the client must deallocate _memory
    00216         _memory=_alloc.allocate(total_allocated_size_in_bytes(dimensions));
    00217         unsigned char* tmp=(_align_in_bytes>0) ? (unsigned char*)align((std::size_t)_memory,_align_in_bytes) : _memory;
    00218         _view=view_t(dimensions,typename view_t::locator(typename view_t::x_iterator(tmp),get_row_size_in_memunits(dimensions.x)));
    00219     }
    00220
    00221     void allocate_(const point_t& dimensions, mpl::true_) {   // if it throws and _memory!=0 the client must deallocate _memory
    00222         std::size_t row_size=get_row_size_in_memunits(dimensions.x);
    00223         std::size_t plane_size=row_size*dimensions.y;
    00224         _memory=_alloc.allocate(total_allocated_size_in_bytes(dimensions));
    00225         unsigned char* tmp=(_align_in_bytes>0) ? (unsigned char*)align((std::size_t)_memory,_align_in_bytes) : _memory;
    00226         typename view_t::x_iterator first;
    00227         for (int i=0; i<num_channels<view_t>::value; ++i) {
    00228             dynamic_at_c(first,i) = (typename channel_type<view_t>::type*)tmp;
    00229             memunit_advance(dynamic_at_c(first,i), plane_size*i);
    00230         }
    00231         _view=view_t(dimensions, typename view_t::locator(first, row_size));
    00232     }
    00233 };
    00234
    00235 template <typename Pixel, bool IsPlanar, typename Alloc>
    00236 void swap(image<Pixel, IsPlanar, Alloc>& im1,image<Pixel, IsPlanar, Alloc>& im2) {
    00237     im1.swap(im2);
    00238 }
    00239
    00240 template <typename Pixel1, bool IsPlanar1, typename Alloc1, typename Pixel2, bool IsPlanar2, typename Alloc2>
    00241 bool operator==(const image<Pixel1,IsPlanar1,Alloc1>& im1,const image<Pixel2,IsPlanar2,Alloc2>& im2) {
    00242     if ((void*)(&im1)==(void*)(&im2)) return true;
    00243     if (const_view(im1).dimensions()!=const_view(im2).dimensions()) return false;
    00244     return equal_pixels(const_view(im1),const_view(im2));
    00245 }
    00246 template <typename Pixel1, bool IsPlanar1, typename Alloc1, typename Pixel2, bool IsPlanar2, typename Alloc2>
    00247 bool operator!=(const image<Pixel1,IsPlanar1,Alloc1>& im1,const image<Pixel2,IsPlanar2,Alloc2>& im2) {return !(im1==im2);}
    00248
    00252
    00254
    00256 template <typename Pixel, bool IsPlanar, typename Alloc> inline
    00257 const typename image<Pixel,IsPlanar,Alloc>::view_t& view(image<Pixel,IsPlanar,Alloc>& img) { return img._view; }
    00258
    00260 template <typename Pixel, bool IsPlanar, typename Alloc> inline
    00261 const typename image<Pixel,IsPlanar,Alloc>::const_view_t const_view(const image<Pixel,IsPlanar,Alloc>& img) {
    00262     return static_cast<const typename image<Pixel,IsPlanar,Alloc>::const_view_t>(img._view);
    00263 }
    00265
    00267 //  PixelBasedConcept
    00269
    00270 template <typename Pixel, bool IsPlanar, typename Alloc>
    00271 struct channel_type<image<Pixel,IsPlanar,Alloc> > : public channel_type<Pixel> {};
    00272
    00273 template <typename Pixel, bool IsPlanar, typename Alloc>
    00274 struct color_space_type<image<Pixel,IsPlanar,Alloc> >  : public color_space_type<Pixel> {};
    00275
    00276 template <typename Pixel, bool IsPlanar, typename Alloc>
    00277 struct channel_mapping_type<image<Pixel,IsPlanar,Alloc> > : public channel_mapping_type<Pixel> {};
    00278
    00279 template <typename Pixel, bool IsPlanar, typename Alloc>
    00280 struct is_planar<image<Pixel,IsPlanar,Alloc> > : public mpl::bool_<IsPlanar> {};
    00281
    00282 //#ifdef _MSC_VER
    00283 //#pragma warning(pop)
    00284 //#endif
    00285
    00286 } }  // namespace boost::gil
    00287
    00288 #endif