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/bitmap.hpp>
00031 #include <algorithm>
00032
00033 namespace claw
00034 {
00035 namespace graphic
00036 {
00037
00044 template<>
00045 void bitmap::reader::rle_bitmap_output_buffer<false>::fill
00046 ( unsigned int n, unsigned char pattern )
00047 {
00048 assert( m_x + n <= m_image.width() );
00049
00050 std::fill(&m_image[m_y][m_x], &m_image[m_y][m_x] + n, m_palette[pattern]);
00051
00052 m_x += n;
00053 }
00054 }
00055 }
00056
00057 namespace claw
00058 {
00059 namespace graphic
00060 {
00061
00068 template<>
00069 void bitmap::reader::rle_bitmap_output_buffer<true>::fill
00070 ( unsigned int n, unsigned char pattern )
00071 {
00072 assert( m_x + n <= m_image.width() );
00073
00074 for (unsigned int i = 0; i != n / 2; ++i, m_x += 2)
00075 {
00076 m_image[m_y][m_x] = m_palette[ (pattern & 0xF0) >> 4 ];
00077 m_image[m_y][m_x+1] = m_palette[ pattern & 0x0F ];
00078 }
00079
00080 if ( n % 2 )
00081 {
00082 m_image[m_y][m_x] = m_palette[ (pattern & 0xF0) >> 4 ];
00083 ++m_x;
00084 }
00085 }
00086 }
00087 }
00088
00089 namespace claw
00090 {
00091 namespace graphic
00092 {
00093
00100 template<>
00101 void bitmap::reader::rle_bitmap_output_buffer<false>::copy
00102 ( unsigned int n, file_input_buffer& buffer )
00103 {
00104 assert( m_x + n <= m_image.width() );
00105
00106
00107 const unsigned int bytes_needed = n + n % 2;
00108
00109 if ( buffer.remaining() < bytes_needed )
00110 buffer.read_more(bytes_needed);
00111
00112 assert( buffer.remaining() >= bytes_needed );
00113
00114 const unsigned char* p =
00115 reinterpret_cast<const unsigned char*>(buffer.get_buffer());
00116
00117 std::transform( p, p + n, &m_image[m_y][m_x], m_palette );
00118
00119 m_x += n;
00120
00121 buffer.move(bytes_needed);
00122 }
00123 }
00124 }
00125
00126 namespace claw
00127 {
00128 namespace graphic
00129 {
00130
00137 template<>
00138 void bitmap::reader::rle_bitmap_output_buffer<true>::copy
00139 ( unsigned int n, file_input_buffer& buffer )
00140 {
00141 assert( m_x + n <= m_image.width() );
00142
00143
00144 unsigned int bytes_needed = n / 2 + n % 2;
00145
00146 if ( bytes_needed % 2 )
00147 ++bytes_needed;
00148
00149 if ( buffer.remaining() < bytes_needed )
00150 buffer.read_more( bytes_needed );
00151
00152 assert( buffer.remaining() >= bytes_needed );
00153
00154 const unsigned char* p =
00155 reinterpret_cast<const unsigned char*>(buffer.get_buffer());
00156 const unsigned char* last = p + n / 2;
00157
00158 for ( ; p != last; ++p, m_x += 2)
00159 {
00160 m_image[m_y][m_x] = m_palette[ (*p & 0xF0) >> 4 ];
00161 m_image[m_y][m_x+1] = m_palette[ *p & 0x0F ];
00162 }
00163
00164 if ( n % 2 )
00165 {
00166 m_image[m_y][m_x] = m_palette[ (*p & 0xF0) >> 4 ];
00167 ++m_x;
00168 }
00169
00170 buffer.move( bytes_needed );
00171 }
00172 }
00173 }
00174
00175
00176
00177
00185 void claw::graphic::bitmap::reader::pixel1_to_pixel32::operator()
00186 ( scanline& dest, const char* src, const color_palette_type& palette ) const
00187 {
00188 assert(palette.size() == 2);
00189
00190 scanline::iterator it( dest.begin() );
00191 const unsigned int n = dest.size();
00192 const unsigned int byte_size = 8;
00193 const unsigned int upper_bound = n / byte_size;
00194
00195 for (unsigned int i=0; i!=upper_bound; ++i)
00196 for (unsigned int j=0; j!=byte_size; ++j, ++it)
00197 if ( src[i] & (0x80 >> j) )
00198 *it = palette[1];
00199 else
00200 *it = palette[0];
00201
00202 for (unsigned int j = 0; j != (n % byte_size); ++j, ++it)
00203 if ( src[upper_bound] & (0x80 >> j) )
00204 *it = palette[1];
00205 else
00206 *it = palette[0];
00207 }
00208
00209
00217 void claw::graphic::bitmap::reader::pixel4_to_pixel32::operator()
00218 ( scanline& dest, const char* src, const color_palette_type& palette ) const
00219 {
00220 assert(palette.size() == 16);
00221
00222 scanline::iterator it( dest.begin() );
00223 const unsigned int upper_bound = dest.size() / 2;
00224
00225 for (unsigned int i=0; i!=upper_bound; ++i, ++src)
00226 {
00227 *it = palette[ (*src & 0xF0) >> 4 ];
00228 ++it;
00229 *it = palette[ *src & 0x0F ];
00230 ++it;
00231 }
00232
00233 if (dest.size() % 2)
00234 *it = palette[ (*src & 0xF0) >> 4 ];
00235 }
00236
00237
00245 void claw::graphic::bitmap::reader::pixel8_to_pixel32::operator()
00246 ( scanline& dest, const char* src, const color_palette_type& palette ) const
00247 {
00248 assert(palette.size() == 256);
00249
00250 const unsigned char* s = reinterpret_cast<const unsigned char*>(src);
00251
00252 std::transform(s, s + dest.size(), dest.begin(), palette);
00253 }
00254
00255
00262 void claw::graphic::bitmap::reader::pixel24_to_pixel32::operator()
00263 ( scanline& dest, const char* src, const color_palette_type& palette ) const
00264 {
00265 scanline::iterator it( dest.begin() );
00266 const unsigned int upper_bound = 3 * dest.size();
00267
00268 for (unsigned int i=0; i!=upper_bound; i+=3)
00269 {
00270 it->components.alpha = 255;
00271 it->components.blue = src[i];
00272 it->components.green = src[i+1];
00273 it->components.red = src[i+2];
00274
00275 ++it;
00276 }
00277 }
00278
00279
00280
00281
00282
00287 claw::graphic::bitmap::reader::reader( image& img )
00288 : m_image( img )
00289 {
00290
00291 }
00292
00293
00300 claw::graphic::bitmap::reader::reader( image& img, std::istream& f )
00301 : m_image( img )
00302 {
00303 load(f);
00304 }
00305
00306
00312 void claw::graphic::bitmap::reader::load( std::istream& f )
00313 {
00314 CLAW_PRECOND( !!f );
00315 std::istream::pos_type init_pos = f.tellg();
00316
00317 try
00318 {
00319 header h;
00320
00321 f.read( reinterpret_cast<char*>(&h), sizeof(header) );
00322
00323 if ( (h.id[0] == 'B') && (h.id[1] == 'M')
00324 && (f.rdstate() == std::ios_base::goodbit) )
00325 {
00326 m_image.set_size(h.width, h.height);
00327
00328 switch(h.bpp)
00329 {
00330 case 1 : load_1bpp(h, f); break;
00331 case 4 : load_4bpp(h, f); break;
00332 case 8 : load_8bpp(h, f); break;
00333
00334 case 24 : load_24bpp(h, f); break;
00335 default :
00336 throw claw::bad_format
00337 ("bitmap::bitmap: unsupported color depth.");
00338 }
00339 }
00340 else
00341 throw claw::bad_format( "bitmap::bitmap: invalid header." );
00342 }
00343 catch(...)
00344 {
00345 f.clear();
00346 f.seekg( init_pos, std::ios_base::beg );
00347 throw;
00348 }
00349 }
00350
00351
00359 void claw::graphic::bitmap::reader::load_palette
00360 ( const header& h, std::istream& f, color_palette_type& palette ) const
00361 {
00362 assert(h.bpp <= 8);
00363
00364 switch(h.bpp)
00365 {
00366 case 1 : assert( palette.size() == 2 ); break;
00367 case 4 : assert( palette.size() == 16 ); break;
00368 case 8 : assert( palette.size() == 256 ); break;
00369 }
00370
00371 const unsigned int sizeof_color = sizeof(color_palette_type::color_type);
00372 const unsigned int buffer_size = sizeof_color * palette.size();
00373 char* buffer = new char[buffer_size];
00374
00375 f.read(buffer, buffer_size);
00376
00377 for (unsigned int i=0, j=0; i!=buffer_size; i+=sizeof_color, ++j)
00378 {
00379 palette[j].components.alpha = 255;
00380 palette[j].components.blue = buffer[i];
00381 palette[j].components.green = buffer[i+1];
00382 palette[j].components.red = buffer[i+2];
00383 }
00384
00385 delete[] buffer;
00386 }
00387
00388
00395 void
00396 claw::graphic::bitmap::reader::load_1bpp( const header& h, std::istream& f )
00397 {
00398 assert(h.bpp == 1);
00399
00400
00401 color_palette_type palette(2);
00402 unsigned int buffer_size = m_image.width() / (sizeof(char) * 8);
00403
00404 if ( m_image.width() % (sizeof(char) * 8) )
00405 ++buffer_size;
00406
00407 load_palette(h, f, palette);
00408 f.seekg(h.data_offset);
00409
00410 load_rgb_data(f, buffer_size, palette, pixel1_to_pixel32());
00411 }
00412
00413
00420 void
00421 claw::graphic::bitmap::reader::load_4bpp( const header& h, std::istream& f )
00422 {
00423 assert(h.bpp == 4);
00424 assert( (h.compression == BMP_COMPRESSION_RGB)
00425 || (h.compression == BMP_COMPRESSION_RLE4) );
00426
00427 color_palette_type palette(16);
00428 load_palette(h, f, palette);
00429
00430 if (h.compression == BMP_COMPRESSION_RLE4)
00431 load_4bpp_rle(h, f, palette);
00432 else
00433 load_4bpp_rgb(h, f, palette);
00434 }
00435
00436
00443 void
00444 claw::graphic::bitmap::reader::load_8bpp( const header& h, std::istream& f )
00445 {
00446 assert(h.bpp == 8);
00447 assert( (h.compression == BMP_COMPRESSION_RGB)
00448 || (h.compression == BMP_COMPRESSION_RLE8) );
00449
00450 color_palette_type palette(256);
00451 load_palette(h, f, palette);
00452
00453 if (h.compression == BMP_COMPRESSION_RLE8)
00454 load_8bpp_rle(h, f, palette);
00455 else
00456 load_8bpp_rgb(h, f, palette);
00457 }
00458
00459
00466 void
00467 claw::graphic::bitmap::reader::load_24bpp( const header& h, std::istream& f )
00468 {
00469 assert(h.bpp == 24);
00470
00471 unsigned int buffer_size = m_image.width() * 3;
00472 color_palette_type palette(0);
00473
00474 f.seekg(h.data_offset);
00475
00476 load_rgb_data(f, buffer_size, palette, pixel24_to_pixel32());
00477 }
00478
00479
00488 void claw::graphic::bitmap::reader::load_4bpp_rle
00489 ( const header& h, std::istream& f, const color_palette_type& palette )
00490 {
00491 assert(h.bpp == 4);
00492 assert(h.compression == BMP_COMPRESSION_RLE4);
00493 assert(palette.size() == 16);
00494
00495 f.seekg(h.data_offset);
00496
00497 rle4_decoder decoder;
00498 rle4_decoder::output_buffer_type output_buffer( palette, m_image );
00499 file_input_buffer input_buffer(f);
00500
00501 decoder.decode( input_buffer, output_buffer );
00502 }
00503
00504
00513 void claw::graphic::bitmap::reader::load_4bpp_rgb
00514 ( const header& h, std::istream& f, const color_palette_type& palette )
00515 {
00516 assert(h.bpp == 4);
00517 assert(h.compression == BMP_COMPRESSION_RGB);
00518 assert(palette.size() == 16);
00519
00520 unsigned int buffer_size = m_image.width() / 2 + m_image.width() % 2;
00521
00522 f.seekg(h.data_offset);
00523
00524 load_rgb_data(f, buffer_size, palette, pixel4_to_pixel32());
00525 }
00526
00527
00536 void claw::graphic::bitmap::reader::load_8bpp_rle
00537 ( const header& h, std::istream& f, const color_palette_type& palette )
00538 {
00539 assert(h.bpp == 8);
00540 assert(h.compression == BMP_COMPRESSION_RLE8);
00541 assert(palette.size() == 256);
00542
00543 f.seekg(h.data_offset);
00544
00545 rle8_decoder decoder;
00546 rle8_decoder::output_buffer_type output_buffer( palette, m_image );
00547 file_input_buffer input_buffer(f);
00548
00549 decoder.decode( input_buffer, output_buffer );
00550 }
00551
00552
00561 void claw::graphic::bitmap::reader::load_8bpp_rgb
00562 ( const header& h, std::istream& f, const color_palette_type& palette )
00563 {
00564 assert(h.bpp == 8);
00565 assert(h.compression == BMP_COMPRESSION_RGB);
00566 assert(palette.size() == 256);
00567
00568 unsigned int buffer_size = m_image.width();
00569
00570 f.seekg(h.data_offset);
00571
00572 load_rgb_data(f, buffer_size, palette, pixel8_to_pixel32());
00573 }