2 // Copyright 2012 Christian Henning
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
8 #ifndef BOOST_GIL_EXTENSION_TOOLBOX_IMAGE_TYPES_INDEXED_IMAGE_HPP
9 #define BOOST_GIL_EXTENSION_TOOLBOX_IMAGE_TYPES_INDEXED_IMAGE_HPP
11 #include <boost/gil/extension/toolbox/metafunctions/is_bit_aligned.hpp>
13 #include <boost/gil/image.hpp>
14 #include <boost/gil/point.hpp>
15 #include <boost/gil/virtual_locator.hpp>
16 #include <boost/gil/detail/is_channel_integral.hpp>
17 #include <boost/gil/detail/mp11.hpp>
22 namespace boost { namespace gil {
24 template< typename Locator >
25 struct get_pixel_type_locator
27 using type = mp11::mp_if
29 typename is_bit_aligned<typename Locator::value_type>::type,
30 typename Locator::reference,
31 typename Locator::value_type
35 // used for virtual locator
36 template< typename IndicesLoc
39 struct indexed_image_deref_fn_base
41 using indices_locator_t = IndicesLoc;
42 using palette_locator_t = PaletteLoc;
43 //using index_t = typename get_pixel_type_locator<indices_locator_t>::type;
45 using const_t = indexed_image_deref_fn_base<IndicesLoc, PaletteLoc>;
46 using value_type = typename PaletteLoc::value_type;
47 using reference = value_type;
48 using const_reference = value_type;
49 using argument_type = point_t;
50 using result_type = reference;
52 static const bool is_mutable = false;
54 indexed_image_deref_fn_base() {}
56 indexed_image_deref_fn_base( const indices_locator_t& indices_loc
57 , const palette_locator_t& palette_loc
59 : _indices_loc( indices_loc )
60 , _palette_loc( palette_loc )
63 void set_indices( const indices_locator_t& indices_loc ) { _indices_loc = indices_loc; }
64 void set_palette( const palette_locator_t& palette_loc ) { _palette_loc = palette_loc; }
66 const indices_locator_t& indices() const { return _indices_loc; }
67 const palette_locator_t& palette() const { return _palette_loc; }
71 indices_locator_t _indices_loc;
72 palette_locator_t _palette_loc;
76 // used for virtual locator
77 template< typename IndicesLoc
79 , typename Enable = void // there is specialization for integral indices
81 struct indexed_image_deref_fn : indexed_image_deref_fn_base< IndicesLoc
85 using base_t = indexed_image_deref_fn_base
91 indexed_image_deref_fn()
95 indexed_image_deref_fn( const typename base_t::indices_locator_t& indices_loc
96 , const typename base_t::palette_locator_t& palette_loc
103 typename base_t::result_type operator()( const point_t& p ) const
105 return * this->_palette_loc.xy_at( at_c<0>( *this->_indices_loc.xy_at( p )), 0 );
110 template <typename IndicesLoc, typename PaletteLoc>
111 struct indexed_image_deref_fn
115 typename std::enable_if
117 detail::is_channel_integral<typename IndicesLoc::value_type>::value
119 > : indexed_image_deref_fn_base<IndicesLoc, PaletteLoc>
121 using base_t = indexed_image_deref_fn_base<IndicesLoc, PaletteLoc>;
123 indexed_image_deref_fn() : base_t() {}
125 indexed_image_deref_fn(
126 typename base_t::indices_locator_t const& indices_loc,
127 typename base_t::palette_locator_t const& palette_loc)
128 : base_t(indices_loc, palette_loc)
132 typename base_t::result_type operator()(point_t const& p) const
134 return *this->_palette_loc.xy_at(*this->_indices_loc.xy_at(p), 0);
138 template< typename IndicesLoc
139 , typename PaletteLoc
141 struct indexed_image_locator_type
143 using type = virtual_2d_locator
145 indexed_image_deref_fn<IndicesLoc, PaletteLoc>,
150 template< typename Locator > // indexed_image_locator_type< ... >::type
151 class indexed_image_view : public image_view< Locator >
155 using deref_fn_t = typename Locator::deref_fn_t;
156 using indices_locator_t = typename deref_fn_t::indices_locator_t;
157 using palette_locator_t = typename deref_fn_t::palette_locator_t;
159 using const_t = indexed_image_view<Locator>;
161 using indices_view_t = image_view<indices_locator_t>;
162 using palette_view_t = image_view<palette_locator_t>;
165 : image_view< Locator >()
169 indexed_image_view( const point_t& dimensions
170 , std::size_t num_colors
171 , const Locator& locator
173 : image_view< Locator >( dimensions, locator )
174 , _num_colors( num_colors )
177 template< typename IndexedView >
178 indexed_image_view( const IndexedView& iv )
179 : image_view< Locator >( iv )
180 , _num_colors( iv._num_colors )
183 std::size_t num_colors() const { return _num_colors; }
186 const indices_locator_t& indices() const { return get_deref_fn().indices(); }
187 const palette_locator_t& palette() const { return get_deref_fn().palette(); }
189 indices_view_t get_indices_view() const { return indices_view_t(this->dimensions(), indices() );}
190 palette_view_t get_palette_view() const { return palette_view_t(point_t(num_colors(), 1), palette());}
194 const deref_fn_t& get_deref_fn() const { return this->pixels().deref_fn(); }
198 template< typename Locator2 > friend class indexed_image_view;
200 std::size_t _num_colors;
203 // build an indexed_image_view from two views
204 template<typename Index_View, typename Palette_View>
207 typename indexed_image_locator_type
209 typename Index_View::locator
210 , typename Palette_View::locator
213 view(Index_View iv, Palette_View pv)
215 using view_t = indexed_image_view
217 typename indexed_image_locator_type
219 typename Index_View::locator,
220 typename Palette_View::locator
224 using defer_fn_t = indexed_image_deref_fn
226 typename Index_View::locator,
227 typename Palette_View::locator
233 , 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)))
237 template< typename Index
239 , typename IndicesAllocator = std::allocator< unsigned char >
240 , typename PalleteAllocator = std::allocator< unsigned char >
246 using indices_t = image<Index, false, IndicesAllocator>;
247 using palette_t = image<Pixel, false, PalleteAllocator>;
249 using indices_view_t = typename indices_t::view_t;
250 using palette_view_t = typename palette_t::view_t;
252 using indices_const_view_t = typename indices_t::const_view_t;
253 using palette_const_view_t = typename palette_t::const_view_t;
255 using indices_locator_t = typename indices_view_t::locator;
256 using palette_locator_t = typename palette_view_t::locator;
258 using locator_t = typename indexed_image_locator_type
264 using x_coord_t = typename indices_t::coord_t;
265 using y_coord_t = typename indices_t::coord_t;
268 using view_t = indexed_image_view<locator_t>;
269 using const_view_t = typename view_t::const_t;
271 indexed_image( const x_coord_t width = 0
272 , const y_coord_t height = 0
273 , const std::size_t num_colors = 1
274 , const std::size_t indices_alignment = 0
275 , const std::size_t palette_alignment = 0
277 : _indices( width , height, indices_alignment, IndicesAllocator() )
278 , _palette( num_colors, 1, palette_alignment, PalleteAllocator() )
280 init( point_t( width, height ), num_colors );
283 indexed_image( const point_t& dimensions
284 , const std::size_t num_colors = 1
285 , const std::size_t indices_alignment = 0
286 , const std::size_t palette_alignment = 0
288 : _indices( dimensions, indices_alignment, IndicesAllocator() )
289 , _palette( num_colors, 1, palette_alignment, PalleteAllocator() )
291 init( dimensions, num_colors );
294 indexed_image( const indexed_image& img )
295 : _indices( img._indices )
296 , _palette( img._palette )
299 template <typename Pixel2, typename Index2>
300 indexed_image( const indexed_image< Pixel2, Index2 >& img )
302 _indices = img._indices;
303 _palette = img._palette;
306 indexed_image& operator= ( const indexed_image& img )
308 _indices = img._indices;
309 _palette = img._palette;
314 indices_const_view_t get_indices_const_view() const { return static_cast< indices_const_view_t >( _view.get_indices_view()); }
315 palette_const_view_t get_palette_const_view() const { return static_cast< palette_const_view_t >( _view.get_palette_view()); }
317 indices_view_t get_indices_view() { return _view.get_indices_view(); }
318 palette_view_t get_palette_view() { return _view.get_palette_view(); }
326 void init( const point_t& dimensions
327 , const std::size_t num_colors
330 using defer_fn_t = indexed_image_deref_fn
336 defer_fn_t deref_fn( view( _indices ).xy_at( 0, 0 )
337 , view( _palette ).xy_at( 0, 0 )
340 locator_t locator( point_t( 0, 0 ) // p
341 , point_t( 1, 1 ) // step
345 _view = view_t( dimensions
357 template< typename Index
361 const typename indexed_image< Index, Pixel >::view_t& view( indexed_image< Index, Pixel >& img )
366 template< typename Index
370 const typename indexed_image< Index, Pixel >::const_view_t const_view( indexed_image< Index, Pixel >& img )
372 return static_cast< const typename indexed_image< Index, Pixel >::const_view_t>( img._view );
375 // Whole image has one color and all indices are set to 0.
376 template< typename Locator
379 void fill_pixels( const indexed_image_view< Locator >& view
383 using view_t = indexed_image_view<Locator>;
385 fill_pixels( view.get_indices_view(), typename view_t::indices_view_t::value_type( 0 ));
386 *view.get_palette_view().begin() = value;