123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- //
- // Copyright 2012 Christian Henning
- //
- // Distributed under the Boost Software License, Version 1.0
- // See accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt
- //
- #ifndef BOOST_GIL_EXTENSION_IO_BMP_DETAIL_WRITE_HPP
- #define BOOST_GIL_EXTENSION_IO_BMP_DETAIL_WRITE_HPP
- #include <boost/gil/extension/io/bmp/tags.hpp>
- #include <boost/gil/extension/io/bmp/detail/writer_backend.hpp>
- #include <boost/gil/io/base.hpp>
- #include <boost/gil/io/device.hpp>
- #include <boost/gil/io/detail/dynamic.hpp>
- #include <vector>
- namespace boost { namespace gil {
- #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
- #pragma warning(push)
- #pragma warning(disable:4512) //assignment operator could not be generated
- #endif
- namespace detail {
- struct bmp_write_is_supported
- {
- template< typename View >
- struct apply
- : public is_write_supported< typename get_pixel_type< View >::type
- , bmp_tag
- >
- {};
- };
- template < int N > struct get_bgr_cs {};
- template <> struct get_bgr_cs< 1 > { using type = gray8_view_t; };
- template <> struct get_bgr_cs< 3 > { using type = bgr8_view_t; };
- template <> struct get_bgr_cs< 4 > { using type = bgra8_view_t; };
- } // namespace detail
- ///
- /// BMP Writer
- ///
- template< typename Device >
- class writer< Device
- , bmp_tag
- >
- : public writer_backend< Device
- , bmp_tag
- >
- {
- public:
- writer( const Device& io_dev
- , const image_write_info< bmp_tag >& info
- )
- : backend_t( io_dev
- , info
- )
- {}
- template<typename View>
- void apply( const View& view )
- {
- write( view );
- }
- private:
- using backend_t = writer_backend<Device, bmp_tag>;
- template< typename View >
- void write( const View& view )
- {
- // using channel_t = typename channel_type<
- // typename get_pixel_type<View>::type>::type;
- // using color_space_t = typename color_space_type<View>::type;
- // check if supported
- /*
- /// todo
- if( bmp_read_write_support_private<channel_t, color_space_t>::channel != 8)
- {
- io_error("Input view type is incompatible with the image type");
- }
- */
- // compute the file size
- int bpp = num_channels< View >::value * 8;
- int entries = 0;
- /*
- /// @todo: Not supported for now. bit_aligned_images refer to indexed images
- /// in this context.
- if( bpp <= 8 )
- {
- entries = 1u << bpp;
- }
- */
- std::size_t spn = ( view.width() * num_channels< View >::value + 3 ) & ~3;
- std::size_t ofs = bmp_header_size::_size
- + bmp_header_size::_win32_info_size
- + entries * 4;
- std::size_t siz = ofs + spn * view.height();
- // write the BMP file header
- this->_io_dev.write_uint16( bmp_signature );
- this->_io_dev.write_uint32( (uint32_t) siz );
- this->_io_dev.write_uint16( 0 );
- this->_io_dev.write_uint16( 0 );
- this->_io_dev.write_uint32( (uint32_t) ofs );
- // writes Windows information header
- this->_io_dev.write_uint32( bmp_header_size::_win32_info_size );
- this->_io_dev.write_uint32( static_cast< uint32_t >( view.width() ));
- this->_io_dev.write_uint32( static_cast< uint32_t >( view.height() ));
- this->_io_dev.write_uint16( 1 );
- this->_io_dev.write_uint16( static_cast< uint16_t >( bpp ));
- this->_io_dev.write_uint32( bmp_compression::_rgb );
- this->_io_dev.write_uint32( 0 );
- this->_io_dev.write_uint32( 0 );
- this->_io_dev.write_uint32( 0 );
- this->_io_dev.write_uint32( entries );
- this->_io_dev.write_uint32( 0 );
- write_image< View
- , typename detail::get_bgr_cs< num_channels< View >::value >::type
- >( view, spn );
- }
- template< typename View
- , typename BMP_View
- >
- void write_image( const View& view
- , const std::size_t spn
- )
- {
- byte_vector_t buffer( spn );
- std::fill( buffer.begin(), buffer.end(), 0 );
- BMP_View row = interleaved_view( view.width()
- , 1
- , (typename BMP_View::value_type*) &buffer.front()
- , spn
- );
- for( typename View::y_coord_t y = view.height() - 1; y > -1; --y )
- {
- copy_pixels( subimage_view( view
- , 0
- , (int) y
- , (int) view.width()
- , 1
- )
- , row
- );
- this->_io_dev.write( &buffer.front(), spn );
- }
- }
- };
- ///
- /// BMP Dynamic Image Writer
- ///
- template< typename Device >
- class dynamic_image_writer< Device
- , bmp_tag
- >
- : public writer< Device
- , bmp_tag
- >
- {
- using parent_t = writer<Device, bmp_tag>;
- public:
- dynamic_image_writer( const Device& io_dev
- , const image_write_info< bmp_tag >& info
- )
- : parent_t( io_dev
- , info
- )
- {}
- template< typename ...Views >
- void apply( const any_image_view< Views... >& views )
- {
- detail::dynamic_io_fnobj< detail::bmp_write_is_supported
- , parent_t
- > op( this );
- variant2::visit( op
- ,views
- );
- }
- };
- #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
- #pragma warning(pop)
- #endif
- } // gil
- } // boost
- #endif
|