Claw 1.7.3
xbm_reader.cpp
Go to the documentation of this file.
1/*
2 CLAW - a C++ Library Absolutely Wonderful
3
4 CLAW is a free library without any particular aim but being useful to
5 anyone.
6
7 Copyright (C) 2005-2011 Julien Jorge
8
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
13
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
23 contact: julien.jorge@gamned.org
24*/
30#include <claw/xbm.hpp>
31
32#include <claw/exception.hpp>
33#include <claw/assert.hpp>
35
36/*----------------------------------------------------------------------------*/
42 : m_image( img ), m_hot(NULL)
43{
44
45} // xbm::reader::reader()
46
47/*----------------------------------------------------------------------------*/
55 : m_image( img ), m_hot(NULL)
56{
57 load(f);
58} // xbm::reader::reader()
59
60/*----------------------------------------------------------------------------*/
68 : m_image( img ), m_hot(NULL)
69{
70 load(f);
71 img.set_name( m_name );
72
73 if (m_hot != NULL)
74 img.set_hot( *m_hot );
75} // xbm::reader::reader()
76
77/*----------------------------------------------------------------------------*/
82{
83 if (m_hot != NULL)
84 {
85 delete m_hot;
86 m_hot = NULL;
87 }
88} // xbm::reader::~reader()
89
90/*----------------------------------------------------------------------------*/
95void claw::graphic::xbm::reader::load( std::istream& f )
96{
97 CLAW_PRECOND( !!f );
98
99 std::istream::pos_type init_pos = f.tellg();
100
101 if (m_hot != NULL)
102 {
103 delete m_hot;
104 m_hot = NULL;
105 }
106
107 try
108 {
109 read_from_file(f);
110 }
111 catch(...)
112 {
113 if (m_hot != NULL)
114 delete m_hot;
115
116 f.clear();
117 f.seekg( init_pos, std::ios_base::beg );
118 throw;
119 }
120} // xbm::reader::load()
121
122/*----------------------------------------------------------------------------*/
127void claw::graphic::xbm::reader::read_from_file( std::istream& f )
128{
129 std::string line;
130 bool valid_format = false;
131 unsigned int bpe;
132
133 read_size(f);
134 bpe = read_bits_per_entry(f);
135 read_name(f);
136 read_line( f, line, '{' );
137
138 if ( !line.empty() )
139 {
140 read_pixels(f, bpe);
141 read_line(f, line, ';');
142
143 valid_format = true;
144 }
145
146 if ( !valid_format )
147 throw claw::exception( "Not an XBM file." );
148} // xbm::reader::read_from_file()
149
150/*----------------------------------------------------------------------------*/
155void claw::graphic::xbm::reader::read_size( std::istream& f )
156{
157 unsigned int w(0), h(0);
158 bool valid = true;
159 bool stop = false;
160 std::string line;
161
162 while ( valid && !stop )
163 {
164 std::ios::pos_type pos = f.tellg();
165
166 read_line( f, line, '\n' );
167
168 if ( !line.empty() )
169 {
170 if ( line.find("width") != std::string::npos )
171 w = read_dim(line);
172 else if ( line.find("height") != std::string::npos )
173 h = read_dim(line);
174 else if ( line.find("x_hot") != std::string::npos )
175 {
176 if ( m_hot == NULL )
178
179 m_hot->x = read_dim(line);
180 }
181 else if ( line.find("y_hot") != std::string::npos )
182 {
183 if ( m_hot == NULL )
185
186 m_hot->y = read_dim(line);
187 }
188 else if ( line.find("static") != std::string::npos )
189 {
190 stop = true;
191 f.seekg( pos );
192 }
193 }
194 else
195 valid = false;
196 }
197
198 if ( valid )
199 m_image.set_size(w, h);
200 else
201 throw claw::exception( "Not an XBM file." );
202} // xbm::reader::read_size()
203
204/*----------------------------------------------------------------------------*/
209unsigned int
210claw::graphic::xbm::reader::read_dim( const std::string& line ) const
211{
212 unsigned int result;
213 std::istringstream iss(line);
214 std::string token;
215 bool valid = false;
216
217 if (iss >> token)
218 if ( token == "#define" )
219 if ( iss >> token )
220 if ( iss >> result )
221 valid = true;
222
223 if ( !valid )
224 throw claw::exception( "Not an XBM file." );
225
226 return result;
227} // xbm::reader::read_dim()
228
229/*----------------------------------------------------------------------------*/
234unsigned int
235claw::graphic::xbm::reader::read_bits_per_entry( std::istream& f ) const
236{
237 std::string line;
238 unsigned int result(0);
239
240 std::string token;
241
242 if ( f >> token )
243 if ( token == "static" )
244 if ( f >> token )
245 {
246 if ( token == "unsigned" )
247 f >> token;
248 else if ( token == "signed" )
249 f >> token;
250
251 if ( token == "char" )
252 result = sizeof(char) * 8;
253 else if ( token == "short" )
254 result = sizeof(short) * 8;
255 else if ( token == "int" )
256 result = sizeof(int) * 8;
257 else if ( token == "long" )
258 result = sizeof(long) * 8;
259 }
260
261 if ( result == 0 )
262 throw claw::exception( "Not an XBM file." );
263
264 return result;
265} // xbm::reader::read_bits_per_entry()
266
267/*----------------------------------------------------------------------------*/
272void claw::graphic::xbm::reader::read_name( std::istream& f )
273{
274 bool valid = false;
275 std::string line;
276
277 read_line(f, line, '[');
278
279 if ( !line.empty() )
280 {
281 std::string::size_type end = line.find_last_of('_');
282
283 if ( end != std::string::npos )
284 {
285 std::string::size_type begin = line.find_last_of(" \t", end);
286
287 if ( begin == std::string::npos )
288 begin = 0;
289
290 m_name = line.substr(begin, end - begin);
291 valid = true;
292 }
293 }
294
295 if ( !valid )
296 throw claw::exception( "Not an XBM file." );
297} // xbm::reader::read_name()
298
299/*----------------------------------------------------------------------------*/
305void claw::graphic::xbm::reader::read_pixels
306( std::istream& f, unsigned int bpe ) const
307{
308 image::iterator first = m_image.begin();
309 const image::iterator last = m_image.end();
310
311 bool valid = true;
312
313 unsigned int x = 0;
314
315 while ( (first!=last) && valid )
316 {
317 std::string s_val;
318 read_line( f, s_val, ',' );
319
320 std::istringstream iss(s_val);
321 long int val;
322
323 if ( iss >> std::hex >> val )
324 {
325 for( unsigned int i=0;
326 (i!=bpe) && (first!=last) && (x!=m_image.width());
327 ++i, ++first, ++x, val >>= 1 )
328 if ( val & 1 )
329 *first = black_pixel;
330 else
331 *first = white_pixel;
332
333 if ( x==m_image.width() )
334 x = 0;
335 }
336 else
337 valid = false;
338 }
339
340 if ( !valid )
341 throw claw::exception( "Not an XBM file." );
342} // xbm::reader::read_pixels()
343
344/*----------------------------------------------------------------------------*/
351void claw::graphic::xbm::reader::read_line
352( std::istream& f, std::string& line, char endchar ) const
353{
354 bool stop = false;
355
356 line.clear();
357
358 while ( !stop )
359 if ( std::getline( f, line, endchar ) )
360 {
361 text::trim(line);
362
363
364 remove_comments(f, line, endchar);
365 stop = !line.empty();
366 }
367 else
368 stop = true;
369} // xbm::reader::read_line()
370
371/*----------------------------------------------------------------------------*/
379void claw::graphic::xbm::reader::remove_comments
380( std::istream& f, std::string& line, char endchar ) const
381{
382 std::string working(line);
383 std::string::size_type beg = working.find( "/*" );
384
385 if ( beg != std::string::npos )
386 {
387 line = working.substr(0, beg);
388
389 std::string::size_type end = working.rfind( "*/" );
390 bool stop = false;
391
392 while ( (end == std::string::npos) && !stop )
393 if ( std::getline(f, working, endchar) )
394 end = working.find( "*/" );
395 else
396 stop = true;
397
398 if ( !stop )
399 {
400 line += working.substr(end+2, line.length() - end - 2);
401 text::trim(line);
402 }
403
404 if ( !line.empty() )
405 remove_comments(f, line, endchar);
406 }
407} // xbm::reader::remove_comments()
Some assert macros to strengthen you code.
#define CLAW_PRECOND(b)
Abort the program if a precondition is not true.
Definition assert.hpp:98
A simple class to use as exception with string message.
Definition exception.hpp:44
A class to deal with images.
Definition image.hpp:50
base_iterator< image, pixel_type > iterator
The type of the iterator on the pixels of the image.
Definition image.hpp:195
iterator end()
Get an iterator pointing just past the last pixel.
Definition image.cpp:177
iterator begin()
Get an iterator pointing on the first pixel.
Definition image.cpp:168
reader(image &img)
Constructor.
void load(std::istream &f)
Load an image from a xbm file.
A class for xbm pictures.
Definition xbm.hpp:46
void set_hot(const claw::math::coordinate_2d< int > &hot)
Set the hot spot of the image.
Definition xbm.cpp:102
void set_name(const std::string &name)
Set the name of the image.
Definition xbm.cpp:92
Coordinates in a two dimensional space.
value_type x
X-coordinate.
value_type y
Y-coordinate.
A simple class to use as exception with string message.
rgba_pixel black_pixel(0, 0, 0, std::numeric_limits< rgba_pixel::component_type >::max())
The black color.
Definition pixel.hpp:136
rgba_pixel white_pixel
The white color.
Generic algorithms on strings.
A class for xbm pictures.