claw  1.9.0
targa_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/targa.hpp>
31 
32 #include <claw/exception.hpp>
33 
34 //********************* targa::reader::file_input_buffer
35 //***********************
36 
37 namespace claw
38 {
39  namespace graphic
40  {
47  template <>
48  rgba_pixel_8 targa::reader::file_input_buffer<rgba_pixel_8>::get_pixel()
49  {
50  rgba_pixel_8 result;
51 
52  if(this->remaining() < 4)
53  this->read_more(4);
54 
55  assert(this->remaining() >= 4);
56 
57  result.components.blue = this->get_next();
58  result.components.green = this->get_next();
59  result.components.red = this->get_next();
60  result.components.alpha = this->get_next();
61 
62  return result;
63  }
64  }
65 }
66 
67 namespace claw
68 {
69  namespace graphic
70  {
77  template <>
78  rgba_pixel_8 targa::reader::file_input_buffer<rgb_pixel_8>::get_pixel()
79  {
80  rgba_pixel_8 result;
81 
82  if(this->remaining() < 3)
83  this->read_more(3);
84 
85  assert(this->remaining() >= 3);
86 
87  result.components.blue = this->get_next();
88  result.components.green = this->get_next();
89  result.components.red = this->get_next();
90  result.components.alpha = std::numeric_limits<
92 
93  return result;
94  }
95  }
96 }
97 
98 namespace claw
99 {
100  namespace graphic
101  {
108  template <>
109  rgba_pixel_8 targa::reader::file_input_buffer<targa::pixel16>::get_pixel()
110  {
111  rgba_pixel_8 result;
112 
113  if(this->remaining() < 2)
114  this->read_more(2);
115 
116  assert(this->remaining() >= 2);
117 
118  unsigned char second_byte = this->get_next();
119  unsigned char first_byte = this->get_next();
120 
121  unsigned char r = (first_byte & 0x7C) >> 2;
122  unsigned char g
123  = ((first_byte & 0x03) << 3) | ((second_byte & 0xE0) >> 5);
124  unsigned char b = second_byte & 0x1F;
125 
126  result.components.blue = b * 8;
127  result.components.green = g * 8;
128  result.components.red = r * 8;
129  result.components.alpha = std::numeric_limits<
131 
132  return result;
133  }
134  }
135 }
136 
137 //****************** targa::reader::mapped_file_input_buffer
138 //*******************
139 
140 namespace claw
141 {
142  namespace graphic
143  {
150  template <>
152  targa::reader::mapped_file_input_buffer<targa::pixel8>::get_pixel()
153  {
154  if(this->remaining() < 1)
155  this->read_more(1);
156 
157  assert(this->remaining() >= 1);
158 
159  unsigned char index = this->get_next();
160 
161  return m_palette[index];
162  }
163  }
164 }
165 
166 //****************************** targa::reader
167 //*********************************
168 
174  : m_image(img)
175 {}
176 
184  : m_image(img)
185 {
186  load(f);
187 }
188 
194 {
195  CLAW_PRECOND(!!f);
196  std::istream::pos_type init_pos = f.tellg();
197 
198  try
199  {
200  check_if_targa(f);
201 
202  header h;
203 
204  f.read(reinterpret_cast<char*>(&h), sizeof(header));
205 
206  if(f.rdstate() == std::ios_base::goodbit)
207  {
208  m_image.set_size(h.image_specification.width,
210 
211  switch(h.image_type)
212  {
213  case color_mapped:
214  load_color_mapped(h, f);
215  break;
216  case rle_color_mapped:
217  load_rle_color_mapped(h, f);
218  break;
219  case true_color:
220  load_true_color(h, f);
221  break;
222  case rle_true_color:
223  load_rle_true_color(h, f);
224  break;
225  default:
226  throw claw::bad_format(
227  "targa::reader::targa: unsupported image type");
228  }
229  }
230  else
231  throw claw::bad_format(
232  "claw::targa::reader::targa: can't read header");
233  }
234  catch(...)
235  {
236  f.clear();
237  f.seekg(init_pos, std::ios_base::beg);
238  throw;
239  }
240 }
241 
246 void claw::graphic::targa::reader::check_if_targa(std::istream& f) const
247 {
248  CLAW_PRECOND(!!f);
249 
250  std::istream::pos_type init_pos = f.tellg();
251 
252  footer foot;
253 
254  f.seekg(-(std::istream::off_type)sizeof(footer), std::ios::end);
255  f.read(reinterpret_cast<char*>(&foot), sizeof(footer));
256  f.seekg(init_pos, std::ios::beg);
257 
258  if(!foot.is_valid())
259  throw CLAW_EXCEPTION("Not a Targa file.");
260 }
261 
269 void claw::graphic::targa::reader::load_palette(const header& h,
270  std::istream& f,
271  color_palette32& palette) const
272 {
273  assert((h.image_type == color_mapped) || (h.image_type == rle_color_mapped));
274 
275  switch(h.color_map_specification.entry_size)
276  {
277  case 16:
278  load_palette_content<pixel16>(f, palette);
279  break;
280  case 24:
281  load_palette_content<rgb_pixel_8>(f, palette);
282  break;
283  case 32:
284  load_palette_content<rgba_pixel_8>(f, palette);
285  break;
286  default:
287  throw claw::bad_format(
288  "targa::reader::load_palette: unsupported entry size");
289  }
290 }
291 
298 void claw::graphic::targa::reader::load_color_mapped(const header& h,
299  std::istream& f)
300 {
301  assert(h.image_type == color_mapped);
302 
303  f.seekg(h.id_length, std::ios_base::cur);
304 
305  color_palette32 palette(h.color_map_specification.length);
306  load_palette(h, f, palette);
307 
308  switch(h.image_specification.bpp)
309  {
310  case 8:
311  load_color_mapped_raw<pixel8>(h, f, palette);
312  break;
313  default:
314  throw claw::bad_format(
315  "targa::reader::load_color_mapped: unsupported color depth");
316  }
317 }
318 
325 void claw::graphic::targa::reader::load_rle_color_mapped(const header& h,
326  std::istream& f)
327 {
328  assert(h.image_type == rle_color_mapped);
329 
330  f.seekg(h.id_length, std::ios_base::cur);
331 
332  color_palette32 palette(h.color_map_specification.length);
333  load_palette(h, f, palette);
334 
335  switch(h.image_specification.bpp)
336  {
337  case 8:
338  decompress_rle_color_mapped<rle8_decoder>(h, f, palette);
339  break;
340  default:
341  throw claw::bad_format(
342  "targa::reader::load_rle_color_mapped: unsupported color depth");
343  }
344 }
345 
352 void claw::graphic::targa::reader::load_true_color(const header& h,
353  std::istream& f)
354 {
355  assert(h.image_type == true_color);
356 
357  f.seekg(h.id_length, std::ios_base::cur);
358 
359  switch(h.image_specification.bpp)
360  {
361  case 16:
362  load_true_color_raw<pixel16>(h, f);
363  break;
364  case 24:
365  load_true_color_raw<rgb_pixel_8>(h, f);
366  break;
367  case 32:
368  load_true_color_raw<rgba_pixel_8>(h, f);
369  break;
370  default:
371  throw claw::bad_format(
372  "targa::reader::load_true_color: unsupported color depth");
373  }
374 }
375 
382 void claw::graphic::targa::reader::load_rle_true_color(const header& h,
383  std::istream& f)
384 {
385  assert(h.image_type == rle_true_color);
386 
387  f.seekg(h.id_length, std::ios_base::cur);
388 
389  switch(h.image_specification.bpp)
390  {
391  case 16:
392  decompress_rle_true_color<rle16_decoder>(h, f);
393  break;
394  case 24:
395  decompress_rle_true_color<rle24_decoder>(h, f);
396  break;
397  case 32:
398  decompress_rle_true_color<rle32_decoder>(h, f);
399  break;
400  default:
401  throw claw::bad_format(
402  "targa::reader::load_rle_true_color: unsupported color depth");
403  }
404 }
reader(image &img)
Constructor.
void load(std::istream &f)
Load an image from a targa file.
rgba_pixel rgba_pixel_8
A color with 8 bits per component and an alpha channel.
Definition: pixel.hpp:126
A simple class to use as exception with string message.
unsigned char component_type
The type of the components of the color.
Definition: pixel.hpp:82
A class to deal with images.
Definition: image.hpp:50
A class for targa pictures.
This is the main namespace.
Definition: application.hpp:49
specification image_specification
The specification of the image.
Definition: targa.hpp:123
#define CLAW_EXCEPTION(m)
Create an exception and add the name of the current function to the message.
Definition: exception.hpp:92
#define CLAW_PRECOND(b)
Abort the program if a precondition is not true.
Definition: assert.hpp:94
Exception thrown when accessing bad formated data.
Definition: exception.hpp:73