claw  1.9.0
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@stuff-o-matic.com
24 */
30 #include <claw/graphic/xbm.hpp>
31 
32 #include <claw/assert.hpp>
33 #include <claw/exception.hpp>
35 
41  : m_image(img)
42  , m_hot(NULL)
43 {}
44 
52  : m_image(img)
53  , m_hot(NULL)
54 {
55  load(f);
56 }
57 
65  : m_image(img)
66  , m_hot(NULL)
67 {
68  load(f);
69  img.set_name(m_name);
70 
71  if(m_hot != NULL)
72  img.set_hot(*m_hot);
73 }
74 
79 {
80  if(m_hot != NULL)
81  {
82  delete m_hot;
83  m_hot = NULL;
84  }
85 }
86 
91 void claw::graphic::xbm::reader::load(std::istream& f)
92 {
93  CLAW_PRECOND(!!f);
94 
95  std::istream::pos_type init_pos = f.tellg();
96 
97  if(m_hot != NULL)
98  {
99  delete m_hot;
100  m_hot = NULL;
101  }
102 
103  try
104  {
105  read_from_file(f);
106  }
107  catch(...)
108  {
109  if(m_hot != NULL)
110  delete m_hot;
111 
112  f.clear();
113  f.seekg(init_pos, std::ios_base::beg);
114  throw;
115  }
116 }
117 
122 void claw::graphic::xbm::reader::read_from_file(std::istream& f)
123 {
124  std::string line;
125  bool valid_format = false;
126  unsigned int bpe;
127 
128  read_size(f);
129  bpe = read_bits_per_entry(f);
130  read_name(f);
131  read_line(f, line, '{');
132 
133  if(!line.empty())
134  {
135  read_pixels(f, bpe);
136  read_line(f, line, ';');
137 
138  valid_format = true;
139  }
140 
141  if(!valid_format)
142  throw claw::exception("Not an XBM file.");
143 }
144 
149 void claw::graphic::xbm::reader::read_size(std::istream& f)
150 {
151  unsigned int w(0), h(0);
152  bool valid = true;
153  bool stop = false;
154  std::string line;
155 
156  while(valid && !stop)
157  {
158  std::ios::pos_type pos = f.tellg();
159 
160  read_line(f, line, '\n');
161 
162  if(!line.empty())
163  {
164  if(line.find("width") != std::string::npos)
165  w = read_dim(line);
166  else if(line.find("height") != std::string::npos)
167  h = read_dim(line);
168  else if(line.find("x_hot") != std::string::npos)
169  {
170  if(m_hot == NULL)
171  m_hot = new claw::math::coordinate_2d<int>;
172 
173  m_hot->x = read_dim(line);
174  }
175  else if(line.find("y_hot") != std::string::npos)
176  {
177  if(m_hot == NULL)
178  m_hot = new claw::math::coordinate_2d<int>;
179 
180  m_hot->y = read_dim(line);
181  }
182  else if(line.find("static") != std::string::npos)
183  {
184  stop = true;
185  f.seekg(pos);
186  }
187  }
188  else
189  valid = false;
190  }
191 
192  if(valid)
193  m_image.set_size(w, h);
194  else
195  throw claw::exception("Not an XBM file.");
196 }
197 
202 unsigned int
203 claw::graphic::xbm::reader::read_dim(const std::string& line) const
204 {
205  unsigned int result;
206  std::istringstream iss(line);
207  std::string token;
208  bool valid = false;
209 
210  if(iss >> token)
211  if(token == "#define")
212  if(iss >> token)
213  if(iss >> result)
214  valid = true;
215 
216  if(!valid)
217  throw claw::exception("Not an XBM file.");
218 
219  return result;
220 }
221 
226 unsigned int
227 claw::graphic::xbm::reader::read_bits_per_entry(std::istream& f) const
228 {
229  std::string line;
230  unsigned int result(0);
231 
232  std::string token;
233 
234  if(f >> token)
235  if(token == "static")
236  if(f >> token)
237  {
238  if(token == "unsigned")
239  f >> token;
240  else if(token == "signed")
241  f >> token;
242 
243  if(token == "char")
244  result = sizeof(char) * 8;
245  else if(token == "short")
246  result = sizeof(short) * 8;
247  else if(token == "int")
248  result = sizeof(int) * 8;
249  else if(token == "long")
250  result = sizeof(long) * 8;
251  }
252 
253  if(result == 0)
254  throw claw::exception("Not an XBM file.");
255 
256  return result;
257 }
258 
263 void claw::graphic::xbm::reader::read_name(std::istream& f)
264 {
265  bool valid = false;
266  std::string line;
267 
268  read_line(f, line, '[');
269 
270  if(!line.empty())
271  {
272  std::string::size_type end = line.find_last_of('_');
273 
274  if(end != std::string::npos)
275  {
276  std::string::size_type begin = line.find_last_of(" \t", end);
277 
278  if(begin == std::string::npos)
279  begin = 0;
280 
281  m_name = line.substr(begin, end - begin);
282  valid = true;
283  }
284  }
285 
286  if(!valid)
287  throw claw::exception("Not an XBM file.");
288 }
289 
295 void claw::graphic::xbm::reader::read_pixels(std::istream& f,
296  unsigned int bpe) const
297 {
298  image::iterator first = m_image.begin();
299  const image::iterator last = m_image.end();
300 
301  bool valid = true;
302 
303  unsigned int x = 0;
304 
305  while((first != last) && valid)
306  {
307  std::string s_val;
308  read_line(f, s_val, ',');
309 
310  std::istringstream iss(s_val);
311  long int val;
312 
313  if(iss >> std::hex >> val)
314  {
315  for(unsigned int i = 0;
316  (i != bpe) && (first != last) && (x != m_image.width());
317  ++i, ++first, ++x, val >>= 1)
318  if(val & 1)
319  *first = black_pixel;
320  else
321  *first = white_pixel;
322 
323  if(x == m_image.width())
324  x = 0;
325  }
326  else
327  valid = false;
328  }
329 
330  if(!valid)
331  throw claw::exception("Not an XBM file.");
332 }
333 
340 void claw::graphic::xbm::reader::read_line(std::istream& f, std::string& line,
341  char endchar) const
342 {
343  bool stop = false;
344 
345  line.clear();
346 
347  while(!stop)
348  if(std::getline(f, line, endchar))
349  {
350  text::trim(line);
351 
352  remove_comments(f, line, endchar);
353  stop = !line.empty();
354  }
355  else
356  stop = true;
357 }
358 
365 void claw::graphic::xbm::reader::remove_comments(std::istream& f,
366  std::string& line,
367  char endchar) const
368 {
369  std::string working(line);
370  std::string::size_type beg = working.find("/*");
371 
372  if(beg != std::string::npos)
373  {
374  line = working.substr(0, beg);
375 
376  std::string::size_type end = working.rfind("*/");
377  bool stop = false;
378 
379  while((end == std::string::npos) && !stop)
380  if(std::getline(f, working, endchar))
381  end = working.find("*/");
382  else
383  stop = true;
384 
385  if(!stop)
386  {
387  line += working.substr(end + 2, line.length() - end - 2);
388  text::trim(line);
389  }
390 
391  if(!line.empty())
392  remove_comments(f, line, endchar);
393  }
394 }
rgba_pixel black_pixel
The black color.
void load(std::istream &f)
Load an image from a xbm file.
Definition: xbm_reader.cpp:91
A class for xbm pictures.
Definition: xbm.hpp:46
iterator end()
Get an iterator pointing just past the last pixel.
Definition: image.cpp:157
A simple class to use as exception with string message.
Definition: exception.hpp:42
void set_name(const std::string &name)
Set the name of the image.
Definition: xbm.cpp:84
base_iterator< image, pixel_type > iterator
The type of the iterator on the pixels of the image.
Definition: image.hpp:195
reader(image &img)
Constructor.
Definition: xbm_reader.cpp:40
value_type y
Y-coordinate.
void set_hot(const claw::math::coordinate_2d< int > &hot)
Set the hot spot of the image.
Definition: xbm.cpp:93
A simple class to use as exception with string message.
iterator begin()
Get an iterator pointing on the first pixel.
Definition: image.cpp:149
Some assert macros to strengthen you code.
A class to deal with images.
Definition: image.hpp:50
rgba_pixel white_pixel
The white color.
A class for xbm pictures.
#define CLAW_PRECOND(b)
Abort the program if a precondition is not true.
Definition: assert.hpp:94
Generic algorithms on strings.
value_type x
X-coordinate.