write.hpp 6.9 KB

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