indexed_image.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  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. #include <boost/gil/extension/toolbox/metafunctions/is_bit_aligned.hpp>
  11. #include <boost/gil/image.hpp>
  12. #include <boost/gil/point.hpp>
  13. #include <boost/gil/virtual_locator.hpp>
  14. #include <boost/gil/detail/is_channel_integral.hpp>
  15. #include <boost/gil/detail/mp11.hpp>
  16. #include <cstddef>
  17. #include <memory>
  18. namespace boost { namespace gil {
  19. template< typename Locator >
  20. struct get_pixel_type_locator
  21. {
  22. using type = mp11::mp_if
  23. <
  24. typename is_bit_aligned<typename Locator::value_type>::type,
  25. typename Locator::reference,
  26. typename Locator::value_type
  27. >;
  28. };
  29. // used for virtual locator
  30. template< typename IndicesLoc
  31. , typename PaletteLoc
  32. >
  33. struct indexed_image_deref_fn_base
  34. {
  35. using indices_locator_t = IndicesLoc;
  36. using palette_locator_t = PaletteLoc;
  37. //using index_t = typename get_pixel_type_locator<indices_locator_t>::type;
  38. using const_t = indexed_image_deref_fn_base<IndicesLoc, PaletteLoc>;
  39. using value_type = typename PaletteLoc::value_type;
  40. using reference = value_type;
  41. using const_reference = value_type;
  42. using argument_type = point_t;
  43. using result_type = reference;
  44. static const bool is_mutable = false;
  45. indexed_image_deref_fn_base() {}
  46. indexed_image_deref_fn_base( const indices_locator_t& indices_loc
  47. , const palette_locator_t& palette_loc
  48. )
  49. : _indices_loc( indices_loc )
  50. , _palette_loc( palette_loc )
  51. {}
  52. void set_indices( const indices_locator_t& indices_loc ) { _indices_loc = indices_loc; }
  53. void set_palette( const palette_locator_t& palette_loc ) { _palette_loc = palette_loc; }
  54. const indices_locator_t& indices() const { return _indices_loc; }
  55. const palette_locator_t& palette() const { return _palette_loc; }
  56. protected:
  57. indices_locator_t _indices_loc;
  58. palette_locator_t _palette_loc;
  59. };
  60. // used for virtual locator
  61. template< typename IndicesLoc
  62. , typename PaletteLoc
  63. , typename Enable = void // there is specialization for integral indices
  64. >
  65. struct indexed_image_deref_fn : indexed_image_deref_fn_base< IndicesLoc
  66. , PaletteLoc
  67. >
  68. {
  69. using base_t = indexed_image_deref_fn_base
  70. <
  71. IndicesLoc,
  72. PaletteLoc
  73. >;
  74. indexed_image_deref_fn()
  75. : base_t()
  76. {}
  77. indexed_image_deref_fn( const typename base_t::indices_locator_t& indices_loc
  78. , const typename base_t::palette_locator_t& palette_loc
  79. )
  80. : base_t( indices_loc
  81. , palette_loc
  82. )
  83. {}
  84. typename base_t::result_type operator()( const point_t& p ) const
  85. {
  86. return * this->_palette_loc.xy_at( at_c<0>( *this->_indices_loc.xy_at( p )), 0 );
  87. }
  88. };
  89. template <typename IndicesLoc, typename PaletteLoc>
  90. struct indexed_image_deref_fn
  91. <
  92. IndicesLoc,
  93. PaletteLoc,
  94. typename std::enable_if
  95. <
  96. detail::is_channel_integral<typename IndicesLoc::value_type>::value
  97. >::type
  98. > : indexed_image_deref_fn_base<IndicesLoc, PaletteLoc>
  99. {
  100. using base_t = indexed_image_deref_fn_base<IndicesLoc, PaletteLoc>;
  101. indexed_image_deref_fn() : base_t() {}
  102. indexed_image_deref_fn(
  103. typename base_t::indices_locator_t const& indices_loc,
  104. typename base_t::palette_locator_t const& palette_loc)
  105. : base_t(indices_loc, palette_loc)
  106. {
  107. }
  108. typename base_t::result_type operator()(point_t const& p) const
  109. {
  110. return *this->_palette_loc.xy_at(*this->_indices_loc.xy_at(p), 0);
  111. }
  112. };
  113. template< typename IndicesLoc
  114. , typename PaletteLoc
  115. >
  116. struct indexed_image_locator_type
  117. {
  118. using type = virtual_2d_locator
  119. <
  120. indexed_image_deref_fn<IndicesLoc, PaletteLoc>,
  121. false
  122. >;
  123. };
  124. template< typename Locator > // indexed_image_locator_type< ... >::type
  125. class indexed_image_view : public image_view< Locator >
  126. {
  127. public:
  128. using deref_fn_t = typename Locator::deref_fn_t;
  129. using indices_locator_t = typename deref_fn_t::indices_locator_t;
  130. using palette_locator_t = typename deref_fn_t::palette_locator_t;
  131. using const_t = indexed_image_view<Locator>;
  132. using indices_view_t = image_view<indices_locator_t>;
  133. using palette_view_t = image_view<palette_locator_t>;
  134. indexed_image_view()
  135. : image_view< Locator >()
  136. , _num_colors( 0 )
  137. {}
  138. indexed_image_view( const point_t& dimensions
  139. , std::size_t num_colors
  140. , const Locator& locator
  141. )
  142. : image_view< Locator >( dimensions, locator )
  143. , _num_colors( num_colors )
  144. {}
  145. template< typename IndexedView >
  146. indexed_image_view( const IndexedView& iv )
  147. : image_view< Locator >( iv )
  148. , _num_colors( iv._num_colors )
  149. {}
  150. std::size_t num_colors() const { return _num_colors; }
  151. const indices_locator_t& indices() const { return get_deref_fn().indices(); }
  152. const palette_locator_t& palette() const { return get_deref_fn().palette(); }
  153. indices_view_t get_indices_view() const { return indices_view_t(this->dimensions(), indices() );}
  154. palette_view_t get_palette_view() const { return palette_view_t(point_t(num_colors(), 1), palette());}
  155. private:
  156. const deref_fn_t& get_deref_fn() const { return this->pixels().deref_fn(); }
  157. private:
  158. template< typename Locator2 > friend class indexed_image_view;
  159. std::size_t _num_colors;
  160. };
  161. // build an indexed_image_view from two views
  162. template<typename Index_View, typename Palette_View>
  163. indexed_image_view
  164. <
  165. typename indexed_image_locator_type
  166. <
  167. typename Index_View::locator
  168. , typename Palette_View::locator
  169. >::type
  170. >
  171. view(Index_View iv, Palette_View pv)
  172. {
  173. using view_t = indexed_image_view
  174. <
  175. typename indexed_image_locator_type
  176. <
  177. typename Index_View::locator,
  178. typename Palette_View::locator
  179. >::type
  180. >;
  181. using defer_fn_t = indexed_image_deref_fn
  182. <
  183. typename Index_View::locator,
  184. typename Palette_View::locator
  185. >;
  186. return view_t(
  187. iv.dimensions()
  188. , pv.dimensions().x
  189. , 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)))
  190. );
  191. }
  192. template< typename Index
  193. , typename Pixel
  194. , typename IndicesAllocator = std::allocator< unsigned char >
  195. , typename PalleteAllocator = std::allocator< unsigned char >
  196. >
  197. class indexed_image
  198. {
  199. public:
  200. using indices_t = image<Index, false, IndicesAllocator>;
  201. using palette_t = image<Pixel, false, PalleteAllocator>;
  202. using indices_view_t = typename indices_t::view_t;
  203. using palette_view_t = typename palette_t::view_t;
  204. using indices_const_view_t = typename indices_t::const_view_t;
  205. using palette_const_view_t = typename palette_t::const_view_t;
  206. using indices_locator_t = typename indices_view_t::locator;
  207. using palette_locator_t = typename palette_view_t::locator;
  208. using locator_t = typename indexed_image_locator_type
  209. <
  210. indices_locator_t,
  211. palette_locator_t
  212. >::type;
  213. using x_coord_t = typename indices_t::coord_t;
  214. using y_coord_t = typename indices_t::coord_t;
  215. using view_t = indexed_image_view<locator_t>;
  216. using const_view_t = typename view_t::const_t;
  217. indexed_image( const x_coord_t width = 0
  218. , const y_coord_t height = 0
  219. , const std::size_t num_colors = 1
  220. , const std::size_t indices_alignment = 0
  221. , const std::size_t palette_alignment = 0
  222. )
  223. : _indices( width , height, indices_alignment, IndicesAllocator() )
  224. , _palette( num_colors, 1, palette_alignment, PalleteAllocator() )
  225. {
  226. init( point_t( width, height ), num_colors );
  227. }
  228. indexed_image( const point_t& dimensions
  229. , const std::size_t num_colors = 1
  230. , const std::size_t indices_alignment = 0
  231. , const std::size_t palette_alignment = 0
  232. )
  233. : _indices( dimensions, indices_alignment, IndicesAllocator() )
  234. , _palette( num_colors, 1, palette_alignment, PalleteAllocator() )
  235. {
  236. init( dimensions, num_colors );
  237. }
  238. indexed_image( const indexed_image& img )
  239. : _indices( img._indices )
  240. , _palette( img._palette )
  241. {}
  242. template <typename Pixel2, typename Index2>
  243. indexed_image( const indexed_image< Pixel2, Index2 >& img )
  244. {
  245. _indices = img._indices;
  246. _palette = img._palette;
  247. }
  248. indexed_image& operator= ( const indexed_image& img )
  249. {
  250. _indices = img._indices;
  251. _palette = img._palette;
  252. return *this;
  253. }
  254. indices_const_view_t get_indices_const_view() const { return static_cast< indices_const_view_t >( _view.get_indices_view()); }
  255. palette_const_view_t get_palette_const_view() const { return static_cast< palette_const_view_t >( _view.get_palette_view()); }
  256. indices_view_t get_indices_view() { return _view.get_indices_view(); }
  257. palette_view_t get_palette_view() { return _view.get_palette_view(); }
  258. public:
  259. view_t _view;
  260. private:
  261. void init( const point_t& dimensions
  262. , const std::size_t num_colors
  263. )
  264. {
  265. using defer_fn_t = indexed_image_deref_fn
  266. <
  267. indices_locator_t,
  268. palette_locator_t
  269. >;
  270. defer_fn_t deref_fn( view( _indices ).xy_at( 0, 0 )
  271. , view( _palette ).xy_at( 0, 0 )
  272. );
  273. locator_t locator( point_t( 0, 0 ) // p
  274. , point_t( 1, 1 ) // step
  275. , deref_fn
  276. );
  277. _view = view_t( dimensions
  278. , num_colors
  279. , locator
  280. );
  281. }
  282. private:
  283. indices_t _indices;
  284. palette_t _palette;
  285. };
  286. template< typename Index
  287. , typename Pixel
  288. >
  289. inline
  290. const typename indexed_image< Index, Pixel >::view_t& view( indexed_image< Index, Pixel >& img )
  291. {
  292. return img._view;
  293. }
  294. template< typename Index
  295. , typename Pixel
  296. >
  297. inline
  298. const typename indexed_image< Index, Pixel >::const_view_t const_view( indexed_image< Index, Pixel >& img )
  299. {
  300. return static_cast< const typename indexed_image< Index, Pixel >::const_view_t>( img._view );
  301. }
  302. // Whole image has one color and all indices are set to 0.
  303. template< typename Locator
  304. , typename Value
  305. >
  306. void fill_pixels( const indexed_image_view< Locator >& view
  307. , const Value& value
  308. )
  309. {
  310. using view_t = indexed_image_view<Locator>;
  311. fill_pixels( view.get_indices_view(), typename view_t::indices_view_t::value_type( 0 ));
  312. *view.get_palette_view().begin() = value;
  313. }
  314. } // namespace gil
  315. } // namespace boost
  316. #endif