Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-17 09:47:31

0001 //
0002 // Copyright 2012 Christian Henning
0003 //
0004 // Distributed under the Boost Software License, Version 1.0
0005 // See accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt
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) //assignment operator could not be generated
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 } // namespace detail
0045 
0046 ///
0047 /// BMP Writer
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         // using channel_t = typename channel_type<
0081         //             typename get_pixel_type<View>::type>::type;
0082 
0083         // using color_space_t = typename color_space_type<View>::type;
0084 
0085         // check if supported
0086 /*
0087         /// todo
0088         if( bmp_read_write_support_private<channel_t, color_space_t>::channel != 8)
0089         {
0090             io_error("Input view type is incompatible with the image type");
0091         }
0092 */
0093 
0094         // compute the file size
0095         int bpp = num_channels< View >::value * 8;
0096         int entries = 0;
0097 
0098 /*
0099         /// @todo: Not supported for now. bit_aligned_images refer to indexed images
0100         ///        in this context.
0101         if( bpp <= 8 )
0102         {
0103             entries = 1u << bpp;
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         // write the BMP file header
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         // writes Windows information header
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 /// BMP Dynamic Image Writer
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 } // gil
0215 } // boost
0216 
0217 #endif