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