libcarla/include/system/boost/gil/extension/io/bmp/detail/write.hpp
2024-10-18 13:19:59 +08:00

218 lines
5.9 KiB
C++

//
// 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