123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- //
- // Copyright 2012 Christian Henning
- //
- // Distributed under the Boost Software License, Version 1.0
- // See accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt
- //
- #ifndef BOOST_GIL_EXTENSION_IO_PNM_DETAIL_READER_BACKEND_HPP
- #define BOOST_GIL_EXTENSION_IO_PNM_DETAIL_READER_BACKEND_HPP
- #include <boost/gil/extension/io/pnm/tags.hpp>
- namespace boost { namespace gil {
- #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
- #pragma warning(push)
- #pragma warning(disable:4512) //assignment operator could not be generated
- #endif
- ///
- /// PNM Backend
- ///
- template< typename Device >
- struct reader_backend< Device
- , pnm_tag
- >
- {
- public:
- using format_tag_t = pnm_tag;
- public:
- reader_backend( const Device& io_dev
- , const image_read_settings< pnm_tag >& settings
- )
- : _io_dev ( io_dev )
- , _settings( settings )
- , _info()
- , _scanline_length( 0 )
- {
- read_header();
- if( _settings._dim.x == 0 )
- {
- _settings._dim.x = _info._width;
- }
- if( _settings._dim.y == 0 )
- {
- _settings._dim.y = _info._height;
- }
- }
- void read_header()
- {
- // read signature
- io_error_if( read_char() != 'P', "Invalid PNM signature" );
- _info._type = read_char() - '0';
- io_error_if( _info._type < pnm_image_type::mono_asc_t::value || _info._type > pnm_image_type::color_bin_t::value
- , "Invalid PNM file (supports P1 to P6)"
- );
- _info._width = read_int();
- _info._height = read_int();
- if( _info._type == pnm_image_type::mono_asc_t::value || _info._type == pnm_image_type::mono_bin_t::value )
- {
- _info._max_value = 1;
- }
- else
- {
- _info._max_value = read_int();
- io_error_if( _info._max_value > 255
- , "Unsupported PNM format (supports maximum value 255)"
- );
- }
- }
- /// Check if image is large enough.
- void check_image_size( point_t const& img_dim )
- {
- if( _settings._dim.x > 0 )
- {
- if( img_dim.x < _settings._dim.x ) { io_error( "Supplied image is too small" ); }
- }
- else
- {
- if( img_dim.x < _info._width ) { io_error( "Supplied image is too small" ); }
- }
- if( _settings._dim.y > 0 )
- {
- if( img_dim.y < _settings._dim.y ) { io_error( "Supplied image is too small" ); }
- }
- else
- {
- if( img_dim.y < _info._height ) { io_error( "Supplied image is too small" ); }
- }
- }
- private:
- // Read a character and skip a comment if necessary.
- char read_char()
- {
- char ch;
- if(( ch = _io_dev.getc() ) == '#' )
- {
- // skip comment to EOL
- do
- {
- ch = _io_dev.getc();
- }
- while (ch != '\n' && ch != '\r');
- }
- return ch;
- }
- unsigned int read_int()
- {
- char ch;
- // skip whitespaces, tabs, and new lines
- do
- {
- ch = read_char();
- }
- while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r');
- if( ch < '0' || ch > '9' )
- {
- io_error( "Unexpected characters reading decimal digits" );
- }
- unsigned val = 0;
- do
- {
- unsigned dig = ch - '0';
- if( val > INT_MAX / 10 - dig )
- {
- io_error( "Integer too large" );
- }
- val = val * 10 + dig;
- ch = read_char();
- }
- while( '0' <= ch && ch <= '9' );
- return val;
- }
- public:
- Device _io_dev;
- image_read_settings< pnm_tag > _settings;
- image_read_info< pnm_tag > _info;
- std::size_t _scanline_length;
- };
- #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
- #pragma warning(pop)
- #endif
- } // namespace gil
- } // namespace boost
- #endif
|