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 rgba_pixel_8 targa::reader::file_input_buffer<rgba_pixel_8>::get_pixel()
00052 {
00053 rgba_pixel_8 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 rgba_pixel_8 targa::reader::file_input_buffer<rgb_pixel_8>::get_pixel()
00083 {
00084 rgba_pixel_8 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::rgba_pixel_8::component_type>::max();
00096
00097 return result;
00098 }
00099 }
00100 }
00101
00102 namespace claw
00103 {
00104 namespace graphic
00105 {
00106
00113 template< >
00114 rgba_pixel_8 targa::reader::file_input_buffer<targa::pixel16>::get_pixel()
00115 {
00116 rgba_pixel_8 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::rgba_pixel_8::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 rgba_pixel_8
00165 targa::reader::mapped_file_input_buffer<targa::pixel8>::get_pixel()
00166 {
00167 if ( this->remaining() < 1 )
00168 this->read_more(1);
00169
00170 assert( this->remaining() >= 1 );
00171
00172 unsigned char index = this->get_next();
00173
00174 return m_palette[index];
00175 }
00176 }
00177 }
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00193 claw::graphic::targa::reader::reader( image& img )
00194 : m_image( img )
00195 {
00196
00197 }
00198
00199
00206 claw::graphic::targa::reader::reader( image& img, std::istream& f )
00207 : m_image( img )
00208 {
00209 load(f);
00210 }
00211
00212
00217 void claw::graphic::targa::reader::load( std::istream& f )
00218 {
00219 CLAW_PRECOND( !!f );
00220 std::istream::pos_type init_pos = f.tellg();
00221
00222 try
00223 {
00224 check_if_targa(f);
00225
00226 header h;
00227
00228 f.read( reinterpret_cast<char*>(&h), sizeof(header) );
00229
00230 if ( f.rdstate() == std::ios_base::goodbit )
00231 {
00232 m_image.set_size( h.image_specification.width,
00233 h.image_specification.height );
00234
00235 switch(h.image_type)
00236 {
00237 case color_mapped: load_color_mapped(h, f); break;
00238 case rle_color_mapped: load_rle_color_mapped(h, f); break;
00239 case true_color: load_true_color(h, f); break;
00240 case rle_true_color: load_rle_true_color(h, f); break;
00241 default :
00242 throw claw::bad_format
00243 ( "targa::reader::targa: unsupported image type" );
00244 }
00245 }
00246 else
00247 throw claw::bad_format
00248 ( "claw::targa::reader::targa: can't read header" );
00249 }
00250 catch(...)
00251 {
00252 f.clear();
00253 f.seekg( init_pos, std::ios_base::beg );
00254 throw;
00255 }
00256 }
00257
00258
00263 void claw::graphic::targa::reader::check_if_targa( std::istream& f ) const
00264 {
00265 CLAW_PRECOND( !!f );
00266
00267 std::istream::pos_type init_pos = f.tellg();
00268
00269 footer foot;
00270
00271 f.seekg( -(std::istream::off_type)sizeof(footer), std::ios::end );
00272 f.read( reinterpret_cast<char*>(&foot), sizeof(footer) );
00273 f.seekg( init_pos , std::ios::beg );
00274
00275 if ( !foot.is_valid() )
00276 throw CLAW_EXCEPTION( "Not a Targa file." );
00277 }
00278
00279
00287 void claw::graphic::targa::reader::load_palette
00288 ( const header& h, std::istream& f, color_palette32& palette ) const
00289 {
00290 assert((h.image_type == color_mapped) || (h.image_type == rle_color_mapped));
00291
00292 switch( h.color_map_specification.entry_size )
00293 {
00294 case 16: load_palette_content<pixel16>(f, palette); break;
00295 case 24: load_palette_content<rgb_pixel_8>(f, palette); break;
00296 case 32: load_palette_content<rgba_pixel_8>(f, palette); break;
00297 default:
00298 throw claw::bad_format
00299 ( "targa::reader::load_palette: unsupported entry size" );
00300 }
00301 }
00302
00303
00310 void claw::graphic::targa::reader::load_color_mapped
00311 ( const header& h, std::istream& f )
00312 {
00313 assert(h.image_type == color_mapped);
00314
00315 f.seekg( h.id_length, std::ios_base::cur );
00316
00317 color_palette32 palette( h.color_map_specification.length );
00318 load_palette( h, f, palette );
00319
00320 switch(h.image_specification.bpp)
00321 {
00322 case 8: load_color_mapped_raw<pixel8>(h, f, palette); break;
00323 default:
00324 throw claw::bad_format
00325 ( "targa::reader::load_color_mapped: unsupported color depth" );
00326 }
00327 }
00328
00329
00336 void claw::graphic::targa::reader::load_rle_color_mapped
00337 ( const header& h, std::istream& f )
00338 {
00339 assert(h.image_type == rle_color_mapped);
00340
00341 f.seekg( h.id_length, std::ios_base::cur );
00342
00343 color_palette32 palette( h.color_map_specification.length );
00344 load_palette( h, f, palette );
00345
00346 switch(h.image_specification.bpp)
00347 {
00348 case 8: decompress_rle_color_mapped<rle8_decoder>(h, f, palette); break;
00349 default:
00350 throw claw::bad_format
00351 ( "targa::reader::load_rle_color_mapped: unsupported color depth" );
00352 }
00353 }
00354
00355
00362 void claw::graphic::targa::reader::load_true_color
00363 ( const header& h, std::istream& f )
00364 {
00365 assert(h.image_type == true_color);
00366
00367 f.seekg( h.id_length, std::ios_base::cur );
00368
00369 switch(h.image_specification.bpp)
00370 {
00371 case 16 : load_true_color_raw<pixel16>(h, f); break;
00372 case 24 : load_true_color_raw<rgb_pixel_8>(h, f); break;
00373 case 32 : load_true_color_raw<rgba_pixel_8>(h, f); break;
00374 default :
00375 throw claw::bad_format
00376 ( "targa::reader::load_true_color: unsupported color depth" );
00377 }
00378 }
00379
00380
00387 void claw::graphic::targa::reader::load_rle_true_color
00388 ( const header& h, std::istream& f )
00389 {
00390 assert(h.image_type == rle_true_color);
00391
00392 f.seekg( h.id_length, std::ios_base::cur );
00393
00394 switch(h.image_specification.bpp)
00395 {
00396 case 16 : decompress_rle_true_color<rle16_decoder>(h, f); break;
00397 case 24 : decompress_rle_true_color<rle24_decoder>(h, f); break;
00398 case 32 : decompress_rle_true_color<rle32_decoder>(h, f); break;
00399 default :
00400 throw claw::bad_format
00401 ( "targa::reader::load_rle_true_color: unsupported color depth" );
00402 }
00403 }
00404