Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / gil / extension / toolbox / image_types / indexed_image.hpp
1 //
2 // Copyright 2012 Christian Henning
3 //
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
7 //
8 #ifndef BOOST_GIL_EXTENSION_TOOLBOX_IMAGE_TYPES_INDEXED_IMAGE_HPP
9 #define BOOST_GIL_EXTENSION_TOOLBOX_IMAGE_TYPES_INDEXED_IMAGE_HPP
10
11 #include <boost/gil/extension/toolbox/metafunctions/is_bit_aligned.hpp>
12
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>
18
19 #include <cstddef>
20 #include <memory>
21
22 namespace boost { namespace gil {
23
24 template< typename Locator >
25 struct get_pixel_type_locator
26 {
27     using type = mp11::mp_if
28         <
29             typename is_bit_aligned<typename Locator::value_type>::type,
30             typename Locator::reference,
31             typename Locator::value_type
32         >;
33 };
34
35 // used for virtual locator
36 template< typename IndicesLoc
37         , typename PaletteLoc
38         >
39 struct indexed_image_deref_fn_base
40 {
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;
44
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;
51
52     static const bool is_mutable = false;
53
54     indexed_image_deref_fn_base() {}
55
56     indexed_image_deref_fn_base( const indices_locator_t& indices_loc
57                                , const palette_locator_t& palette_loc
58                                )
59     : _indices_loc( indices_loc )
60     , _palette_loc( palette_loc )
61     {}
62
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; }
65
66     const indices_locator_t& indices() const { return _indices_loc; }
67     const palette_locator_t& palette() const { return _palette_loc; }
68
69 protected:
70
71     indices_locator_t _indices_loc;
72     palette_locator_t _palette_loc;
73 };
74
75
76 // used for virtual locator
77 template< typename IndicesLoc
78         , typename PaletteLoc
79         , typename Enable = void // there is specialization for integral indices
80         >
81 struct indexed_image_deref_fn : indexed_image_deref_fn_base< IndicesLoc
82                                                            , PaletteLoc
83                                                            >
84 {
85     using base_t = indexed_image_deref_fn_base
86         <
87             IndicesLoc,
88             PaletteLoc
89         >;
90
91     indexed_image_deref_fn()
92     : base_t()
93     {}
94
95     indexed_image_deref_fn( const typename base_t::indices_locator_t& indices_loc
96                           , const typename base_t::palette_locator_t& palette_loc
97                           )
98     : base_t( indices_loc
99             , palette_loc
100             )
101     {}
102
103     typename base_t::result_type operator()( const point_t& p ) const
104     {
105         return * this->_palette_loc.xy_at( at_c<0>( *this->_indices_loc.xy_at( p )), 0 );
106     }
107 };
108
109
110 template <typename IndicesLoc, typename PaletteLoc>
111 struct indexed_image_deref_fn
112 <
113     IndicesLoc,
114     PaletteLoc,
115     typename std::enable_if
116     <
117         detail::is_channel_integral<typename IndicesLoc::value_type>::value
118     >::type
119 > : indexed_image_deref_fn_base<IndicesLoc, PaletteLoc>
120 {
121     using base_t = indexed_image_deref_fn_base<IndicesLoc, PaletteLoc>;
122
123     indexed_image_deref_fn() : base_t() {}
124
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)
129     {
130     }
131
132     typename base_t::result_type operator()(point_t const& p) const
133     {
134         return *this->_palette_loc.xy_at(*this->_indices_loc.xy_at(p), 0);
135     }
136 };
137
138 template< typename IndicesLoc
139         , typename PaletteLoc
140         >
141 struct indexed_image_locator_type
142 {
143     using type = virtual_2d_locator
144         <
145             indexed_image_deref_fn<IndicesLoc, PaletteLoc>,
146             false
147         >;
148 };
149
150 template< typename Locator > // indexed_image_locator_type< ... >::type
151 class indexed_image_view : public image_view< Locator >
152 {
153 public:
154
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;
158
159     using const_t = indexed_image_view<Locator>;
160
161     using indices_view_t = image_view<indices_locator_t>;
162     using palette_view_t = image_view<palette_locator_t>;
163
164     indexed_image_view()
165     : image_view< Locator >()
166     , _num_colors( 0 )
167     {}
168
169     indexed_image_view( const point_t& dimensions
170                       , std::size_t    num_colors
171                       , const Locator& locator
172                       )
173     : image_view< Locator >( dimensions, locator )
174     , _num_colors( num_colors )
175     {}
176
177     template< typename IndexedView >
178     indexed_image_view( const IndexedView& iv )
179     : image_view< Locator >( iv )
180     , _num_colors( iv._num_colors )
181     {}
182
183     std::size_t num_colors() const { return _num_colors; }
184
185
186     const indices_locator_t& indices() const { return get_deref_fn().indices(); }
187     const palette_locator_t& palette() const { return get_deref_fn().palette(); }
188
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());}
191
192 private:
193
194     const deref_fn_t& get_deref_fn() const { return this->pixels().deref_fn(); }
195
196 private:
197
198     template< typename Locator2 > friend class indexed_image_view;
199
200     std::size_t _num_colors;
201 };
202
203 // build an indexed_image_view from two views
204 template<typename Index_View, typename Palette_View>
205 indexed_image_view
206 <
207     typename indexed_image_locator_type
208     <
209         typename Index_View::locator
210         , typename Palette_View::locator
211     >::type
212 >
213     view(Index_View iv, Palette_View pv)
214 {
215     using view_t = indexed_image_view
216         <
217             typename indexed_image_locator_type
218                 <
219                     typename Index_View::locator,
220                     typename Palette_View::locator
221                 >::type
222         >;
223
224     using defer_fn_t = indexed_image_deref_fn
225         <
226             typename Index_View::locator,
227             typename Palette_View::locator
228         >;
229
230     return view_t(
231         iv.dimensions()
232         , pv.dimensions().x
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)))
234     );
235 }
236
237 template< typename Index
238         , typename Pixel
239         , typename IndicesAllocator = std::allocator< unsigned char >
240         , typename PalleteAllocator = std::allocator< unsigned char >
241         >
242 class indexed_image
243 {
244 public:
245
246     using indices_t = image<Index, false, IndicesAllocator>;
247     using palette_t = image<Pixel, false, PalleteAllocator>;
248
249     using indices_view_t = typename indices_t::view_t;
250     using palette_view_t = typename palette_t::view_t;
251
252     using indices_const_view_t = typename indices_t::const_view_t;
253     using palette_const_view_t = typename palette_t::const_view_t;
254
255     using indices_locator_t = typename indices_view_t::locator;
256     using palette_locator_t = typename palette_view_t::locator;
257
258     using locator_t = typename indexed_image_locator_type
259         <
260             indices_locator_t,
261             palette_locator_t
262         >::type;
263
264     using x_coord_t = typename indices_t::coord_t;
265     using y_coord_t = typename indices_t::coord_t;
266
267
268     using view_t = indexed_image_view<locator_t>;
269     using const_view_t = typename view_t::const_t;
270
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
276                  )
277     : _indices( width     , height, indices_alignment, IndicesAllocator() )
278     , _palette( num_colors,      1, palette_alignment, PalleteAllocator() )
279     {
280         init( point_t( width, height ), num_colors );
281     }
282
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
287                  )
288     : _indices( dimensions,    indices_alignment, IndicesAllocator() )
289     , _palette( num_colors, 1, palette_alignment, PalleteAllocator() )
290     {
291         init( dimensions, num_colors );
292     }
293
294     indexed_image( const indexed_image& img )
295     : _indices( img._indices )
296     , _palette( img._palette )
297     {}
298
299     template <typename Pixel2, typename Index2>
300     indexed_image( const indexed_image< Pixel2, Index2 >& img )
301     {
302         _indices = img._indices;
303         _palette = img._palette;
304     }
305
306     indexed_image& operator= ( const indexed_image& img )
307     {
308         _indices = img._indices;
309         _palette = img._palette;
310
311         return *this;
312     }
313
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()); }
316
317     indices_view_t get_indices_view() { return _view.get_indices_view(); }
318     palette_view_t get_palette_view() { return _view.get_palette_view(); }
319
320 public:
321
322     view_t _view;
323
324 private:
325
326     void init( const point_t&    dimensions
327              , const std::size_t num_colors
328              )
329     {
330         using defer_fn_t = indexed_image_deref_fn
331             <
332                 indices_locator_t,
333                 palette_locator_t
334             >;
335
336         defer_fn_t deref_fn( view( _indices ).xy_at( 0, 0 )
337                            , view( _palette ).xy_at( 0, 0 )
338                            );
339
340         locator_t locator( point_t( 0, 0 ) // p
341                          , point_t( 1, 1 ) // step
342                          , deref_fn
343                          );
344
345         _view = view_t( dimensions
346                       , num_colors
347                       , locator
348                       );
349     }
350
351 private:
352
353     indices_t _indices;
354     palette_t _palette;
355 };
356
357 template< typename Index
358         , typename Pixel
359         >
360 inline
361 const typename indexed_image< Index, Pixel >::view_t& view( indexed_image< Index, Pixel >& img )
362 {
363     return img._view;
364 }
365
366 template< typename Index
367         , typename Pixel
368         >
369 inline
370 const typename indexed_image< Index, Pixel >::const_view_t const_view( indexed_image< Index, Pixel >& img )
371 {
372     return static_cast< const typename indexed_image< Index, Pixel >::const_view_t>( img._view );
373 }
374
375 // Whole image has one color and all indices are set to 0.
376 template< typename Locator
377         , typename Value
378         >
379 void fill_pixels( const indexed_image_view< Locator >& view
380                 , const Value&                         value
381                 )
382 {
383     using view_t = indexed_image_view<Locator>;
384
385     fill_pixels( view.get_indices_view(), typename view_t::indices_view_t::value_type( 0 ));
386     *view.get_palette_view().begin() = value;
387 }
388
389 } // namespace gil
390 } // namespace boost
391
392 #endif