File indexing completed on 2025-12-17 09:47:31
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_GIL_EXTENSION_IO_BMP_DETAIL_WRITE_HPP
0009 #define BOOST_GIL_EXTENSION_IO_BMP_DETAIL_WRITE_HPP
0010
0011 #include <boost/gil/extension/io/bmp/tags.hpp>
0012 #include <boost/gil/extension/io/bmp/detail/writer_backend.hpp>
0013
0014 #include <boost/gil/io/base.hpp>
0015 #include <boost/gil/io/device.hpp>
0016 #include <boost/gil/io/detail/dynamic.hpp>
0017
0018 #include <vector>
0019
0020 namespace boost { namespace gil {
0021
0022 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0023 #pragma warning(push)
0024 #pragma warning(disable:4512)
0025 #endif
0026
0027 namespace detail {
0028
0029 struct bmp_write_is_supported
0030 {
0031 template< typename View >
0032 struct apply
0033 : public is_write_supported< typename get_pixel_type< View >::type
0034 , bmp_tag
0035 >
0036 {};
0037 };
0038
0039 template < int N > struct get_bgr_cs {};
0040 template <> struct get_bgr_cs< 1 > { using type = gray8_view_t; };
0041 template <> struct get_bgr_cs< 3 > { using type = bgr8_view_t; };
0042 template <> struct get_bgr_cs< 4 > { using type = bgra8_view_t; };
0043
0044 }
0045
0046
0047
0048
0049 template< typename Device >
0050 class writer< Device
0051 , bmp_tag
0052 >
0053 : public writer_backend< Device
0054 , bmp_tag
0055 >
0056 {
0057 public:
0058
0059 writer( const Device& io_dev
0060 , const image_write_info< bmp_tag >& info
0061 )
0062 : backend_t( io_dev
0063 , info
0064 )
0065 {}
0066
0067 template<typename View>
0068 void apply( const View& view )
0069 {
0070 write( view );
0071 }
0072
0073 private:
0074
0075 using backend_t = writer_backend<Device, bmp_tag>;
0076
0077 template< typename View >
0078 void write( const View& view )
0079 {
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095 int bpp = num_channels< View >::value * 8;
0096 int entries = 0;
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107 std::size_t spn = ( view.width() * num_channels< View >::value + 3 ) & ~3;
0108 std::size_t ofs = bmp_header_size::_size
0109 + bmp_header_size::_win32_info_size
0110 + entries * 4;
0111
0112 std::size_t siz = ofs + spn * view.height();
0113
0114
0115 this->_io_dev.write_uint16( bmp_signature );
0116 this->_io_dev.write_uint32( (uint32_t) siz );
0117 this->_io_dev.write_uint16( 0 );
0118 this->_io_dev.write_uint16( 0 );
0119 this->_io_dev.write_uint32( (uint32_t) ofs );
0120
0121
0122 this->_io_dev.write_uint32( bmp_header_size::_win32_info_size );
0123 this->_io_dev.write_uint32( static_cast< uint32_t >( view.width() ));
0124 this->_io_dev.write_uint32( static_cast< uint32_t >( view.height() ));
0125 this->_io_dev.write_uint16( 1 );
0126 this->_io_dev.write_uint16( static_cast< uint16_t >( bpp ));
0127 this->_io_dev.write_uint32( bmp_compression::_rgb );
0128 this->_io_dev.write_uint32( 0 );
0129 this->_io_dev.write_uint32( 0 );
0130 this->_io_dev.write_uint32( 0 );
0131 this->_io_dev.write_uint32( entries );
0132 this->_io_dev.write_uint32( 0 );
0133
0134 write_image< View
0135 , typename detail::get_bgr_cs< num_channels< View >::value >::type
0136 >( view, spn );
0137 }
0138
0139
0140 template< typename View
0141 , typename BMP_View
0142 >
0143 void write_image( const View& view
0144 , const std::size_t spn
0145 )
0146 {
0147 byte_vector_t buffer( spn );
0148 std::fill( buffer.begin(), buffer.end(), 0 );
0149
0150
0151 BMP_View row = interleaved_view( view.width()
0152 , 1
0153 , (typename BMP_View::value_type*) &buffer.front()
0154 , spn
0155 );
0156
0157 for( typename View::y_coord_t y = view.height() - 1; y > -1; --y )
0158 {
0159 copy_pixels( subimage_view( view
0160 , 0
0161 , (int) y
0162 , (int) view.width()
0163 , 1
0164 )
0165 , row
0166 );
0167
0168 this->_io_dev.write( &buffer.front(), spn );
0169 }
0170
0171 }
0172 };
0173
0174
0175
0176
0177 template< typename Device >
0178 class dynamic_image_writer< Device
0179 , bmp_tag
0180 >
0181 : public writer< Device
0182 , bmp_tag
0183 >
0184 {
0185 using parent_t = writer<Device, bmp_tag>;
0186
0187 public:
0188
0189 dynamic_image_writer( const Device& io_dev
0190 , const image_write_info< bmp_tag >& info
0191 )
0192 : parent_t( io_dev
0193 , info
0194 )
0195 {}
0196
0197 template< typename ...Views >
0198 void apply( const any_image_view< Views... >& views )
0199 {
0200 detail::dynamic_io_fnobj< detail::bmp_write_is_supported
0201 , parent_t
0202 > op( this );
0203
0204 variant2::visit( op
0205 ,views
0206 );
0207 }
0208 };
0209
0210 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0211 #pragma warning(pop)
0212 #endif
0213
0214 }
0215 }
0216
0217 #endif