claw 1.9.0
 
Loading...
Searching...
No Matches
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
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
122void 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
149void 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)
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)
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
202unsigned int
203claw::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
226unsigned int
227claw::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
263void 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
295void 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
340void 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
365void 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}
Some assert macros to strengthen you code.
#define CLAW_PRECOND(b)
Abort the program if a precondition is not true.
Definition assert.hpp:94
A simple class to use as exception with string message.
Definition exception.hpp:43
iterator end()
Get an iterator pointing just past the last pixel.
Definition image.cpp:157
image()
Constructor. Creates an image without datas.
Definition image.cpp:95
base_iterator< image, pixel_type > iterator
The type of the iterator on the pixels of the image.
Definition image.hpp:195
iterator begin()
Get an iterator pointing on the first pixel.
Definition image.cpp:149
reader(image &img)
Constructor.
void load(std::istream &f)
Load an image from a xbm file.
xbm(unsigned int w, unsigned int h)
Constructor. Creates an empty image.
Definition xbm.cpp:38
void set_hot(const claw::math::coordinate_2d< int > &hot)
Set the hot spot of the image.
Definition xbm.cpp:93
void set_name(const std::string &name)
Set the name of the image.
Definition xbm.cpp:84
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 white_pixel
The white color.
rgba_pixel black_pixel
The black color.
Generic algorithms on strings.
A class for xbm pictures.