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