Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:36:58

0001 //
0002 // Copyright 2012 Christian Henning
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_PNM_DETAIL_WRITE_HPP
0009 #define BOOST_GIL_EXTENSION_IO_PNM_DETAIL_WRITE_HPP
0010 
0011 #include <boost/gil/extension/io/pnm/tags.hpp>
0012 #include <boost/gil/extension/io/pnm/detail/writer_backend.hpp>
0013 
0014 #include <boost/gil/io/base.hpp>
0015 #include <boost/gil/io/bit_operations.hpp>
0016 #include <boost/gil/io/device.hpp>
0017 #include <boost/gil/io/detail/dynamic.hpp>
0018 #include <boost/gil/detail/mp11.hpp>
0019 
0020 #include <cstdlib>
0021 #include <string>
0022 #include <type_traits>
0023 
0024 namespace boost { namespace gil {
0025 
0026 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0027 #pragma warning(push)
0028 #pragma warning(disable:4512) //assignment operator could not be generated
0029 #endif
0030 
0031 namespace detail {
0032 
0033 struct pnm_write_is_supported
0034 {
0035     template< typename View >
0036     struct apply
0037         : public is_write_supported< typename get_pixel_type< View >::type
0038                                    , pnm_tag
0039                                    >
0040     {};
0041 };
0042 
0043 } // namespace detail
0044 
0045 ///
0046 /// PNM Writer
0047 ///
0048 template< typename Device >
0049 class writer< Device
0050             , pnm_tag
0051             >
0052     : public writer_backend< Device
0053                            , pnm_tag
0054                            >
0055 {
0056 private:
0057     using backend_t = writer_backend<Device, pnm_tag>;
0058 
0059 public:
0060 
0061     writer( const Device&                      io_dev
0062           , const image_write_info< pnm_tag >& info
0063           )
0064     : backend_t( io_dev
0065                 , info
0066                 )
0067     {}
0068 
0069     template< typename View >
0070     void apply( const View& view )
0071     {
0072         using pixel_t = typename get_pixel_type<View>::type;
0073 
0074         std::size_t width  = view.width();
0075         std::size_t height = view.height();
0076 
0077         std::size_t chn    = num_channels< View >::value;
0078         std::size_t pitch  = chn * width;
0079 
0080         unsigned int type = get_type< num_channels< View >::value >( is_bit_aligned< pixel_t >() );
0081 
0082         // write header
0083 
0084         // Add a white space at each string so read_int() can decide when a numbers ends.
0085 
0086         std::string str( "P" );
0087         str += std::to_string( type ) + std::string( " " );
0088         this->_io_dev.print_line( str );
0089 
0090         str.clear();
0091         str += std::to_string( width ) + std::string( " " );
0092         this->_io_dev.print_line( str );
0093 
0094         str.clear();
0095         str += std::to_string( height ) + std::string( " " );
0096         this->_io_dev.print_line( str );
0097 
0098         if( type != pnm_image_type::mono_bin_t::value )
0099         {
0100             this->_io_dev.print_line( "255 ");
0101         }
0102 
0103         // write data
0104         write_data( view
0105                   , pitch
0106                   , typename is_bit_aligned< pixel_t >::type()
0107                   );
0108     }
0109 
0110 private:
0111 
0112     template< int Channels >
0113     unsigned int get_type( std::true_type  /* is_bit_aligned */ )
0114     {
0115         return mp11::mp_if_c
0116             <
0117                 Channels == 1,
0118                 pnm_image_type::mono_bin_t,
0119                 pnm_image_type::color_bin_t
0120             >::value;
0121     }
0122 
0123     template< int Channels >
0124     unsigned int get_type( std::false_type /* is_bit_aligned */ )
0125     {
0126         return mp11::mp_if_c
0127             <
0128                 Channels == 1,
0129                 pnm_image_type::gray_bin_t,
0130                 pnm_image_type::color_bin_t
0131             >::value;
0132     }
0133 
0134     template< typename View >
0135     void write_data( const View&   src
0136                    , std::size_t   pitch
0137                    , const std::true_type&    // bit_aligned
0138                    )
0139     {
0140         static_assert(std::is_same<View, typename gray1_image_t::view_t>::value, "");
0141 
0142         byte_vector_t row( pitch / 8 );
0143 
0144         using x_it_t = typename View::x_iterator;
0145         x_it_t row_it = x_it_t( &( *row.begin() ));
0146 
0147         detail::negate_bits<byte_vector_t, std::true_type> negate;
0148         detail::mirror_bits<byte_vector_t, std::true_type> mirror;
0149         for (typename View::y_coord_t y = 0; y < src.height(); ++y)
0150         {
0151             std::copy(src.row_begin(y), src.row_end(y), row_it);
0152 
0153             mirror(row);
0154             negate(row);
0155 
0156             this->_io_dev.write(&row.front(), pitch / 8);
0157         }
0158     }
0159 
0160     template< typename View >
0161     void write_data( const View&   src
0162                    , std::size_t   pitch
0163                    , const std::false_type&    // bit_aligned
0164                    )
0165     {
0166         std::vector< pixel< typename channel_type< View >::type
0167                           , layout<typename color_space_type< View >::type >
0168                           >
0169                    > buf( src.width() );
0170 
0171         // using pixel_t = typename View::value_type;
0172         // using view_t = typename view_type_from_pixel< pixel_t >::type;
0173 
0174         //view_t row = interleaved_view( src.width()
0175         //                             , 1
0176         //                             , reinterpret_cast< pixel_t* >( &buf.front() )
0177         //                             , pitch
0178         //                             );
0179 
0180         byte_t* row_addr = reinterpret_cast< byte_t* >( &buf.front() );
0181 
0182         for( typename View::y_coord_t y = 0
0183            ; y < src.height()
0184            ; ++y
0185            )
0186         {
0187             //copy_pixels( subimage_view( src
0188             //                          , 0
0189             //                          , (int) y
0190             //                          , (int) src.width()
0191             //                          , 1
0192             //                          )
0193             //           , row
0194             //           );
0195 
0196             std::copy( src.row_begin( y )
0197                      , src.row_end  ( y )
0198                      , buf.begin()
0199                      );
0200 
0201             this->_io_dev.write( row_addr, pitch );
0202         }
0203     }
0204 };
0205 
0206 ///
0207 /// PNM Writer
0208 ///
0209 template< typename Device >
0210 class dynamic_image_writer< Device
0211                           , pnm_tag
0212                           >
0213     : public writer< Device
0214                    , pnm_tag
0215                    >
0216 {
0217     using parent_t = writer<Device, pnm_tag>;
0218 
0219 public:
0220 
0221     dynamic_image_writer( const Device&                      io_dev
0222                         , const image_write_info< pnm_tag >& info
0223                         )
0224     : parent_t( io_dev
0225               , info
0226               )
0227     {}
0228 
0229     template< typename ...Views >
0230     void apply( const any_image_view< Views... >& views )
0231     {
0232         detail::dynamic_io_fnobj< detail::pnm_write_is_supported
0233                                 , parent_t
0234                                 > op( this );
0235 
0236         variant2::visit( op, views );
0237     }
0238 };
0239 
0240 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0241 #pragma warning(pop)
0242 #endif
0243 
0244 } // gil
0245 } // boost
0246 
0247 #endif