write.hpp 6.2 KB

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