// // Copyright 2012 Christian Henning // // Distributed under 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 // #ifndef BOOST_GIL_EXTENSION_TOOLBOX_IMAGE_TYPES_INDEXED_IMAGE_HPP #define BOOST_GIL_EXTENSION_TOOLBOX_IMAGE_TYPES_INDEXED_IMAGE_HPP #include #include #include #include #include #include #include #include namespace boost { namespace gil { template< typename Locator > struct get_pixel_type_locator { using type = mp11::mp_if < typename is_bit_aligned::type, typename Locator::reference, typename Locator::value_type >; }; // used for virtual locator template< typename IndicesLoc , typename PaletteLoc > struct indexed_image_deref_fn_base { using indices_locator_t = IndicesLoc; using palette_locator_t = PaletteLoc; //using index_t = typename get_pixel_type_locator::type; using const_t = indexed_image_deref_fn_base; using value_type = typename PaletteLoc::value_type; using reference = value_type; using const_reference = value_type; using argument_type = point_t; using result_type = reference; static const bool is_mutable = false; indexed_image_deref_fn_base() {} indexed_image_deref_fn_base( const indices_locator_t& indices_loc , const palette_locator_t& palette_loc ) : _indices_loc( indices_loc ) , _palette_loc( palette_loc ) {} void set_indices( const indices_locator_t& indices_loc ) { _indices_loc = indices_loc; } void set_palette( const palette_locator_t& palette_loc ) { _palette_loc = palette_loc; } const indices_locator_t& indices() const { return _indices_loc; } const palette_locator_t& palette() const { return _palette_loc; } protected: indices_locator_t _indices_loc; palette_locator_t _palette_loc; }; // used for virtual locator template< typename IndicesLoc , typename PaletteLoc , typename Enable = void // there is specialization for integral indices > struct indexed_image_deref_fn : indexed_image_deref_fn_base< IndicesLoc , PaletteLoc > { using base_t = indexed_image_deref_fn_base < IndicesLoc, PaletteLoc >; indexed_image_deref_fn() : base_t() {} indexed_image_deref_fn( const typename base_t::indices_locator_t& indices_loc , const typename base_t::palette_locator_t& palette_loc ) : base_t( indices_loc , palette_loc ) {} typename base_t::result_type operator()( const point_t& p ) const { return * this->_palette_loc.xy_at( at_c<0>( *this->_indices_loc.xy_at( p )), 0 ); } }; template struct indexed_image_deref_fn < IndicesLoc, PaletteLoc, typename std::enable_if < detail::is_channel_integral::value >::type > : indexed_image_deref_fn_base { using base_t = indexed_image_deref_fn_base; indexed_image_deref_fn() : base_t() {} indexed_image_deref_fn( typename base_t::indices_locator_t const& indices_loc, typename base_t::palette_locator_t const& palette_loc) : base_t(indices_loc, palette_loc) { } typename base_t::result_type operator()(point_t const& p) const { return *this->_palette_loc.xy_at(*this->_indices_loc.xy_at(p), 0); } }; template< typename IndicesLoc , typename PaletteLoc > struct indexed_image_locator_type { using type = virtual_2d_locator < indexed_image_deref_fn, false >; }; template< typename Locator > // indexed_image_locator_type< ... >::type class indexed_image_view : public image_view< Locator > { public: using deref_fn_t = typename Locator::deref_fn_t; using indices_locator_t = typename deref_fn_t::indices_locator_t; using palette_locator_t = typename deref_fn_t::palette_locator_t; using const_t = indexed_image_view; using indices_view_t = image_view; using palette_view_t = image_view; indexed_image_view() : image_view< Locator >() , _num_colors( 0 ) {} indexed_image_view( const point_t& dimensions , std::size_t num_colors , const Locator& locator ) : image_view< Locator >( dimensions, locator ) , _num_colors( num_colors ) {} template< typename IndexedView > indexed_image_view( const IndexedView& iv ) : image_view< Locator >( iv ) , _num_colors( iv._num_colors ) {} std::size_t num_colors() const { return _num_colors; } const indices_locator_t& indices() const { return get_deref_fn().indices(); } const palette_locator_t& palette() const { return get_deref_fn().palette(); } indices_view_t get_indices_view() const { return indices_view_t(this->dimensions(), indices() );} palette_view_t get_palette_view() const { return palette_view_t(point_t(num_colors(), 1), palette());} private: const deref_fn_t& get_deref_fn() const { return this->pixels().deref_fn(); } private: template< typename Locator2 > friend class indexed_image_view; std::size_t _num_colors; }; // build an indexed_image_view from two views template indexed_image_view < typename indexed_image_locator_type < typename Index_View::locator , typename Palette_View::locator >::type > view(Index_View iv, Palette_View pv) { using view_t = indexed_image_view < typename indexed_image_locator_type < typename Index_View::locator, typename Palette_View::locator >::type >; using defer_fn_t = indexed_image_deref_fn < typename Index_View::locator, typename Palette_View::locator >; return view_t( iv.dimensions() , pv.dimensions().x , typename view_t::locator(point_t(0, 0), point_t(1, 1), defer_fn_t(iv.xy_at(0, 0), pv.xy_at(0, 0))) ); } template< typename Index , typename Pixel , typename IndicesAllocator = std::allocator< unsigned char > , typename PalleteAllocator = std::allocator< unsigned char > > class indexed_image { public: using indices_t = image; using palette_t = image; using indices_view_t = typename indices_t::view_t; using palette_view_t = typename palette_t::view_t; using indices_const_view_t = typename indices_t::const_view_t; using palette_const_view_t = typename palette_t::const_view_t; using indices_locator_t = typename indices_view_t::locator; using palette_locator_t = typename palette_view_t::locator; using locator_t = typename indexed_image_locator_type < indices_locator_t, palette_locator_t >::type; using x_coord_t = typename indices_t::coord_t; using y_coord_t = typename indices_t::coord_t; using view_t = indexed_image_view; using const_view_t = typename view_t::const_t; indexed_image( const x_coord_t width = 0 , const y_coord_t height = 0 , const std::size_t num_colors = 1 , const std::size_t indices_alignment = 0 , const std::size_t palette_alignment = 0 ) : _indices( width , height, indices_alignment, IndicesAllocator() ) , _palette( num_colors, 1, palette_alignment, PalleteAllocator() ) { init( point_t( width, height ), num_colors ); } indexed_image( const point_t& dimensions , const std::size_t num_colors = 1 , const std::size_t indices_alignment = 0 , const std::size_t palette_alignment = 0 ) : _indices( dimensions, indices_alignment, IndicesAllocator() ) , _palette( num_colors, 1, palette_alignment, PalleteAllocator() ) { init( dimensions, num_colors ); } indexed_image( const indexed_image& img ) : _indices( img._indices ) , _palette( img._palette ) {} template indexed_image( const indexed_image< Pixel2, Index2 >& img ) { _indices = img._indices; _palette = img._palette; } indexed_image& operator= ( const indexed_image& img ) { _indices = img._indices; _palette = img._palette; return *this; } indices_const_view_t get_indices_const_view() const { return static_cast< indices_const_view_t >( _view.get_indices_view()); } palette_const_view_t get_palette_const_view() const { return static_cast< palette_const_view_t >( _view.get_palette_view()); } indices_view_t get_indices_view() { return _view.get_indices_view(); } palette_view_t get_palette_view() { return _view.get_palette_view(); } public: view_t _view; private: void init( const point_t& dimensions , const std::size_t num_colors ) { using defer_fn_t = indexed_image_deref_fn < indices_locator_t, palette_locator_t >; defer_fn_t deref_fn( view( _indices ).xy_at( 0, 0 ) , view( _palette ).xy_at( 0, 0 ) ); locator_t locator( point_t( 0, 0 ) // p , point_t( 1, 1 ) // step , deref_fn ); _view = view_t( dimensions , num_colors , locator ); } private: indices_t _indices; palette_t _palette; }; template< typename Index , typename Pixel > inline const typename indexed_image< Index, Pixel >::view_t& view( indexed_image< Index, Pixel >& img ) { return img._view; } template< typename Index , typename Pixel > inline const typename indexed_image< Index, Pixel >::const_view_t const_view( indexed_image< Index, Pixel >& img ) { return static_cast< const typename indexed_image< Index, Pixel >::const_view_t>( img._view ); } // Whole image has one color and all indices are set to 0. template< typename Locator , typename Value > void fill_pixels( const indexed_image_view< Locator >& view , const Value& value ) { using view_t = indexed_image_view; fill_pixels( view.get_indices_view(), typename view_t::indices_view_t::value_type( 0 )); *view.get_palette_view().begin() = value; } } // namespace gil } // namespace boost #endif