write.hpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /*
  2. Copyright 2012 Christian Henning
  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_BMP_DETAIL_WRITE_HPP
  9. #define BOOST_GIL_EXTENSION_IO_BMP_DETAIL_WRITE_HPP
  10. ////////////////////////////////////////////////////////////////////////////////////////
  11. /// \file
  12. /// \brief
  13. /// \author Christian Henning \n
  14. ///
  15. /// \date 2012 \n
  16. ///
  17. ////////////////////////////////////////////////////////////////////////////////////////
  18. #include <vector>
  19. #include <boost/gil/io/base.hpp>
  20. #include <boost/gil/io/device.hpp>
  21. #include <boost/gil/extension/io/bmp/tags.hpp>
  22. #include <boost/gil/extension/io/bmp/detail/writer_backend.hpp>
  23. namespace boost { namespace gil {
  24. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  25. #pragma warning(push)
  26. #pragma warning(disable:4512) //assignment operator could not be generated
  27. #endif
  28. namespace detail {
  29. struct bmp_write_is_supported
  30. {
  31. template< typename View >
  32. struct apply
  33. : public is_write_supported< typename get_pixel_type< View >::type
  34. , bmp_tag
  35. >
  36. {};
  37. };
  38. template < int N > struct get_bgr_cs {};
  39. template <> struct get_bgr_cs< 1 > { typedef gray8_view_t type; };
  40. template <> struct get_bgr_cs< 3 > { typedef bgr8_view_t type; };
  41. template <> struct get_bgr_cs< 4 > { typedef bgra8_view_t type; };
  42. } // namespace detail
  43. ///
  44. /// BMP Writer
  45. ///
  46. template< typename Device >
  47. class writer< Device
  48. , bmp_tag
  49. >
  50. : public writer_backend< Device
  51. , bmp_tag
  52. >
  53. {
  54. public:
  55. writer( const Device& io_dev
  56. , const image_write_info< bmp_tag >& info
  57. )
  58. : backend_t( io_dev
  59. , info
  60. )
  61. {}
  62. template<typename View>
  63. void apply( const View& view )
  64. {
  65. write( view );
  66. }
  67. private:
  68. typedef writer_backend< Device, bmp_tag > backend_t;
  69. template< typename View >
  70. void write( const View& view )
  71. {
  72. // typedef typename channel_type<
  73. // typename get_pixel_type< View >::type >::type channel_t;
  74. // typedef typename color_space_type< View >::type color_space_t;
  75. // check if supported
  76. /*
  77. /// todo
  78. if( bmp_read_write_support_private<channel_t, color_space_t>::channel != 8)
  79. {
  80. io_error("Input view type is incompatible with the image type");
  81. }
  82. */
  83. // compute the file size
  84. int bpp = num_channels< View >::value * 8;
  85. int entries = 0;
  86. /*
  87. /// @todo: Not supported for now. bit_aligned_images refer to indexed images
  88. /// in this context.
  89. if( bpp <= 8 )
  90. {
  91. entries = 1u << bpp;
  92. }
  93. */
  94. std::size_t spn = ( view.width() * num_channels< View >::value + 3 ) & ~3;
  95. std::size_t ofs = bmp_header_size::_size
  96. + bmp_header_size::_win32_info_size
  97. + entries * 4;
  98. std::size_t siz = ofs + spn * view.height();
  99. // write the BMP file header
  100. this->_io_dev.write_uint16( bmp_signature );
  101. this->_io_dev.write_uint32( (uint32_t) siz );
  102. this->_io_dev.write_uint16( 0 );
  103. this->_io_dev.write_uint16( 0 );
  104. this->_io_dev.write_uint32( (uint32_t) ofs );
  105. // writes Windows information header
  106. this->_io_dev.write_uint32( bmp_header_size::_win32_info_size );
  107. this->_io_dev.write_uint32( static_cast< uint32_t >( view.width() ));
  108. this->_io_dev.write_uint32( static_cast< uint32_t >( view.height() ));
  109. this->_io_dev.write_uint16( 1 );
  110. this->_io_dev.write_uint16( static_cast< uint16_t >( bpp ));
  111. this->_io_dev.write_uint32( bmp_compression::_rgb );
  112. this->_io_dev.write_uint32( 0 );
  113. this->_io_dev.write_uint32( 0 );
  114. this->_io_dev.write_uint32( 0 );
  115. this->_io_dev.write_uint32( entries );
  116. this->_io_dev.write_uint32( 0 );
  117. write_image< View
  118. , typename detail::get_bgr_cs< num_channels< View >::value >::type
  119. >( view, spn );
  120. }
  121. template< typename View
  122. , typename BMP_View
  123. >
  124. void write_image( const View& view
  125. , const std::size_t spn
  126. )
  127. {
  128. byte_vector_t buffer( spn );
  129. std::fill( buffer.begin(), buffer.end(), 0 );
  130. BMP_View row = interleaved_view( view.width()
  131. , 1
  132. , (typename BMP_View::value_type*) &buffer.front()
  133. , spn
  134. );
  135. for( typename View::y_coord_t y = view.height() - 1; y > -1; --y )
  136. {
  137. copy_pixels( subimage_view( view
  138. , 0
  139. , (int) y
  140. , (int) view.width()
  141. , 1
  142. )
  143. , row
  144. );
  145. this->_io_dev.write( &buffer.front(), spn );
  146. }
  147. }
  148. };
  149. ///
  150. /// BMP Dynamic Image Writer
  151. ///
  152. template< typename Device >
  153. class dynamic_image_writer< Device
  154. , bmp_tag
  155. >
  156. : public writer< Device
  157. , bmp_tag
  158. >
  159. {
  160. typedef writer< Device
  161. , bmp_tag
  162. > parent_t;
  163. public:
  164. dynamic_image_writer( const Device& io_dev
  165. , const image_write_info< bmp_tag >& info
  166. )
  167. : parent_t( io_dev
  168. , info
  169. )
  170. {}
  171. template< typename Views >
  172. void apply( const any_image_view< Views >& views )
  173. {
  174. detail::dynamic_io_fnobj< detail::bmp_write_is_supported
  175. , parent_t
  176. > op( this );
  177. apply_operation( views
  178. , op
  179. );
  180. }
  181. };
  182. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  183. #pragma warning(pop)
  184. #endif
  185. } // gil
  186. } // boost
  187. #endif