targa_reader.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00030 #include <claw/targa.hpp>
00031 #include <claw/exception.hpp>
00032
00033
00034
00035
00036
00037
00038
00039 namespace claw
00040 {
00041 namespace graphic
00042 {
00043
00050 template< >
00051 pixel32 targa::reader::file_input_buffer<pixel32>::get_pixel()
00052 {
00053 pixel32 result;
00054
00055 if ( this->remaining() < 4 )
00056 this->read_more(4);
00057
00058 assert( this->remaining() >= 4 );
00059
00060 result.components.blue = this->get_next();
00061 result.components.green = this->get_next();
00062 result.components.red = this->get_next();
00063 result.components.alpha = this->get_next();
00064
00065 return result;
00066 }
00067 }
00068 }
00069
00070 namespace claw
00071 {
00072 namespace graphic
00073 {
00074
00081 template< >
00082 pixel32 targa::reader::file_input_buffer<pixel24>::get_pixel()
00083 {
00084 pixel32 result;
00085
00086 if ( this->remaining() < 3 )
00087 this->read_more(3);
00088
00089 assert( this->remaining() >= 3 );
00090
00091 result.components.blue = this->get_next();
00092 result.components.green = this->get_next();
00093 result.components.red = this->get_next();
00094 result.components.alpha =
00095 std::numeric_limits<claw::graphic::pixel32::component_type>::max();
00096
00097 return result;
00098 }
00099 }
00100 }
00101
00102 namespace claw
00103 {
00104 namespace graphic
00105 {
00106
00113 template< >
00114 pixel32 targa::reader::file_input_buffer<targa::pixel16>::get_pixel()
00115 {
00116 pixel32 result;
00117
00118 if ( this->remaining() < 2 )
00119 this->read_more(2);
00120
00121 assert( this->remaining() >= 2 );
00122
00123 unsigned char second_byte = this->get_next();
00124 unsigned char first_byte = this->get_next();
00125
00126 unsigned char r = (first_byte & 0x7C) >> 2;
00127 unsigned char g =
00128 ((first_byte & 0x03) << 3) | ((second_byte & 0xE0) >> 5);
00129 unsigned char b = second_byte & 0x1F;
00130
00131 result.components.blue = b * 8;
00132 result.components.green = g * 8;
00133 result.components.red = r * 8;
00134 result.components.alpha =
00135 std::numeric_limits<claw::graphic::pixel32::component_type>::max();
00136
00137 return result;
00138 }
00139 }
00140 }
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 namespace claw
00153 {
00154 namespace graphic
00155 {
00156
00163 template< >
00164 pixel32 targa::reader::mapped_file_input_buffer<targa::pixel8>::get_pixel()
00165 {
00166 if ( this->remaining() < 1 )
00167 this->read_more(1);
00168
00169 assert( this->remaining() >= 1 );
00170
00171 unsigned char index = this->get_next();
00172
00173 return m_palette[index];
00174 }
00175 }
00176 }
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00192 claw::graphic::targa::reader::reader( image& img )
00193 : m_image( img )
00194 {
00195
00196 }
00197
00198
00205 claw::graphic::targa::reader::reader( image& img, std::istream& f )
00206 : m_image( img )
00207 {
00208 load(f);
00209 }
00210
00211
00216 void claw::graphic::targa::reader::load( std::istream& f )
00217 {
00218 CLAW_PRECOND( !!f );
00219 std::istream::pos_type init_pos = f.tellg();
00220
00221 try
00222 {
00223 check_if_targa(f);
00224
00225 header h;
00226
00227 f.read( reinterpret_cast<char*>(&h), sizeof(header) );
00228
00229 if ( f.rdstate() == std::ios_base::goodbit )
00230 {
00231 m_image.set_size( h.image_specification.width,
00232 h.image_specification.height );
00233
00234 switch(h.image_type)
00235 {
00236 case color_mapped: load_color_mapped(h, f); break;
00237 case rle_color_mapped: load_rle_color_mapped(h, f); break;
00238 case true_color: load_true_color(h, f); break;
00239 case rle_true_color: load_rle_true_color(h, f); break;
00240 default :
00241 throw claw::bad_format
00242 ( "targa::reader::targa: unsupported image type" );
00243 }
00244 }
00245 else
00246 throw claw::bad_format
00247 ( "claw::targa::reader::targa: can't read header" );
00248 }
00249 catch(...)
00250 {
00251 f.clear();
00252 f.seekg( init_pos, std::ios_base::beg );
00253 throw;
00254 }
00255 }
00256
00257
00262 void claw::graphic::targa::reader::check_if_targa( std::istream& f ) const
00263 {
00264 CLAW_PRECOND( !!f );
00265
00266 std::istream::pos_type init_pos = f.tellg();
00267
00268 footer foot;
00269
00270 f.seekg( -(std::istream::off_type)sizeof(footer), std::ios::end );
00271 f.read( reinterpret_cast<char*>(&foot), sizeof(footer) );
00272 f.seekg( init_pos , std::ios::beg );
00273
00274 if ( !foot.is_valid() )
00275 throw CLAW_EXCEPTION( "Not a Targa file." );
00276 }
00277
00278
00286 void claw::graphic::targa::reader::load_palette
00287 ( const header& h, std::istream& f, color_palette32& palette ) const
00288 {
00289 assert((h.image_type == color_mapped) || (h.image_type == rle_color_mapped));
00290
00291 switch( h.color_map_specification.entry_size )
00292 {
00293 case 16: load_palette_content<pixel16>(f, palette); break;
00294 case 24: load_palette_content<pixel24>(f, palette); break;
00295 case 32: load_palette_content<pixel32>(f, palette); break;
00296 default:
00297 throw claw::bad_format
00298 ( "targa::reader::load_palette: unsupported entry size" );
00299 }
00300 }
00301
00302
00309 void claw::graphic::targa::reader::load_color_mapped
00310 ( const header& h, std::istream& f )
00311 {
00312 assert(h.image_type == color_mapped);
00313
00314 f.seekg( h.id_length, std::ios_base::cur );
00315
00316 color_palette32 palette( h.color_map_specification.length );
00317 load_palette( h, f, palette );
00318
00319 switch(h.image_specification.bpp)
00320 {
00321 case 8: load_color_mapped_raw<pixel8>(h, f, palette); break;
00322 default:
00323 throw claw::bad_format
00324 ( "targa::reader::load_color_mapped: unsupported color depth" );
00325 }
00326 }
00327
00328
00335 void claw::graphic::targa::reader::load_rle_color_mapped
00336 ( const header& h, std::istream& f )
00337 {
00338 assert(h.image_type == rle_color_mapped);
00339
00340 f.seekg( h.id_length, std::ios_base::cur );
00341
00342 color_palette32 palette( h.color_map_specification.length );
00343 load_palette( h, f, palette );
00344
00345 switch(h.image_specification.bpp)
00346 {
00347 case 8: decompress_rle_color_mapped<rle8_decoder>(h, f, palette); break;
00348 default:
00349 throw claw::bad_format
00350 ( "targa::reader::load_rle_color_mapped: unsupported color depth" );
00351 }
00352 }
00353
00354
00361 void claw::graphic::targa::reader::load_true_color
00362 ( const header& h, std::istream& f )
00363 {
00364 assert(h.image_type == true_color);
00365
00366 f.seekg( h.id_length, std::ios_base::cur );
00367
00368 switch(h.image_specification.bpp)
00369 {
00370 case 16 : load_true_color_raw<pixel16>(h, f); break;
00371 case 24 : load_true_color_raw<pixel24>(h, f); break;
00372 case 32 : load_true_color_raw<pixel32>(h, f); break;
00373 default :
00374 throw claw::bad_format
00375 ( "targa::reader::load_true_color: unsupported color depth" );
00376 }
00377 }
00378
00379
00386 void claw::graphic::targa::reader::load_rle_true_color
00387 ( const header& h, std::istream& f )
00388 {
00389 assert(h.image_type == rle_true_color);
00390
00391 f.seekg( h.id_length, std::ios_base::cur );
00392
00393 switch(h.image_specification.bpp)
00394 {
00395 case 16 : decompress_rle_true_color<rle16_decoder>(h, f); break;
00396 case 24 : decompress_rle_true_color<rle24_decoder>(h, f); break;
00397 case 32 : decompress_rle_true_color<rle32_decoder>(h, f); break;
00398 default :
00399 throw claw::bad_format
00400 ( "targa::reader::load_rle_true_color: unsupported color depth" );
00401 }
00402 }
00403