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_READER_BACKEND_HPP
0009 #define BOOST_GIL_EXTENSION_IO_PNM_DETAIL_READER_BACKEND_HPP
0010 
0011 #include <boost/gil/extension/io/pnm/tags.hpp>
0012 
0013 namespace boost { namespace gil {
0014 
0015 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0016 #pragma warning(push)
0017 #pragma warning(disable:4512) //assignment operator could not be generated
0018 #endif
0019 
0020 ///
0021 /// PNM Backend
0022 ///
0023 template< typename Device >
0024 struct reader_backend< Device
0025                      , pnm_tag
0026                      >
0027 {
0028 public:
0029 
0030     using format_tag_t = pnm_tag;
0031 
0032 public:
0033 
0034     reader_backend( const Device&                         io_dev
0035                   , const image_read_settings< pnm_tag >& settings
0036                   )
0037     : _io_dev  ( io_dev   )
0038     , _settings( settings )
0039     , _info()
0040 
0041     , _scanline_length( 0 )
0042     {
0043         read_header();
0044 
0045         if( _settings._dim.x == 0 )
0046         {
0047             _settings._dim.x = _info._width;
0048         }
0049 
0050         if( _settings._dim.y == 0 )
0051         {
0052             _settings._dim.y = _info._height;
0053         }
0054     }
0055 
0056     void read_header()
0057     {
0058         // read signature
0059         io_error_if( read_char() != 'P', "Invalid PNM signature" );
0060 
0061         _info._type = read_char() - '0';
0062 
0063         io_error_if( _info._type < pnm_image_type::mono_asc_t::value || _info._type > pnm_image_type::color_bin_t::value
0064                    , "Invalid PNM file (supports P1 to P6)"
0065                    );
0066 
0067         _info._width  = read_int();
0068         _info._height = read_int();
0069 
0070         if( _info._type == pnm_image_type::mono_asc_t::value || _info._type == pnm_image_type::mono_bin_t::value )
0071         {
0072             _info._max_value = 1;
0073         }
0074         else
0075         {
0076             _info._max_value = read_int();
0077 
0078             io_error_if( _info._max_value > 255
0079                        , "Unsupported PNM format (supports maximum value 255)"
0080                        );
0081         }
0082     }
0083 
0084     /// Check if image is large enough.
0085     void check_image_size( point_t const& img_dim )
0086     {
0087         if( _settings._dim.x > 0 )
0088         {
0089             if( img_dim.x < _settings._dim.x ) { io_error( "Supplied image is too small" ); }
0090         }
0091         else
0092         {
0093             if( img_dim.x < _info._width ) { io_error( "Supplied image is too small" ); }
0094         }
0095 
0096 
0097         if( _settings._dim.y > 0 )
0098         {
0099             if( img_dim.y < _settings._dim.y ) { io_error( "Supplied image is too small" ); }
0100         }
0101         else
0102         {
0103             if( img_dim.y < _info._height ) { io_error( "Supplied image is too small" ); }
0104         }
0105     }
0106 
0107 private:
0108 
0109     // Read a character and skip a comment if necessary.
0110     char read_char()
0111     {
0112         char ch;
0113 
0114         if(( ch = _io_dev.getc() ) == '#' )
0115         {
0116             // skip comment to EOL
0117             do
0118             {
0119                 ch = _io_dev.getc();
0120             }
0121             while (ch != '\n' && ch != '\r');
0122         }
0123 
0124         return ch;
0125     }
0126 
0127     unsigned int read_int()
0128     {
0129         char ch;
0130 
0131         // skip whitespaces, tabs, and new lines
0132         do
0133         {
0134             ch = read_char();
0135         }
0136         while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r');
0137 
0138         if( ch < '0' || ch > '9' )
0139         {
0140             io_error( "Unexpected characters reading decimal digits" );
0141         }
0142 
0143         unsigned val = 0;
0144 
0145         do
0146         {
0147             unsigned dig = ch - '0';
0148 
0149             if( val > INT_MAX / 10 - dig )
0150             {
0151                 io_error( "Integer too large" );
0152             }
0153 
0154             val = val * 10 + dig;
0155 
0156             ch = read_char();
0157         }
0158         while( '0' <= ch && ch <= '9' );
0159 
0160         return val;
0161     }
0162 
0163 
0164 public:
0165 
0166     Device _io_dev;
0167 
0168     image_read_settings< pnm_tag > _settings;
0169     image_read_info< pnm_tag >     _info;
0170 
0171     std::size_t _scanline_length;
0172 };
0173 
0174 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0175 #pragma warning(pop)
0176 #endif
0177 
0178 } // namespace gil
0179 } // namespace boost
0180 
0181 #endif