Claw
1.7.3
|
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/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 } // bitmap::reader::rle_bitmap_output_buffer<false>::fill() 00054 } // namespace graphic 00055 } // namespace claw 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 } // bitmap::reader::rle_bitmap_output_buffer<false>::fill() 00086 } // namespace graphic 00087 } // namespace claw 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 // RLE bitmap data is 2-bytes aligned 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 } // bitmap::reader::rle_bitmap_output_buffer<false>::copy() 00123 } // namespace graphic 00124 } // namespace claw 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 // RLE bitmap data is 2-bytes aligned 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 } // bitmap::reader::rle_bitmap_output_buffer<true>::copy() 00172 } // namespace graphic 00173 } // namespace claw 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; // 8 bits per byte 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 } // bitmap::reader::pixel1_to_pixel32() 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 } // bitmap::reader::pixel4_to_pixel32() 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 } // bitmap::reader::pixel8_to_pixel32() 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 } // bitmap::reader::pixel24_to_pixel32() 00278 00279 00280 00281 00282 /*----------------------------------------------------------------------------*/ 00287 claw::graphic::bitmap::reader::reader( image& img ) 00288 : m_image( img ) 00289 { 00290 00291 } // bitmap::reader::reader() 00292 00293 /*----------------------------------------------------------------------------*/ 00300 claw::graphic::bitmap::reader::reader( image& img, std::istream& f ) 00301 : m_image( img ) 00302 { 00303 load(f); 00304 } // bitmap::reader::reader() 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 //case 16 : load_16bpp(h, f); break; 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 } // bitmap::reader::load() 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 } // bitmap::reader::load_palette() 00387 00388 /*----------------------------------------------------------------------------*/ 00395 void 00396 claw::graphic::bitmap::reader::load_1bpp( const header& h, std::istream& f ) 00397 { 00398 assert(h.bpp == 1); 00399 //assert(h.compression == BMP_COMPRESSION_BITFIELDS); 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 } // bitmap::reader::load_1bpp() 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 } // bitmap::reader::load_4bpp() 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 } // bitmap::reader::load_8bpp() 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 } // bitmap::reader::load_24bpp() 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 } // bitmap::reader::load_4bpp_rle() 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 } // bitmap::reader::load_4bpp_rgb() 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 } // bitmap::reader::load_8bpp_rle() 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 } // bitmap::reader::load_8bpp_rgb()