write.hpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. //
  2. // Copyright 2007-2012 Christian Henning, Andreas Pokorny, Lubomir Bourdev
  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_IO_PNG_DETAIL_WRITE_HPP
  9. #define BOOST_GIL_EXTENSION_IO_PNG_DETAIL_WRITE_HPP
  10. #include <boost/gil/extension/io/png/detail/writer_backend.hpp>
  11. #include <boost/gil/io/device.hpp>
  12. #include <boost/gil/io/detail/dynamic.hpp>
  13. #include <boost/gil/io/row_buffer_helper.hpp>
  14. #include <boost/gil/detail/mp11.hpp>
  15. #include <type_traits>
  16. namespace boost { namespace gil {
  17. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  18. #pragma warning(push)
  19. #pragma warning(disable:4512) //assignment operator could not be generated
  20. #endif
  21. namespace detail {
  22. struct png_write_is_supported
  23. {
  24. template< typename View >
  25. struct apply
  26. : public is_write_supported< typename get_pixel_type< View >::type
  27. , png_tag
  28. >
  29. {};
  30. };
  31. } // namespace detail
  32. ///
  33. /// PNG Writer
  34. ///
  35. template< typename Device >
  36. class writer< Device
  37. , png_tag
  38. >
  39. : public writer_backend< Device
  40. , png_tag
  41. >
  42. {
  43. public:
  44. using backend_t = writer_backend<Device, png_tag>;
  45. writer( const Device& io_dev
  46. , const image_write_info< png_tag >& info
  47. )
  48. : backend_t( io_dev
  49. , info
  50. )
  51. {}
  52. template< typename View >
  53. void apply( const View& view )
  54. {
  55. io_error_if( view.width() == 0 && view.height() == 0
  56. , "png format cannot handle empty views."
  57. );
  58. this->write_header( view );
  59. write_view( view
  60. , typename is_bit_aligned< typename View::value_type >::type()
  61. );
  62. }
  63. private:
  64. template<typename View>
  65. void write_view( const View& view
  66. , std::false_type // is bit aligned
  67. )
  68. {
  69. using pixel_t = typename get_pixel_type<View>::type;
  70. using png_rw_info = detail::png_write_support
  71. <
  72. typename channel_type<pixel_t>::type,
  73. typename color_space_type<pixel_t>::type
  74. >;
  75. if( little_endian() )
  76. {
  77. set_swap< png_rw_info >();
  78. }
  79. std::vector< pixel< typename channel_type< View >::type
  80. , layout<typename color_space_type< View >::type >
  81. >
  82. > row_buffer( view.width() );
  83. for( int y = 0; y != view.height(); ++ y)
  84. {
  85. std::copy( view.row_begin( y )
  86. , view.row_end ( y )
  87. , row_buffer.begin()
  88. );
  89. png_write_row( this->get_struct()
  90. , reinterpret_cast< png_bytep >( row_buffer.data() )
  91. );
  92. }
  93. png_write_end( this->get_struct()
  94. , this->get_info()
  95. );
  96. }
  97. template<typename View>
  98. void write_view( const View& view
  99. , std::true_type // is bit aligned
  100. )
  101. {
  102. using png_rw_info = detail::png_write_support
  103. <
  104. typename kth_semantic_element_type<typename View::value_type, 0>::type,
  105. typename color_space_type<View>::type
  106. >;
  107. if (little_endian() )
  108. {
  109. set_swap< png_rw_info >();
  110. }
  111. detail::row_buffer_helper_view< View > row_buffer( view.width()
  112. , false
  113. );
  114. for( int y = 0; y != view.height(); ++y )
  115. {
  116. std::copy( view.row_begin( y )
  117. , view.row_end ( y )
  118. , row_buffer.begin()
  119. );
  120. png_write_row( this->get_struct()
  121. , reinterpret_cast< png_bytep >( row_buffer.data() )
  122. );
  123. }
  124. png_free_data( this->get_struct()
  125. , this->get_info()
  126. , PNG_FREE_UNKN
  127. , -1
  128. );
  129. png_write_end( this->get_struct()
  130. , this->get_info()
  131. );
  132. }
  133. template<typename Info>
  134. struct is_less_than_eight : mp11::mp_less
  135. <
  136. std::integral_constant<int, Info::_bit_depth>,
  137. std::integral_constant<int, 8>
  138. >
  139. {};
  140. template<typename Info>
  141. struct is_equal_to_sixteen : mp11::mp_and
  142. <
  143. mp11::mp_not
  144. <
  145. mp11::mp_less
  146. <
  147. std::integral_constant<int, Info::_bit_depth>,
  148. std::integral_constant<int, 16>
  149. >
  150. >,
  151. mp11::mp_not
  152. <
  153. mp11::mp_less
  154. <
  155. std::integral_constant<int, 16>,
  156. std::integral_constant<int, Info::_bit_depth>
  157. >
  158. >
  159. >
  160. {};
  161. template <typename Info>
  162. void set_swap(typename std::enable_if<is_less_than_eight<Info>::value>::type* /*ptr*/ = 0)
  163. {
  164. png_set_packswap(this->get_struct());
  165. }
  166. template <typename Info>
  167. void set_swap(typename std::enable_if<is_equal_to_sixteen<Info>::value>::type* /*ptr*/ = 0)
  168. {
  169. png_set_swap(this->get_struct());
  170. }
  171. template <typename Info>
  172. void set_swap(
  173. typename std::enable_if
  174. <
  175. mp11::mp_and
  176. <
  177. mp11::mp_not<is_less_than_eight<Info>>,
  178. mp11::mp_not<is_equal_to_sixteen<Info>>
  179. >::value
  180. >::type* /*ptr*/ = nullptr)
  181. {
  182. }
  183. };
  184. ///
  185. /// PNG Dynamic Image Writer
  186. ///
  187. template< typename Device >
  188. class dynamic_image_writer< Device
  189. , png_tag
  190. >
  191. : public writer< Device
  192. , png_tag
  193. >
  194. {
  195. using parent_t = writer<Device, png_tag>;
  196. public:
  197. dynamic_image_writer( const Device& io_dev
  198. , const image_write_info< png_tag >& info
  199. )
  200. : parent_t( io_dev
  201. , info
  202. )
  203. {}
  204. template< typename ...Views >
  205. void apply( const any_image_view< Views... >& views )
  206. {
  207. detail::dynamic_io_fnobj< detail::png_write_is_supported
  208. , parent_t
  209. > op( this );
  210. variant2::visit( op, views );
  211. }
  212. };
  213. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  214. #pragma warning(pop)
  215. #endif
  216. } // namespace gil
  217. } // namespace boost
  218. #endif