Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:51:47

0001 //
0002 // Copyright 2007-2012 Christian Henning, Andreas Pokorny, Lubomir Bourdev
0003 //
0004 // Distributed under the Boost Software License, Version 1.0
0005 // See accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt
0007 //
0008 #ifndef BOOST_GIL_EXTENSION_IO_PNG_DETAIL_WRITE_HPP
0009 #define BOOST_GIL_EXTENSION_IO_PNG_DETAIL_WRITE_HPP
0010 
0011 #include <boost/gil/extension/io/png/detail/writer_backend.hpp>
0012 
0013 #include <boost/gil/io/device.hpp>
0014 #include <boost/gil/io/detail/dynamic.hpp>
0015 #include <boost/gil/io/row_buffer_helper.hpp>
0016 #include <boost/gil/detail/mp11.hpp>
0017 
0018 #include <type_traits>
0019 
0020 namespace boost { namespace gil {
0021 
0022 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0023 #pragma warning(push)
0024 #pragma warning(disable:4512) //assignment operator could not be generated
0025 #endif
0026 
0027 namespace detail {
0028 
0029 struct png_write_is_supported
0030 {
0031     template< typename View >
0032     struct apply
0033         : public is_write_supported< typename get_pixel_type< View >::type
0034                                    , png_tag
0035                                    >
0036     {};
0037 };
0038 
0039 } // namespace detail
0040 
0041 ///
0042 /// PNG Writer
0043 ///
0044 template< typename Device >
0045 class writer< Device
0046             , png_tag
0047             >
0048     : public writer_backend< Device
0049                            , png_tag
0050                            >
0051 {
0052 
0053 public:
0054 
0055     using backend_t = writer_backend<Device, png_tag>;
0056 
0057     writer( const Device&                      io_dev
0058           , const image_write_info< png_tag >& info
0059           )
0060     : backend_t( io_dev
0061                , info
0062                )
0063     {}
0064 
0065 
0066     template< typename View >
0067     void apply( const View& view )
0068     {
0069         io_error_if( view.width() == 0 && view.height() == 0
0070                    , "png format cannot handle empty views."
0071                    );
0072 
0073         this->write_header( view );
0074 
0075         write_view( view
0076                   , typename is_bit_aligned< typename View::value_type >::type()
0077                   );
0078     }
0079 
0080 private:
0081 
0082     template<typename View>
0083     void write_view( const View& view
0084                    ,  std::false_type       // is bit aligned
0085                    )
0086     {
0087         using pixel_t = typename get_pixel_type<View>::type;
0088 
0089         using png_rw_info = detail::png_write_support
0090             <
0091                 typename channel_type<pixel_t>::type,
0092                 typename color_space_type<pixel_t>::type
0093             >;
0094 
0095         if( little_endian() )
0096         {
0097             set_swap< png_rw_info >();
0098         }
0099 
0100         std::vector< pixel< typename channel_type< View >::type
0101                           , layout<typename color_space_type< View >::type >
0102                           >
0103                    > row_buffer( view.width() );
0104 
0105         for( int y = 0; y != view.height(); ++ y)
0106         {
0107             std::copy( view.row_begin( y )
0108                      , view.row_end  ( y )
0109                      , row_buffer.begin()
0110                      );
0111 
0112             png_write_row( this->get_struct()
0113                          , reinterpret_cast< png_bytep >( row_buffer.data() )
0114                          );
0115         }
0116 
0117         png_write_end( this->get_struct()
0118                      , this->get_info()
0119                      );
0120     }
0121 
0122     template<typename View>
0123     void write_view( const View& view
0124                    , std::true_type         // is bit aligned
0125                    )
0126     {
0127         using png_rw_info = detail::png_write_support
0128             <
0129                 typename kth_semantic_element_type<typename View::value_type, 0>::type,
0130                 typename color_space_type<View>::type
0131             >;
0132 
0133         if (little_endian() )
0134         {
0135             set_swap< png_rw_info >();
0136         }
0137 
0138         detail::row_buffer_helper_view< View > row_buffer( view.width()
0139                                                          , false
0140                                                          );
0141 
0142         for( int y = 0; y != view.height(); ++y )
0143         {
0144             std::copy( view.row_begin( y )
0145                      , view.row_end  ( y )
0146                      , row_buffer.begin()
0147                      );
0148 
0149             png_write_row( this->get_struct()
0150                          , reinterpret_cast< png_bytep >( row_buffer.data() )
0151                          );
0152         }
0153 
0154         png_free_data( this->get_struct()
0155                      , this->get_info()
0156                      , PNG_FREE_UNKN
0157                      , -1
0158                      );
0159 
0160         png_write_end( this->get_struct()
0161                      , this->get_info()
0162                      );
0163     }
0164 
0165     template<typename Info>
0166     struct is_less_than_eight : mp11::mp_less
0167         <
0168             std::integral_constant<int, Info::_bit_depth>,
0169             std::integral_constant<int, 8>
0170         >
0171     {};
0172 
0173     template<typename Info>
0174     struct is_equal_to_sixteen : mp11::mp_and
0175         <
0176             mp11::mp_not
0177             <
0178                 mp11::mp_less
0179                 <
0180                     std::integral_constant<int, Info::_bit_depth>,
0181                     std::integral_constant<int, 16>
0182                 >
0183             >,
0184             mp11::mp_not
0185             <
0186                 mp11::mp_less
0187                 <
0188                     std::integral_constant<int, 16>,
0189                     std::integral_constant<int, Info::_bit_depth>
0190                 >
0191             >
0192         >
0193     {};
0194 
0195     template <typename Info>
0196     void set_swap(typename std::enable_if<is_less_than_eight<Info>::value>::type* /*ptr*/ = 0)
0197     {
0198         png_set_packswap(this->get_struct());
0199     }
0200 
0201     template <typename Info>
0202     void set_swap(typename std::enable_if<is_equal_to_sixteen<Info>::value>::type* /*ptr*/ = 0)
0203     {
0204         png_set_swap(this->get_struct());
0205     }
0206 
0207     template <typename Info>
0208     void set_swap(
0209         typename std::enable_if
0210         <
0211             mp11::mp_and
0212             <
0213                 mp11::mp_not<is_less_than_eight<Info>>,
0214                 mp11::mp_not<is_equal_to_sixteen<Info>>
0215             >::value
0216         >::type* /*ptr*/ = nullptr)
0217     {
0218     }
0219 };
0220 
0221 ///
0222 /// PNG Dynamic Image Writer
0223 ///
0224 template< typename Device >
0225 class dynamic_image_writer< Device
0226                           , png_tag
0227                           >
0228     : public writer< Device
0229                    , png_tag
0230                    >
0231 {
0232     using parent_t = writer<Device, png_tag>;
0233 
0234 public:
0235 
0236     dynamic_image_writer( const Device&                      io_dev
0237                         , const image_write_info< png_tag >& info
0238 )
0239     : parent_t( io_dev
0240               , info
0241               )
0242     {}
0243 
0244     template< typename ...Views >
0245     void apply( const any_image_view< Views... >& views )
0246     {
0247         detail::dynamic_io_fnobj< detail::png_write_is_supported
0248                                 , parent_t
0249                                 > op( this );
0250 
0251         variant2::visit( op, views );
0252     }
0253 };
0254 
0255 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0256 #pragma warning(pop)
0257 #endif
0258 
0259 } // namespace gil
0260 } // namespace boost
0261 
0262 #endif