libcarla/include/system/boost/gil/extension/io/png/detail/write.hpp

263 lines
6.7 KiB
C++
Raw Normal View History

2024-10-18 13:19:59 +08:00
//
// Copyright 2007-2012 Christian Henning, Andreas Pokorny, Lubomir Bourdev
//
// 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_PNG_DETAIL_WRITE_HPP
#define BOOST_GIL_EXTENSION_IO_PNG_DETAIL_WRITE_HPP
#include <boost/gil/extension/io/png/detail/writer_backend.hpp>
#include <boost/gil/io/device.hpp>
#include <boost/gil/io/detail/dynamic.hpp>
#include <boost/gil/io/row_buffer_helper.hpp>
#include <boost/gil/detail/mp11.hpp>
#include <type_traits>
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 png_write_is_supported
{
template< typename View >
struct apply
: public is_write_supported< typename get_pixel_type< View >::type
, png_tag
>
{};
};
} // namespace detail
///
/// PNG Writer
///
template< typename Device >
class writer< Device
, png_tag
>
: public writer_backend< Device
, png_tag
>
{
public:
using backend_t = writer_backend<Device, png_tag>;
writer( const Device& io_dev
, const image_write_info< png_tag >& info
)
: backend_t( io_dev
, info
)
{}
template< typename View >
void apply( const View& view )
{
io_error_if( view.width() == 0 && view.height() == 0
, "png format cannot handle empty views."
);
this->write_header( view );
write_view( view
, typename is_bit_aligned< typename View::value_type >::type()
);
}
private:
template<typename View>
void write_view( const View& view
, std::false_type // is bit aligned
)
{
using pixel_t = typename get_pixel_type<View>::type;
using png_rw_info = detail::png_write_support
<
typename channel_type<pixel_t>::type,
typename color_space_type<pixel_t>::type
>;
if( little_endian() )
{
set_swap< png_rw_info >();
}
std::vector< pixel< typename channel_type< View >::type
, layout<typename color_space_type< View >::type >
>
> row_buffer( view.width() );
for( int y = 0; y != view.height(); ++ y)
{
std::copy( view.row_begin( y )
, view.row_end ( y )
, row_buffer.begin()
);
png_write_row( this->get_struct()
, reinterpret_cast< png_bytep >( row_buffer.data() )
);
}
png_write_end( this->get_struct()
, this->get_info()
);
}
template<typename View>
void write_view( const View& view
, std::true_type // is bit aligned
)
{
using png_rw_info = detail::png_write_support
<
typename kth_semantic_element_type<typename View::value_type, 0>::type,
typename color_space_type<View>::type
>;
if (little_endian() )
{
set_swap< png_rw_info >();
}
detail::row_buffer_helper_view< View > row_buffer( view.width()
, false
);
for( int y = 0; y != view.height(); ++y )
{
std::copy( view.row_begin( y )
, view.row_end ( y )
, row_buffer.begin()
);
png_write_row( this->get_struct()
, reinterpret_cast< png_bytep >( row_buffer.data() )
);
}
png_free_data( this->get_struct()
, this->get_info()
, PNG_FREE_UNKN
, -1
);
png_write_end( this->get_struct()
, this->get_info()
);
}
template<typename Info>
struct is_less_than_eight : mp11::mp_less
<
std::integral_constant<int, Info::_bit_depth>,
std::integral_constant<int, 8>
>
{};
template<typename Info>
struct is_equal_to_sixteen : mp11::mp_and
<
mp11::mp_not
<
mp11::mp_less
<
std::integral_constant<int, Info::_bit_depth>,
std::integral_constant<int, 16>
>
>,
mp11::mp_not
<
mp11::mp_less
<
std::integral_constant<int, 16>,
std::integral_constant<int, Info::_bit_depth>
>
>
>
{};
template <typename Info>
void set_swap(typename std::enable_if<is_less_than_eight<Info>::value>::type* /*ptr*/ = 0)
{
png_set_packswap(this->get_struct());
}
template <typename Info>
void set_swap(typename std::enable_if<is_equal_to_sixteen<Info>::value>::type* /*ptr*/ = 0)
{
png_set_swap(this->get_struct());
}
template <typename Info>
void set_swap(
typename std::enable_if
<
mp11::mp_and
<
mp11::mp_not<is_less_than_eight<Info>>,
mp11::mp_not<is_equal_to_sixteen<Info>>
>::value
>::type* /*ptr*/ = nullptr)
{
}
};
///
/// PNG Dynamic Image Writer
///
template< typename Device >
class dynamic_image_writer< Device
, png_tag
>
: public writer< Device
, png_tag
>
{
using parent_t = writer<Device, png_tag>;
public:
dynamic_image_writer( const Device& io_dev
, const image_write_info< png_tag >& info
)
: parent_t( io_dev
, info
)
{}
template< typename ...Views >
void apply( const any_image_view< Views... >& views )
{
detail::dynamic_io_fnobj< detail::png_write_is_supported
, parent_t
> op( this );
variant2::visit( op, views );
}
};
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(pop)
#endif
} // namespace gil
} // namespace boost
#endif