write.hpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  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/dynamic_io_new.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_less
  142. <
  143. std::integral_constant<int, Info::_bit_depth>,
  144. std::integral_constant<int, 16>
  145. >
  146. {};
  147. template <typename Info>
  148. void set_swap(typename std::enable_if<is_less_than_eight<Info>::value>::type* /*ptr*/ = 0)
  149. {
  150. png_set_packswap(this->get_struct());
  151. }
  152. template <typename Info>
  153. void set_swap(typename std::enable_if<is_equal_to_sixteen<Info>::value>::type* /*ptr*/ = 0)
  154. {
  155. png_set_swap(this->get_struct());
  156. }
  157. template <typename Info>
  158. void set_swap(
  159. typename std::enable_if
  160. <
  161. mp11::mp_and
  162. <
  163. mp11::mp_not<is_less_than_eight<Info>>,
  164. mp11::mp_not<is_equal_to_sixteen<Info>>
  165. >::value
  166. >::type* /*ptr*/ = nullptr)
  167. {
  168. }
  169. };
  170. ///
  171. /// PNG Dynamic Image Writer
  172. ///
  173. template< typename Device >
  174. class dynamic_image_writer< Device
  175. , png_tag
  176. >
  177. : public writer< Device
  178. , png_tag
  179. >
  180. {
  181. using parent_t = writer<Device, png_tag>;
  182. public:
  183. dynamic_image_writer( const Device& io_dev
  184. , const image_write_info< png_tag >& info
  185. )
  186. : parent_t( io_dev
  187. , info
  188. )
  189. {}
  190. template< typename Views >
  191. void apply( const any_image_view< Views >& views )
  192. {
  193. detail::dynamic_io_fnobj< detail::png_write_is_supported
  194. , parent_t
  195. > op( this );
  196. apply_operation( views, op );
  197. }
  198. };
  199. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  200. #pragma warning(pop)
  201. #endif
  202. } // namespace gil
  203. } // namespace boost
  204. #endif