Claw  1.7.3
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@gamned.org
24 */
30 #include <claw/targa.hpp>
31 #include <claw/exception.hpp>
32 
33 
34 
35 //********************* targa::reader::file_input_buffer ***********************
36 
37 
38 
39 namespace claw
40 {
41  namespace graphic
42  {
43  /*------------------------------------------------------------------------*/
50  template< >
51  rgba_pixel_8 targa::reader::file_input_buffer<rgba_pixel_8>::get_pixel()
52  {
53  rgba_pixel_8 result;
54 
55  if ( this->remaining() < 4 )
56  this->read_more(4);
57 
58  assert( this->remaining() >= 4 );
59 
60  result.components.blue = this->get_next();
61  result.components.green = this->get_next();
62  result.components.red = this->get_next();
63  result.components.alpha = this->get_next();
64 
65  return result;
66  } // targa::reader::file_input_buffer::get_pixel()
67  } // namespace graphic
68 } // namespace claw
69 
70 namespace claw
71 {
72  namespace graphic
73  {
74  /*------------------------------------------------------------------------*/
81  template< >
82  rgba_pixel_8 targa::reader::file_input_buffer<rgb_pixel_8>::get_pixel()
83  {
84  rgba_pixel_8 result;
85 
86  if ( this->remaining() < 3 )
87  this->read_more(3);
88 
89  assert( this->remaining() >= 3 );
90 
91  result.components.blue = this->get_next();
92  result.components.green = this->get_next();
93  result.components.red = this->get_next();
94  result.components.alpha =
95  std::numeric_limits<claw::graphic::rgba_pixel_8::component_type>::max();
96 
97  return result;
98  } // targa::reader::file_input_buffer::get_pixel()
99  } // namespace graphic
100 } // namespace claw
101 
102 namespace claw
103 {
104  namespace graphic
105  {
106  /*------------------------------------------------------------------------*/
113  template< >
114  rgba_pixel_8 targa::reader::file_input_buffer<targa::pixel16>::get_pixel()
115  {
116  rgba_pixel_8 result;
117 
118  if ( this->remaining() < 2 )
119  this->read_more(2);
120 
121  assert( this->remaining() >= 2 );
122 
123  unsigned char second_byte = this->get_next();
124  unsigned char first_byte = this->get_next();
125 
126  unsigned char r = (first_byte & 0x7C) >> 2;
127  unsigned char g =
128  ((first_byte & 0x03) << 3) | ((second_byte & 0xE0) >> 5);
129  unsigned char b = second_byte & 0x1F;
130 
131  result.components.blue = b * 8;
132  result.components.green = g * 8;
133  result.components.red = r * 8;
134  result.components.alpha =
135  std::numeric_limits<claw::graphic::rgba_pixel_8::component_type>::max();
136 
137  return result;
138  } // targa::reader::file_input_buffer::get_pixel()
139  } // namespace graphic
140 } // namespace claw
141 
142 
143 
144 
145 
146 
147 
148 //****************** targa::reader::mapped_file_input_buffer *******************
149 
150 
151 
152 namespace claw
153 {
154  namespace graphic
155  {
156  /*------------------------------------------------------------------------*/
163  template< >
165  targa::reader::mapped_file_input_buffer<targa::pixel8>::get_pixel()
166  {
167  if ( this->remaining() < 1 )
168  this->read_more(1);
169 
170  assert( this->remaining() >= 1 );
171 
172  unsigned char index = this->get_next();
173 
174  return m_palette[index];
175  } // targa::reader::mapped_file_input_buffer::get_pixel()
176  } // namespace graphic
177 } // namespace claw
178 
179 
180 
181 
182 
183 //****************************** targa::reader *********************************
184 
185 
186 
187 
188 /*----------------------------------------------------------------------------*/
194  : m_image( img )
195 {
196 
197 } // targa::reader::reader()
198 
199 /*----------------------------------------------------------------------------*/
207  : m_image( img )
208 {
209  load(f);
210 } // targa::reader::reader()
211 
212 /*----------------------------------------------------------------------------*/
217 void claw::graphic::targa::reader::load( std::istream& f )
218 {
219  CLAW_PRECOND( !!f );
220  std::istream::pos_type init_pos = f.tellg();
221 
222  try
223  {
224  check_if_targa(f);
225 
226  header h;
227 
228  f.read( reinterpret_cast<char*>(&h), sizeof(header) );
229 
230  if ( f.rdstate() == std::ios_base::goodbit )
231  {
232  m_image.set_size( h.image_specification.width,
234 
235  switch(h.image_type)
236  {
237  case color_mapped: load_color_mapped(h, f); break;
238  case rle_color_mapped: load_rle_color_mapped(h, f); break;
239  case true_color: load_true_color(h, f); break;
240  case rle_true_color: load_rle_true_color(h, f); break;
241  default :
242  throw claw::bad_format
243  ( "targa::reader::targa: unsupported image type" );
244  }
245  }
246  else
247  throw claw::bad_format
248  ( "claw::targa::reader::targa: can't read header" );
249  }
250  catch(...)
251  {
252  f.clear();
253  f.seekg( init_pos, std::ios_base::beg );
254  throw;
255  }
256 } // targa::reader::load()
257 
258 /*----------------------------------------------------------------------------*/
263 void claw::graphic::targa::reader::check_if_targa( std::istream& f ) const
264 {
265  CLAW_PRECOND( !!f );
266 
267  std::istream::pos_type init_pos = f.tellg();
268 
269  footer foot;
270 
271  f.seekg( -(std::istream::off_type)sizeof(footer), std::ios::end );
272  f.read( reinterpret_cast<char*>(&foot), sizeof(footer) );
273  f.seekg( init_pos , std::ios::beg );
274 
275  if ( !foot.is_valid() )
276  throw CLAW_EXCEPTION( "Not a Targa file." );
277 } // targa::reader::check_if_targa()
278 
279 /*----------------------------------------------------------------------------*/
287 void claw::graphic::targa::reader::load_palette
288 ( const header& h, std::istream& f, color_palette32& palette ) const
289 {
290  assert((h.image_type == color_mapped) || (h.image_type == rle_color_mapped));
291 
292  switch( h.color_map_specification.entry_size )
293  {
294  case 16: load_palette_content<pixel16>(f, palette); break;
295  case 24: load_palette_content<rgb_pixel_8>(f, palette); break;
296  case 32: load_palette_content<rgba_pixel_8>(f, palette); break;
297  default:
298  throw claw::bad_format
299  ( "targa::reader::load_palette: unsupported entry size" );
300  }
301 } // targa::reader::load_palette()
302 
303 /*----------------------------------------------------------------------------*/
310 void claw::graphic::targa::reader::load_color_mapped
311 ( const header& h, std::istream& f )
312 {
313  assert(h.image_type == color_mapped);
314 
315  f.seekg( h.id_length, std::ios_base::cur );
316 
317  color_palette32 palette( h.color_map_specification.length );
318  load_palette( h, f, palette );
319 
320  switch(h.image_specification.bpp)
321  {
322  case 8: load_color_mapped_raw<pixel8>(h, f, palette); break;
323  default:
324  throw claw::bad_format
325  ( "targa::reader::load_color_mapped: unsupported color depth" );
326  }
327 } // targa::reader::load_color_mapped()
328 
329 /*----------------------------------------------------------------------------*/
336 void claw::graphic::targa::reader::load_rle_color_mapped
337 ( const header& h, std::istream& f )
338 {
339  assert(h.image_type == rle_color_mapped);
340 
341  f.seekg( h.id_length, std::ios_base::cur );
342 
343  color_palette32 palette( h.color_map_specification.length );
344  load_palette( h, f, palette );
345 
346  switch(h.image_specification.bpp)
347  {
348  case 8: decompress_rle_color_mapped<rle8_decoder>(h, f, palette); break;
349  default:
350  throw claw::bad_format
351  ( "targa::reader::load_rle_color_mapped: unsupported color depth" );
352  }
353 } // targa::reader::load_color_mapped()
354 
355 /*----------------------------------------------------------------------------*/
362 void claw::graphic::targa::reader::load_true_color
363 ( const header& h, std::istream& f )
364 {
365  assert(h.image_type == true_color);
366 
367  f.seekg( h.id_length, std::ios_base::cur );
368 
369  switch(h.image_specification.bpp)
370  {
371  case 16 : load_true_color_raw<pixel16>(h, f); break;
372  case 24 : load_true_color_raw<rgb_pixel_8>(h, f); break;
373  case 32 : load_true_color_raw<rgba_pixel_8>(h, f); break;
374  default :
375  throw claw::bad_format
376  ( "targa::reader::load_true_color: unsupported color depth" );
377  }
378 } // targa::reader::load_true_color()
379 
380 /*----------------------------------------------------------------------------*/
387 void claw::graphic::targa::reader::load_rle_true_color
388 ( const header& h, std::istream& f )
389 {
390  assert(h.image_type == rle_true_color);
391 
392  f.seekg( h.id_length, std::ios_base::cur );
393 
394  switch(h.image_specification.bpp)
395  {
396  case 16 : decompress_rle_true_color<rle16_decoder>(h, f); break;
397  case 24 : decompress_rle_true_color<rle24_decoder>(h, f); break;
398  case 32 : decompress_rle_true_color<rle32_decoder>(h, f); break;
399  default :
400  throw claw::bad_format
401  ( "targa::reader::load_rle_true_color: unsupported color depth" );
402  }
403 } // targa::reader::load_rle_true_color()
404