subchroma_image.hpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. //
  2. // Copyright 2013 Christian Henning and Juan V. Puertos
  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_SUBCHROMA_IMAGE_HPP
  9. #define BOOST_GIL_EXTENSION_TOOLBOX_IMAGE_TYPES_SUBCHROMA_IMAGE_HPP
  10. #include <boost/gil/dynamic_step.hpp>
  11. #include <boost/gil/image.hpp>
  12. #include <boost/gil/image_view.hpp>
  13. #include <boost/gil/point.hpp>
  14. #include <boost/gil/virtual_locator.hpp>
  15. #include <boost/gil/detail/mp11.hpp>
  16. #include <cstddef>
  17. #include <memory>
  18. #include <type_traits>
  19. namespace boost { namespace gil {
  20. namespace detail {
  21. template< int J, int A, int B>
  22. struct scaling_factors
  23. {
  24. static_assert(std::integral_constant<int, J>::value == 4, "");
  25. static_assert(
  26. std::integral_constant<int, A>::value == 4 ||
  27. std::integral_constant<int, A>::value == 2 ||
  28. std::integral_constant<int, A>::value == 1,
  29. "");
  30. static_assert(
  31. std::integral_constant<int, B>::value == 4 ||
  32. std::integral_constant<int, B>::value == 2 ||
  33. std::integral_constant<int, B>::value == 1 ||
  34. std::integral_constant<int, B>::value == 0,
  35. "");
  36. static constexpr int ss_X =
  37. std::integral_constant<int, J>::value / std::integral_constant<int, A>::value;
  38. static constexpr int ss_Y =
  39. mp11::mp_if_c
  40. <
  41. std::integral_constant<int, B>::value == 0,
  42. std::integral_constant<int, 2>,
  43. mp11::mp_if_c
  44. <
  45. std::integral_constant<int, A>::value == std::integral_constant<int, B>::value,
  46. std::integral_constant<int, 1>,
  47. std::integral_constant<int, 4>
  48. >
  49. >::value;
  50. };
  51. } // namespace detail
  52. ////////////////////////////////////////////////////////////////////////////////////////
  53. /// \class subchroma_image_deref_fn
  54. /// \ingroup PixelLocatorModel PixelBasedModel
  55. /// \brief Used for virtual_2D_locator
  56. ///
  57. ////////////////////////////////////////////////////////////////////////////////////////
  58. template< typename Locator
  59. , typename Factors
  60. >
  61. struct subchroma_image_deref_fn
  62. {
  63. using plane_locator_t = gray8_view_t::locator;
  64. using const_t = subchroma_image_deref_fn<Locator, Factors>;
  65. using value_type = typename Locator::value_type;
  66. using reference = value_type;
  67. using const_reference = value_type;
  68. using argument_type = point_t;
  69. using result_type = reference;
  70. static const bool is_mutable = false;
  71. /// default constructor
  72. subchroma_image_deref_fn() {}
  73. /// constructor
  74. subchroma_image_deref_fn( const plane_locator_t& y_locator
  75. , const plane_locator_t& v_locator
  76. , const plane_locator_t& u_locator
  77. )
  78. : _y_locator( y_locator )
  79. , _v_locator( v_locator )
  80. , _u_locator( u_locator )
  81. {}
  82. /// operator()
  83. result_type operator()( const point_t& p ) const
  84. {
  85. using scaling_factors_t = detail::scaling_factors
  86. <
  87. mp11::mp_at_c<Factors, 0>::value,
  88. mp11::mp_at_c<Factors, 1>::value,
  89. mp11::mp_at_c<Factors, 2>::value
  90. >;
  91. plane_locator_t y = _y_locator.xy_at( p );
  92. plane_locator_t v = _v_locator.xy_at( p.x / scaling_factors_t::ss_X, p.y / scaling_factors_t::ss_X );
  93. plane_locator_t u = _u_locator.xy_at( p.x / scaling_factors_t::ss_X, p.y / scaling_factors_t::ss_X );
  94. return value_type( at_c< 0 >( *y )
  95. , at_c< 0 >( *v )
  96. , at_c< 0 >( *u )
  97. );
  98. }
  99. ///
  100. const plane_locator_t& y_locator() const { return _y_locator; }
  101. const plane_locator_t& v_locator() const { return _v_locator; }
  102. const plane_locator_t& u_locator() const { return _u_locator; }
  103. private:
  104. plane_locator_t _y_locator;
  105. plane_locator_t _v_locator;
  106. plane_locator_t _u_locator;
  107. };
  108. ////////////////////////////////////////////////////////////////////////////////////////
  109. /// \class subchroma_image_locator_type
  110. /// \ingroup PixelLocatorModel PixelBasedModel
  111. /// \brief
  112. ///
  113. ////////////////////////////////////////////////////////////////////////////////////////
  114. template< typename Locator
  115. , typename Factors
  116. >
  117. struct subchroma_image_locator
  118. {
  119. using type = virtual_2d_locator
  120. <
  121. subchroma_image_deref_fn<Locator, Factors>, // Deref
  122. false // IsTransposed
  123. >;
  124. };
  125. /////////////////////////////
  126. // PixelBasedConcept
  127. /////////////////////////////
  128. template < typename Locator, typename Factors >
  129. struct channel_type< subchroma_image_locator< Locator, Factors > >
  130. : public channel_type< typename subchroma_image_locator< Locator, Factors >::type > {};
  131. template < typename Locator, typename Factors >
  132. struct color_space_type< subchroma_image_locator< Locator, Factors > >
  133. : public color_space_type< typename subchroma_image_locator< Locator, Factors >::type > {};
  134. template < typename Locator, typename Factors >
  135. struct channel_mapping_type< subchroma_image_locator< Locator, Factors > >
  136. : public channel_mapping_type< typename subchroma_image_locator< Locator, Factors >::type > {};
  137. template < typename Locator, typename Factors >
  138. struct is_planar< subchroma_image_locator< Locator, Factors > >
  139. : public is_planar< typename subchroma_image_locator< Locator, Factors >::type > {};
  140. /////////////////////////////
  141. // HasDynamicXStepTypeConcept
  142. /////////////////////////////
  143. template < typename Locator, typename Factors >
  144. struct dynamic_x_step_type< subchroma_image_locator< Locator, Factors > >
  145. {
  146. using type = typename subchroma_image_locator<Locator, Factors>::type;
  147. };
  148. /////////////////////////////
  149. // HasDynamicYStepTypeConcept
  150. /////////////////////////////
  151. template < typename Locator, typename Factors >
  152. struct dynamic_y_step_type< subchroma_image_locator< Locator, Factors > >
  153. {
  154. using type = typename subchroma_image_locator<Locator, Factors>::type;
  155. };
  156. /////////////////////////////
  157. // HasTransposedTypeConcept
  158. /////////////////////////////
  159. template < typename Locator, typename Factors >
  160. struct transposed_type< subchroma_image_locator< Locator, Factors > >
  161. {
  162. using type = typename subchroma_image_locator<Locator, Factors>::type;
  163. };
  164. //////////////////////////////////
  165. ////////////////////////////////////////////////////////////////////////////////////////
  166. /// \class subchroma_image_view
  167. /// \ingroup ImageViewModel PixelBasedModel
  168. /// \brief A lightweight object that interprets a subchroma image.
  169. ///
  170. ////////////////////////////////////////////////////////////////////////////////////////
  171. template
  172. <
  173. typename Locator,
  174. typename Factors = mp11::mp_list_c<int, 4, 4, 4>
  175. >
  176. class subchroma_image_view : public image_view<Locator>
  177. {
  178. public:
  179. using locator = Locator;
  180. using deref_fn_t = typename locator::deref_fn_t;
  181. using plane_locator_t = typename deref_fn_t::plane_locator_t;
  182. using const_t = subchroma_image_view<Locator, Factors>;
  183. using plane_view_t = image_view<plane_locator_t>;
  184. /// default constructor
  185. subchroma_image_view()
  186. : image_view< Locator >()
  187. {}
  188. /// constructor
  189. subchroma_image_view( const point_t& y_dimensions
  190. , const point_t& v_dimensions
  191. , const point_t& u_dimensions
  192. , const Locator& locator
  193. )
  194. : image_view< Locator >( y_dimensions, locator )
  195. , _y_dimensions( y_dimensions )
  196. , _v_dimensions( v_dimensions )
  197. , _u_dimensions( u_dimensions )
  198. {}
  199. /// copy constructor
  200. template< typename Subchroma_View >
  201. subchroma_image_view( const Subchroma_View& v )
  202. : image_view< locator >( v )
  203. {}
  204. const point_t& v_ssfactors() const { return point_t( get_deref_fn().vx_ssfactor(), get_deref_fn().vx_ssfactor() ); }
  205. const point_t& u_ssfactors() const { return point_t( get_deref_fn().ux_ssfactor(), get_deref_fn().ux_ssfactor() ); }
  206. const point_t& y_dimension() const { return _y_dimensions; }
  207. const point_t& v_dimension() const { return _v_dimensions; }
  208. const point_t& u_dimension() const { return _u_dimensions; }
  209. const plane_locator_t& y_plane() const { return get_deref_fn().y_locator(); }
  210. const plane_locator_t& v_plane() const { return get_deref_fn().v_locator(); }
  211. const plane_locator_t& u_plane() const { return get_deref_fn().u_locator(); }
  212. const plane_view_t y_plane_view() const { return plane_view_t( _y_dimensions, y_plane() ); }
  213. const plane_view_t v_plane_view() const { return plane_view_t( _v_dimensions, v_plane() ); }
  214. const plane_view_t u_plane_view() const { return plane_view_t( _u_dimensions, u_plane() ); }
  215. private:
  216. const deref_fn_t& get_deref_fn() const { return this->pixels().deref_fn(); }
  217. private:
  218. point_t _y_dimensions;
  219. point_t _v_dimensions;
  220. point_t _u_dimensions;
  221. };
  222. /////////////////////////////
  223. // PixelBasedConcept
  224. /////////////////////////////
  225. template < typename Locator, typename Factors >
  226. struct channel_type< subchroma_image_view< Locator, Factors > >
  227. : public channel_type< Locator > {};
  228. template < typename Locator, typename Factors >
  229. struct color_space_type< subchroma_image_view< Locator, Factors > >
  230. : public color_space_type< Locator > {};
  231. template < typename Locator, typename Factors >
  232. struct channel_mapping_type< subchroma_image_view< Locator, Factors > >
  233. : public channel_mapping_type< Locator > {};
  234. template < typename Locator, typename Factors >
  235. struct is_planar< subchroma_image_view< Locator, Factors > >
  236. : public is_planar< Locator > {};
  237. /////////////////////////////
  238. // HasDynamicXStepTypeConcept
  239. /////////////////////////////
  240. template < typename Locator, typename Factors >
  241. struct dynamic_x_step_type< subchroma_image_view< Locator, Factors > >
  242. {
  243. using type = image_view<typename dynamic_x_step_type<Locator>::type>;
  244. };
  245. /////////////////////////////
  246. // HasDynamicYStepTypeConcept
  247. /////////////////////////////
  248. template < typename Locator, typename Factors >
  249. struct dynamic_y_step_type< subchroma_image_view< Locator, Factors > >
  250. {
  251. using type = image_view<typename dynamic_y_step_type<Locator>::type>;
  252. };
  253. /////////////////////////////
  254. // HasTransposedTypeConcept
  255. /////////////////////////////
  256. template < typename Locator, typename Factors >
  257. struct transposed_type< subchroma_image_view< Locator, Factors > >
  258. {
  259. using type = image_view<typename transposed_type<Locator>::type>;
  260. };
  261. ////////////////////////////////////////////////////////////////////////////////////////
  262. /// \ingroup ImageModel PixelBasedModel
  263. /// \brief container interface over image view. Models ImageConcept, PixelBasedConcept
  264. ///
  265. /// A subchroma image holds a bunch of planes which don't need to have the same resolution.
  266. ///
  267. ////////////////////////////////////////////////////////////////////////////////////////
  268. template
  269. <
  270. typename Pixel,
  271. typename Factors = mp11::mp_list_c<int, 4, 4, 4>,
  272. typename Allocator = std::allocator<unsigned char>
  273. >
  274. class subchroma_image : public detail::scaling_factors
  275. <
  276. mp11::mp_at_c<Factors, 0>::value,
  277. mp11::mp_at_c<Factors, 1>::value,
  278. mp11::mp_at_c<Factors, 2>::value
  279. >
  280. {
  281. private:
  282. using parent_t = detail::scaling_factors
  283. <
  284. mp11::mp_at_c<Factors, 0>::value,
  285. mp11::mp_at_c<Factors, 1>::value,
  286. mp11::mp_at_c<Factors, 2>::value
  287. >;
  288. public:
  289. using channel_t = typename channel_type<Pixel>::type;
  290. using pixel_t = pixel<channel_t, gray_layout_t>;
  291. using plane_image_t = image<pixel_t, false, Allocator>;
  292. using plane_view_t = typename plane_image_t::view_t;
  293. using plane_const_view_t = typename plane_image_t::const_view_t;
  294. using plane_locator_t = typename plane_view_t::locator;
  295. using pixel_view_t = typename view_type_from_pixel<Pixel>::type;
  296. using pixel_locator_t = typename pixel_view_t::locator;
  297. using locator_t = typename subchroma_image_locator
  298. <
  299. pixel_locator_t,
  300. Factors
  301. >::type;
  302. using x_coord_t = typename plane_image_t::coord_t;
  303. using y_coord_t = typename plane_image_t::coord_t;
  304. using view_t = subchroma_image_view<locator_t, Factors>;
  305. using const_view_t = typename view_t::const_t;
  306. /// constructor
  307. subchroma_image( const x_coord_t y_width
  308. , const y_coord_t y_height
  309. )
  310. : _y_plane( y_width, y_height, 0, Allocator() )
  311. , _v_plane( y_width / parent_t::ss_X, y_height / parent_t::ss_Y, 0, Allocator() )
  312. , _u_plane( y_width / parent_t::ss_X, y_height / parent_t::ss_Y, 0, Allocator() )
  313. {
  314. init();
  315. }
  316. public:
  317. view_t _view;
  318. private:
  319. void init()
  320. {
  321. using defer_fn_t = subchroma_image_deref_fn<pixel_locator_t, Factors>;
  322. defer_fn_t deref_fn( view( _y_plane ).xy_at( 0, 0 )
  323. , view( _v_plane ).xy_at( 0, 0 )
  324. , view( _u_plane ).xy_at( 0, 0 )
  325. );
  326. // init a virtual_2d_locator
  327. locator_t locator( point_t( 0, 0 ) // p
  328. , point_t( 1, 1 ) // step
  329. , deref_fn
  330. );
  331. _view = view_t( _y_plane.dimensions()
  332. , _v_plane.dimensions()
  333. , _u_plane.dimensions()
  334. , locator
  335. );
  336. }
  337. private:
  338. plane_image_t _y_plane;
  339. plane_image_t _v_plane;
  340. plane_image_t _u_plane;
  341. };
  342. /////////////////////////////
  343. // PixelBasedConcept
  344. /////////////////////////////
  345. template < typename Pixel, typename Factors, typename Alloc >
  346. struct channel_type< subchroma_image< Pixel, Factors, Alloc > >
  347. : channel_type< Pixel > {};
  348. template < typename Pixel, typename Factors, typename Alloc >
  349. struct color_space_type< subchroma_image< Pixel, Factors, Alloc > >
  350. : color_space_type< Pixel > {};
  351. template < typename Pixel, typename Factors, typename Alloc >
  352. struct channel_mapping_type< subchroma_image< Pixel, Factors, Alloc > >
  353. : channel_mapping_type< Pixel > {};
  354. template < typename Pixel, typename Factors, typename Alloc >
  355. struct is_planar< subchroma_image< Pixel, Factors, Alloc > >
  356. : std::integral_constant<bool, false>
  357. {};
  358. /////////////////////////////////////////////////////////////////////////////////////////
  359. /// \name view, const_view
  360. /// \brief Get an image view from an subchroma_image
  361. /// \ingroup ImageModel
  362. /// \brief Returns the non-constant-pixel view of an image
  363. /////////////////////////////////////////////////////////////////////////////////////////
  364. template< typename Pixel
  365. , typename Factors
  366. >
  367. inline
  368. const typename subchroma_image< Pixel, Factors >::view_t& view( subchroma_image< Pixel, Factors >& img )
  369. {
  370. return img._view;
  371. }
  372. template< typename Pixel
  373. , typename Factors
  374. >
  375. inline
  376. const typename subchroma_image< Pixel, Factors >::const_view_t const_view( subchroma_image< Pixel, Factors >& img )
  377. {
  378. return static_cast< const typename subchroma_image< Pixel, Factors >::const_view_t>( img._view );
  379. }
  380. /////////////////////////////////////////////////////////////////////////////////////////
  381. /// \ingroup ImageViewSTLAlgorithmsFillPixels
  382. /// \brief std::fill for subchroma_image views
  383. /////////////////////////////////////////////////////////////////////////////////////////
  384. template< typename Locator
  385. , typename Factors
  386. , typename Pixel
  387. >
  388. void fill_pixels( const subchroma_image_view< Locator, Factors >& view
  389. , const Pixel& value
  390. )
  391. {
  392. using channel_t = typename subchroma_image
  393. <
  394. Pixel,
  395. Factors
  396. >::plane_view_t::value_type;
  397. fill_pixels( view.y_plane_view(), channel_t( at_c< 0 >( value )));
  398. fill_pixels( view.v_plane_view(), channel_t( at_c< 1 >( value )));
  399. fill_pixels( view.u_plane_view(), channel_t( at_c< 2 >( value )));
  400. }
  401. /////////////////////////////////////////////////////////////////////////////////////////
  402. /// \ingroup ImageViewConstructors
  403. /// \brief Creates a subchroma view from a raw memory
  404. /////////////////////////////////////////////////////////////////////////////////////////
  405. template< typename Pixel
  406. , typename Factors
  407. >
  408. typename subchroma_image< Pixel
  409. , Factors
  410. >::view_t subchroma_view( std::size_t y_width
  411. , std::size_t y_height
  412. , unsigned char* y_base
  413. )
  414. {
  415. using scaling_factors_t = detail::scaling_factors
  416. <
  417. mp11::mp_at_c<Factors, 0>::type::value,
  418. mp11::mp_at_c<Factors, 1>::type::value,
  419. mp11::mp_at_c<Factors, 2>::type::value
  420. >;
  421. std::size_t y_channel_size = 1;
  422. std::size_t u_channel_size = 1;
  423. unsigned char* u_base = y_base + ( y_width * y_height * y_channel_size );
  424. unsigned char* v_base = u_base + ( y_width / scaling_factors_t::ss_X )
  425. * u_channel_size;
  426. using plane_view_t = typename subchroma_image<Pixel, Factors>::plane_view_t;
  427. plane_view_t y_plane = interleaved_view( y_width
  428. , y_height
  429. , (typename plane_view_t::value_type*) y_base // pixels
  430. , y_width // rowsize_in_bytes
  431. );
  432. plane_view_t v_plane = interleaved_view( y_width / scaling_factors_t::ss_X
  433. , y_height / scaling_factors_t::ss_Y
  434. , (typename plane_view_t::value_type*) v_base // pixels
  435. , y_width // rowsize_in_bytes
  436. );
  437. plane_view_t u_plane = interleaved_view( y_width / scaling_factors_t::ss_X
  438. , y_height / scaling_factors_t::ss_Y
  439. , (typename plane_view_t::value_type*) u_base // pixels
  440. , y_width // rowsize_in_bytes
  441. );
  442. using defer_fn_t = subchroma_image_deref_fn
  443. <
  444. typename subchroma_image<Pixel, Factors>::pixel_locator_t,
  445. Factors
  446. >;
  447. defer_fn_t deref_fn( y_plane.xy_at( 0, 0 )
  448. , v_plane.xy_at( 0, 0 )
  449. , u_plane.xy_at( 0, 0 )
  450. );
  451. using locator_t = typename subchroma_image<Pixel, Factors>::locator_t;
  452. locator_t locator( point_t( 0, 0 ) // p
  453. , point_t( 1, 1 ) // step
  454. , deref_fn
  455. );
  456. using view_t = typename subchroma_image<Pixel, Factors>::view_t;
  457. return view_t( point_t( y_width, y_height )
  458. , point_t( y_width / scaling_factors_t::ss_X, y_height / scaling_factors_t::ss_Y )
  459. , point_t( y_width / scaling_factors_t::ss_X, y_height / scaling_factors_t::ss_Y )
  460. , locator
  461. );
  462. }
  463. } // namespace gil
  464. } // namespace boost
  465. #endif