// // 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 #include #include #include #include #include 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; 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 void write_view( const View& view , std::false_type // is bit aligned ) { using pixel_t = typename get_pixel_type::type; using png_rw_info = detail::png_write_support < typename channel_type::type, typename color_space_type::type >; if( little_endian() ) { set_swap< png_rw_info >(); } std::vector< pixel< typename channel_type< View >::type , layout::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 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::type, typename color_space_type::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 struct is_less_than_eight : mp11::mp_less < std::integral_constant, std::integral_constant > {}; template struct is_equal_to_sixteen : mp11::mp_and < mp11::mp_not < mp11::mp_less < std::integral_constant, std::integral_constant > >, mp11::mp_not < mp11::mp_less < std::integral_constant, std::integral_constant > > > {}; template void set_swap(typename std::enable_if::value>::type* /*ptr*/ = 0) { png_set_packswap(this->get_struct()); } template void set_swap(typename std::enable_if::value>::type* /*ptr*/ = 0) { png_set_swap(this->get_struct()); } template void set_swap( typename std::enable_if < mp11::mp_and < mp11::mp_not>, mp11::mp_not> >::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; 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