File indexing completed on 2025-01-18 09:36:58
0001
0002
0003
0004
0005
0006
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)
0018 #endif
0019
0020
0021
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
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
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
0110 char read_char()
0111 {
0112 char ch;
0113
0114 if(( ch = _io_dev.getc() ) == '#' )
0115 {
0116
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
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 }
0179 }
0180
0181 #endif