Claw
1.7.0
|
00001 /* 00002 CLAW - a C++ Library Absolutely Wonderful 00003 00004 CLAW is a free library without any particular aim but being useful to 00005 anyone. 00006 00007 Copyright (C) 2005-2011 Julien Jorge 00008 00009 This library is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU Lesser General Public 00011 License as published by the Free Software Foundation; either 00012 version 2.1 of the License, or (at your option) any later version. 00013 00014 This library is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public 00020 License along with this library; if not, write to the Free Software 00021 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00022 00023 contact: julien.jorge@gamned.org 00024 */ 00030 #include <claw/targa.hpp> 00031 #include <claw/exception.hpp> 00032 00033 00034 00035 //********************* targa::reader::file_input_buffer *********************** 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 } // targa::reader::file_input_buffer::get_pixel() 00067 } // namespace graphic 00068 } // namespace claw 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 } // targa::reader::file_input_buffer::get_pixel() 00099 } // namespace graphic 00100 } // namespace claw 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 } // targa::reader::file_input_buffer::get_pixel() 00139 } // namespace graphic 00140 } // namespace claw 00141 00142 00143 00144 00145 00146 00147 00148 //****************** targa::reader::mapped_file_input_buffer ******************* 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 } // targa::reader::mapped_file_input_buffer::get_pixel() 00176 } // namespace graphic 00177 } // namespace claw 00178 00179 00180 00181 00182 00183 //****************************** targa::reader ********************************* 00184 00185 00186 00187 00188 /*----------------------------------------------------------------------------*/ 00193 claw::graphic::targa::reader::reader( image& img ) 00194 : m_image( img ) 00195 { 00196 00197 } // targa::reader::reader() 00198 00199 /*----------------------------------------------------------------------------*/ 00206 claw::graphic::targa::reader::reader( image& img, std::istream& f ) 00207 : m_image( img ) 00208 { 00209 load(f); 00210 } // targa::reader::reader() 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 } // targa::reader::load() 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 } // targa::reader::check_if_targa() 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 } // targa::reader::load_palette() 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 } // targa::reader::load_color_mapped() 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 } // targa::reader::load_color_mapped() 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 } // targa::reader::load_true_color() 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 } // targa::reader::load_rle_true_color() 00404