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_READ_HPP
0009 #define BOOST_GIL_EXTENSION_IO_PNM_DETAIL_READ_HPP
0010 
0011 #include <boost/gil/extension/io/pnm/tags.hpp>
0012 #include <boost/gil/extension/io/pnm/detail/reader_backend.hpp>
0013 #include <boost/gil/extension/io/pnm/detail/is_allowed.hpp>
0014 
0015 #include <boost/gil.hpp> // FIXME: Include what you use!
0016 #include <boost/gil/io/detail/dynamic.hpp>
0017 #include <boost/gil/io/base.hpp>
0018 #include <boost/gil/io/bit_operations.hpp>
0019 #include <boost/gil/io/conversion_policies.hpp>
0020 #include <boost/gil/io/device.hpp>
0021 #include <boost/gil/io/reader_base.hpp>
0022 #include <boost/gil/io/row_buffer_helper.hpp>
0023 #include <boost/gil/io/typedefs.hpp>
0024 
0025 #include <type_traits>
0026 #include <vector>
0027 
0028 namespace boost { namespace gil {
0029 
0030 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0031 #pragma warning(push)
0032 #pragma warning(disable:4512) //assignment operator could not be generated
0033 #endif
0034 
0035 ///
0036 /// PNM Reader
0037 ///
0038 template< typename Device
0039         , typename ConversionPolicy
0040         >
0041 class reader< Device
0042             , pnm_tag
0043             , ConversionPolicy
0044             >
0045     : public reader_base< pnm_tag
0046                         , ConversionPolicy
0047                         >
0048     , public reader_backend< Device
0049                            , pnm_tag
0050                            >
0051 {
0052 
0053 private:
0054 
0055     using this_t = reader<Device, pnm_tag, ConversionPolicy>;
0056     using cc_t = typename ConversionPolicy::color_converter_type;
0057 
0058 public:
0059 
0060     using backend_t = reader_backend<Device, pnm_tag>;
0061 
0062     reader( const Device&                         io_dev
0063           , const image_read_settings< pnm_tag >& settings
0064           )
0065     : reader_base< pnm_tag
0066                  , ConversionPolicy
0067                  >()
0068     , backend_t( io_dev
0069                , settings
0070                )
0071     {}
0072 
0073     reader( const Device&                         io_dev
0074           , const cc_t&                           cc
0075           , const image_read_settings< pnm_tag >& settings
0076           )
0077     : reader_base< pnm_tag
0078                  , ConversionPolicy
0079                  >( cc )
0080     , backend_t( io_dev
0081                , settings
0082                )
0083     {}
0084 
0085     template<typename View>
0086     void apply( const View& view )
0087     {
0088         using is_read_and_convert_t = typename std::is_same
0089             <
0090                 ConversionPolicy,
0091                 detail::read_and_no_convert
0092             >::type;
0093 
0094         io_error_if( !detail::is_allowed< View >( this->_info
0095                                                 , is_read_and_convert_t()
0096                                                 )
0097                    , "Image types aren't compatible."
0098                    );
0099 
0100         switch( this->_info._type )
0101         {
0102             // reading mono text is reading grayscale but with only two values
0103             case pnm_image_type::mono_asc_t::value:
0104             case pnm_image_type::gray_asc_t::value:
0105             {
0106                 this->_scanline_length = this->_info._width;
0107 
0108                 read_text_data< gray8_view_t >( view );
0109 
0110                 break;
0111             }
0112 
0113             case pnm_image_type::color_asc_t::value:
0114             {
0115                 this->_scanline_length = this->_info._width * num_channels< rgb8_view_t >::value;
0116 
0117                 read_text_data< rgb8_view_t  >( view );
0118 
0119                 break;
0120             }
0121 
0122             case pnm_image_type::mono_bin_t::value:
0123             {
0124                 //gray1_image_t
0125                 this->_scanline_length = ( this->_info._width + 7 ) >> 3;
0126 
0127                 read_bin_data< gray1_image_t::view_t >( view );
0128 
0129                 break;
0130             }
0131 
0132             case pnm_image_type::gray_bin_t::value:
0133             {
0134                 // gray8_image_t
0135                 this->_scanline_length = this->_info._width;
0136 
0137                 read_bin_data< gray8_view_t >( view );
0138 
0139                 break;
0140             }
0141 
0142             case pnm_image_type::color_bin_t::value:
0143             {
0144                 // rgb8_image_t
0145                 this->_scanline_length = this->_info._width * num_channels< rgb8_view_t >::value;
0146 
0147                 read_bin_data< rgb8_view_t >( view );
0148                 break;
0149             }
0150         }
0151     }
0152 
0153 private:
0154 
0155     template< typename View_Src
0156             , typename View_Dst
0157             >
0158     void read_text_data( const View_Dst& dst )
0159     {
0160         using y_t = typename View_Dst::y_coord_t;
0161 
0162         byte_vector_t row( this->_scanline_length );
0163 
0164         //Skip scanlines if necessary.
0165         for( int y = 0; y <  this->_settings._top_left.y; ++y )
0166         {
0167             read_text_row< View_Src >( dst, row, y, false );
0168         }
0169 
0170         for( y_t y = 0; y < dst.height(); ++y )
0171         {
0172             read_text_row< View_Src >( dst, row, y, true );
0173         }
0174     }
0175 
0176     template< typename View_Src
0177             , typename View_Dst
0178             >
0179     void read_text_row( const View_Dst&              dst
0180                       , byte_vector_t&               row
0181                       , typename View_Dst::y_coord_t y
0182                       , bool                         process
0183                       )
0184     {
0185         View_Src src = interleaved_view( this->_info._width
0186                                        , 1
0187                                        , (typename View_Src::value_type*) &row.front()
0188                                        , this->_scanline_length
0189                                        );
0190 
0191         for( uint32_t x = 0; x < this->_scanline_length; ++x )
0192         {
0193             for( uint32_t k = 0; ; )
0194             {
0195                 int ch = this->_io_dev.getc_unchecked();
0196 
0197                 if( isdigit( ch ))
0198                 {
0199                     buf[ k++ ] = static_cast< char >( ch );
0200                 }
0201                 else if( k )
0202                 {
0203                     buf[ k ] = 0;
0204                     break;
0205                 }
0206                 else if( ch == EOF || !isspace( ch ))
0207                 {
0208                     return;
0209                 }
0210             }
0211 
0212             if( process )
0213             {
0214                 int value = atoi( buf );
0215 
0216                 if( this->_info._max_value == 1 )
0217                 {
0218                     using channel_t = typename channel_type<typename get_pixel_type<View_Dst>::type>::type;
0219 
0220                     // for pnm format 0 is white
0221                     row[x] = ( value != 0 )
0222                              ? typename channel_traits< channel_t >::value_type( 0 )
0223                              : channel_traits< channel_t >::max_value();
0224                 }
0225                 else
0226                 {
0227                     row[x] = static_cast< byte_t >( value );
0228                 }
0229             }
0230         }
0231 
0232         if( process )
0233         {
0234             // We are reading a gray1_image like a gray8_image but the two pixel_t
0235             // aren't compatible. Though, read_and_no_convert::read(...) wont work.
0236             copy_data< View_Dst
0237                      , View_Src >( dst
0238                                  , src
0239                                  , y
0240                                  , typename std::is_same< View_Dst
0241                                                    , gray1_image_t::view_t
0242                                                    >::type()
0243                                  );
0244         }
0245     }
0246 
0247     template< typename View_Dst
0248             , typename View_Src
0249             >
0250     void copy_data( const View_Dst&              dst
0251                   , const View_Src&              src
0252                   , typename View_Dst::y_coord_t y
0253                   , std::true_type // is gray1_view
0254                   )
0255     {
0256         if(  this->_info._max_value == 1 )
0257         {
0258             typename View_Dst::x_iterator it = dst.row_begin( y );
0259 
0260             for( typename View_Dst::x_coord_t x = 0
0261                ; x < dst.width()
0262                ; ++x
0263                )
0264             {
0265                 it[x] = src[x];
0266             }
0267         }
0268         else
0269         {
0270             copy_data(dst, src, y, std::false_type{});
0271         }
0272     }
0273 
0274     template< typename View_Dst
0275             , typename View_Src
0276             >
0277     void copy_data( const View_Dst&              view
0278                   , const View_Src&              src
0279                   , typename View_Dst::y_coord_t y
0280                   , std::false_type // is gray1_view
0281                   )
0282     {
0283         typename View_Src::x_iterator beg = src.row_begin( 0 ) + this->_settings._top_left.x;
0284         typename View_Src::x_iterator end = beg + this->_settings._dim.x;
0285 
0286         this->_cc_policy.read( beg
0287                              , end
0288                              , view.row_begin( y )
0289                              );
0290     }
0291 
0292 
0293     template< typename View_Src
0294             , typename View_Dst
0295             >
0296     void read_bin_data( const View_Dst& view )
0297     {
0298         using y_t = typename View_Dst::y_coord_t;
0299         using is_bit_aligned_t = typename is_bit_aligned<typename View_Src::value_type>::type;
0300 
0301         using rh_t = detail::row_buffer_helper_view<View_Src>;
0302         rh_t rh( this->_scanline_length, true );
0303 
0304         typename rh_t::iterator_t beg = rh.begin() + this->_settings._top_left.x;
0305         typename rh_t::iterator_t end = beg + this->_settings._dim.x;
0306 
0307         // For bit_aligned images we need to negate all bytes in the row_buffer
0308         // to make sure that 0 is black and 255 is white.
0309         detail::negate_bits
0310             <
0311                 typename rh_t::buffer_t,
0312                 std::integral_constant<bool, is_bit_aligned_t::value> // TODO: Simplify after MPL removal
0313             > neg;
0314 
0315         detail::swap_half_bytes
0316             <
0317                 typename rh_t::buffer_t,
0318                 std::integral_constant<bool, is_bit_aligned_t::value> // TODO: Simplify after MPL removal
0319             > swhb;
0320 
0321         //Skip scanlines if necessary.
0322         for( y_t y = 0; y < this->_settings._top_left.y; ++y )
0323         {
0324             this->_io_dev.read( reinterpret_cast< byte_t* >( rh.data() )
0325                         , this->_scanline_length
0326                         );
0327         }
0328 
0329         for( y_t y = 0; y < view.height(); ++y )
0330         {
0331             this->_io_dev.read( reinterpret_cast< byte_t* >( rh.data() )
0332                         , this->_scanline_length
0333                         );
0334 
0335             neg( rh.buffer() );
0336             swhb( rh.buffer() );
0337 
0338             this->_cc_policy.read( beg
0339                                  , end
0340                                  , view.row_begin( y )
0341                                  );
0342         }
0343     }
0344 
0345 private:
0346 
0347     char buf[16];
0348 
0349 };
0350 
0351 
0352 namespace detail {
0353 
0354 struct pnm_type_format_checker
0355 {
0356     pnm_type_format_checker( pnm_image_type::type type )
0357     : _type( type )
0358     {}
0359 
0360     template< typename Image >
0361     bool apply()
0362     {
0363         using is_supported_t = is_read_supported
0364             <
0365                 typename get_pixel_type<typename Image::view_t>::type,
0366                 pnm_tag
0367             >;
0368 
0369         return is_supported_t::_asc_type == _type
0370             || is_supported_t::_bin_type == _type;
0371     }
0372 
0373 private:
0374 
0375     pnm_image_type::type _type;
0376 };
0377 
0378 struct pnm_read_is_supported
0379 {
0380     template< typename View >
0381     struct apply : public is_read_supported< typename get_pixel_type< View >::type
0382                                            , pnm_tag
0383                                            >
0384     {};
0385 };
0386 
0387 } // namespace detail
0388 
0389 ///
0390 /// PNM Dynamic Image Reader
0391 ///
0392 template< typename Device
0393         >
0394 class dynamic_image_reader< Device
0395                           , pnm_tag
0396                           >
0397     : public reader< Device
0398                    , pnm_tag
0399                    , detail::read_and_no_convert
0400                    >
0401 {
0402     using parent_t = reader
0403         <
0404             Device,
0405             pnm_tag,
0406             detail::read_and_no_convert
0407         >;
0408 
0409 public:
0410 
0411     dynamic_image_reader( const Device&                         io_dev
0412                         , const image_read_settings< pnm_tag >& settings
0413                         )
0414     : parent_t( io_dev
0415               , settings
0416               )
0417     {}
0418 
0419     template< typename ...Images >
0420     void apply( any_image< Images... >& images )
0421     {
0422         detail::pnm_type_format_checker format_checker( this->_info._type );
0423 
0424         if( !detail::construct_matched( images
0425                               , format_checker
0426                               ))
0427         {
0428             io_error( "No matching image type between those of the given any_image and that of the file" );
0429         }
0430         else
0431         {
0432             this->init_image( images
0433                             , this->_settings
0434                             );
0435 
0436             detail::dynamic_io_fnobj< detail::pnm_read_is_supported
0437                                     , parent_t
0438                                     > op( this );
0439 
0440             variant2::visit( op
0441                            ,view( images )
0442                            );
0443         }
0444     }
0445 };
0446 
0447 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0448 #pragma warning(pop)
0449 #endif
0450 
0451 } // gil
0452 } // boost
0453 
0454 #endif