xbm_reader.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00030 #include <claw/xbm.hpp>
00031
00032 #include <claw/exception.hpp>
00033 #include <claw/assert.hpp>
00034 #include <claw/string_algorithm.hpp>
00035
00036
00041 claw::graphic::xbm::reader::reader( image& img )
00042 : m_image( img ), m_hot(NULL)
00043 {
00044
00045 }
00046
00047
00054 claw::graphic::xbm::reader::reader( image& img, std::istream& f )
00055 : m_image( img ), m_hot(NULL)
00056 {
00057 load(f);
00058 }
00059
00060
00067 claw::graphic::xbm::reader::reader( xbm& img, std::istream& f )
00068 : m_image( img ), m_hot(NULL)
00069 {
00070 load(f);
00071 img.set_name( m_name );
00072
00073 if (m_hot != NULL)
00074 img.set_hot( *m_hot );
00075 }
00076
00077
00081 claw::graphic::xbm::reader::~reader()
00082 {
00083 if (m_hot != NULL)
00084 {
00085 delete m_hot;
00086 m_hot = NULL;
00087 }
00088 }
00089
00090
00095 void claw::graphic::xbm::reader::load( std::istream& f )
00096 {
00097 CLAW_PRECOND( !!f );
00098
00099 std::istream::pos_type init_pos = f.tellg();
00100
00101 if (m_hot != NULL)
00102 {
00103 delete m_hot;
00104 m_hot = NULL;
00105 }
00106
00107 try
00108 {
00109 read_from_file(f);
00110 }
00111 catch(...)
00112 {
00113 if (m_hot != NULL)
00114 delete m_hot;
00115
00116 f.clear();
00117 f.seekg( init_pos, std::ios_base::beg );
00118 throw;
00119 }
00120 }
00121
00122
00127 void claw::graphic::xbm::reader::read_from_file( std::istream& f )
00128 {
00129 std::string line;
00130 bool valid_format = false;
00131 unsigned int bpe;
00132
00133 read_size(f);
00134 bpe = read_bits_per_entry(f);
00135 read_name(f);
00136 read_line( f, line, '{' );
00137
00138 if ( !line.empty() )
00139 {
00140 read_pixels(f, bpe);
00141 read_line(f, line, ';');
00142
00143 valid_format = true;
00144 }
00145
00146 if ( !valid_format )
00147 throw CLAW_EXCEPTION( "Not a XBM file." );
00148 }
00149
00150
00155 void claw::graphic::xbm::reader::read_size( std::istream& f )
00156 {
00157 unsigned int w(0), h(0);
00158 bool valid = true;
00159 bool stop = false;
00160 std::string line;
00161
00162 while ( valid && !stop )
00163 {
00164 std::ios::pos_type pos = f.tellg();
00165
00166 read_line( f, line, '\n' );
00167
00168 if ( !line.empty() )
00169 {
00170 if ( line.find("width") != std::string::npos )
00171 w = read_dim(line);
00172 else if ( line.find("height") != std::string::npos )
00173 h = read_dim(line);
00174 else if ( line.find("x_hot") != std::string::npos )
00175 {
00176 if ( m_hot == NULL )
00177 m_hot = new claw::math::coordinate_2d<int>;
00178
00179 m_hot->x = read_dim(line);
00180 }
00181 else if ( line.find("y_hot") != std::string::npos )
00182 {
00183 if ( m_hot == NULL )
00184 m_hot = new claw::math::coordinate_2d<int>;
00185
00186 m_hot->y = read_dim(line);
00187 }
00188 else if ( line.find("static") != std::string::npos )
00189 {
00190 stop = true;
00191 f.seekg( pos );
00192 }
00193 }
00194 else
00195 valid = false;
00196 }
00197
00198 if ( valid )
00199 m_image.set_size(w, h);
00200 else
00201 throw CLAW_EXCEPTION( "Not a XBM file." );
00202 }
00203
00204
00209 unsigned int
00210 claw::graphic::xbm::reader::read_dim( const std::string& line ) const
00211 {
00212 unsigned int result;
00213 std::istringstream iss(line);
00214 std::string token;
00215 bool valid = false;
00216
00217 if (iss >> token)
00218 if ( token == "#define" )
00219 if ( iss >> token )
00220 if ( iss >> result )
00221 valid = true;
00222
00223 if ( !valid )
00224 throw CLAW_EXCEPTION( "Not a XBM file." );
00225
00226 return result;
00227 }
00228
00229
00234 unsigned int
00235 claw::graphic::xbm::reader::read_bits_per_entry( std::istream& f ) const
00236 {
00237 std::string line;
00238 unsigned int result(0);
00239
00240 std::string token;
00241
00242 if ( f >> token )
00243 if ( token == "static" )
00244 if ( f >> token )
00245 {
00246 if ( token == "unsigned" )
00247 f >> token;
00248 else if ( token == "signed" )
00249 f >> token;
00250
00251 if ( token == "char" )
00252 result = sizeof(char) * 8;
00253 else if ( token == "short" )
00254 result = sizeof(short) * 8;
00255 else if ( token == "int" )
00256 result = sizeof(int) * 8;
00257 else if ( token == "long" )
00258 result = sizeof(long) * 8;
00259 }
00260
00261 if ( result == 0 )
00262 throw CLAW_EXCEPTION( "Not a XBM file." );
00263
00264 return result;
00265 }
00266
00267
00272 void claw::graphic::xbm::reader::read_name( std::istream& f )
00273 {
00274 bool valid = false;
00275 std::string line;
00276
00277 read_line(f, line, '[');
00278
00279 if ( !line.empty() )
00280 {
00281 std::string::size_type end = line.find_last_of('_');
00282
00283 if ( end != std::string::npos )
00284 {
00285 std::string::size_type begin = line.find_last_of(" \t", end);
00286
00287 if ( begin == std::string::npos )
00288 begin = 0;
00289
00290 m_name = line.substr(begin, end - begin);
00291 valid = true;
00292 }
00293 }
00294
00295 if ( !valid )
00296 throw CLAW_EXCEPTION( "Not a XBM file." );
00297 }
00298
00299
00305 void claw::graphic::xbm::reader::read_pixels
00306 ( std::istream& f, unsigned int bpe ) const
00307 {
00308 image::iterator first = m_image.begin();
00309 const image::iterator last = m_image.end();
00310
00311 bool valid = true;
00312
00313 unsigned int x = 0;
00314
00315 while ( (first!=last) && valid )
00316 {
00317 std::string s_val;
00318 read_line( f, s_val, ',' );
00319
00320 std::istringstream iss(s_val);
00321 long int val;
00322
00323 if ( iss >> std::hex >> val )
00324 {
00325 for( unsigned int i=0;
00326 (i!=bpe) && (first!=last) && (x!=m_image.width());
00327 ++i, ++first, ++x, val >>= 1 )
00328 if ( val & 1 )
00329 *first = black_pixel;
00330 else
00331 *first = white_pixel;
00332
00333 if ( x==m_image.width() )
00334 x = 0;
00335 }
00336 else
00337 valid = false;
00338 }
00339
00340 if ( !valid )
00341 throw CLAW_EXCEPTION( "Not a XBM file." );
00342 }
00343
00344
00351 void claw::graphic::xbm::reader::read_line
00352 ( std::istream& f, std::string& line, char endchar ) const
00353 {
00354 bool stop = false;
00355
00356 line.clear();
00357
00358 while ( !stop )
00359 if ( std::getline( f, line, endchar ) )
00360 {
00361 text::trim(line);
00362
00363
00364 remove_comments(f, line, endchar);
00365 stop = !line.empty();
00366 }
00367 else
00368 stop = true;
00369 }
00370
00371
00379 void claw::graphic::xbm::reader::remove_comments
00380 ( std::istream& f, std::string& line, char endchar ) const
00381 {
00382 std::string working(line);
00383 std::string::size_type beg = working.find( "/*" );
00384
00385 if ( beg != std::string::npos )
00386 {
00387 line = working.substr(0, beg);
00388
00389 std::string::size_type end = working.rfind( "*/" );
00390 bool stop = false;
00391
00392 while ( (end == std::string::npos) && !stop )
00393 if ( std::getline(f, working, endchar) )
00394 end = working.find( "*/" );
00395 else
00396 stop = true;
00397
00398 if ( !stop )
00399 {
00400 line += working.substr(end+2, line.length() - end - 2);
00401 text::trim(line);
00402 }
00403
00404 if ( !line.empty() )
00405 remove_comments(f, line, endchar);
00406 }
00407 }