bitmap_reader.cpp

Go to the documentation of this file.
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-2008 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@yahoo.fr
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()

Generated on 9 Nov 2009 for CLAW Library (a C++ Library Absolutely Wonderful) by  doxygen 1.6.1