Claw  1.7.3
bitmap_reader.cpp
Go to the documentation of this file.
1 /*
2  CLAW - a C++ Library Absolutely Wonderful
3 
4  CLAW is a free library without any particular aim but being useful to
5  anyone.
6 
7  Copyright (C) 2005-2011 Julien Jorge
8 
9  This library is free software; you can redistribute it and/or
10  modify it under the terms of the GNU Lesser General Public
11  License as published by the Free Software Foundation; either
12  version 2.1 of the License, or (at your option) any later version.
13 
14  This library is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public
20  License along with this library; if not, write to the Free Software
21  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 
23  contact: julien.jorge@gamned.org
24 */
30 #include <claw/bitmap.hpp>
31 #include <algorithm>
32 
33 namespace claw
34 {
35  namespace graphic
36  {
37  /*------------------------------------------------------------------------*/
44  template<>
46  ( unsigned int n, unsigned char pattern )
47  {
48  assert( m_x + n <= m_image.width() );
49 
50  std::fill(&m_image[m_y][m_x], &m_image[m_y][m_x] + n, m_palette[pattern]);
51 
52  m_x += n;
53  } // bitmap::reader::rle_bitmap_output_buffer<false>::fill()
54  } // namespace graphic
55 } // namespace claw
56 
57 namespace claw
58 {
59  namespace graphic
60  {
61  /*------------------------------------------------------------------------*/
68  template<>
70  ( unsigned int n, unsigned char pattern )
71  {
72  assert( m_x + n <= m_image.width() );
73 
74  for (unsigned int i = 0; i != n / 2; ++i, m_x += 2)
75  {
76  m_image[m_y][m_x] = m_palette[ (pattern & 0xF0) >> 4 ];
77  m_image[m_y][m_x+1] = m_palette[ pattern & 0x0F ];
78  }
79 
80  if ( n % 2 )
81  {
82  m_image[m_y][m_x] = m_palette[ (pattern & 0xF0) >> 4 ];
83  ++m_x;
84  }
85  } // bitmap::reader::rle_bitmap_output_buffer<false>::fill()
86  } // namespace graphic
87 } // namespace claw
88 
89 namespace claw
90 {
91  namespace graphic
92  {
93  /*------------------------------------------------------------------------*/
100  template<>
101  void bitmap::reader::rle_bitmap_output_buffer<false>::copy
102  ( unsigned int n, file_input_buffer& buffer )
103  {
104  assert( m_x + n <= m_image.width() );
105 
106  // RLE bitmap data is 2-bytes aligned
107  const unsigned int bytes_needed = n + n % 2;
108 
109  if ( buffer.remaining() < bytes_needed )
110  buffer.read_more(bytes_needed);
111 
112  assert( buffer.remaining() >= bytes_needed );
113 
114  const unsigned char* p =
115  reinterpret_cast<const unsigned char*>(buffer.get_buffer());
116 
117  std::transform( p, p + n, &m_image[m_y][m_x], m_palette );
118 
119  m_x += n;
120 
121  buffer.move(bytes_needed);
122  } // bitmap::reader::rle_bitmap_output_buffer<false>::copy()
123  } // namespace graphic
124 } // namespace claw
125 
126 namespace claw
127 {
128  namespace graphic
129  {
130  /*------------------------------------------------------------------------*/
137  template<>
138  void bitmap::reader::rle_bitmap_output_buffer<true>::copy
139  ( unsigned int n, file_input_buffer& buffer )
140  {
141  assert( m_x + n <= m_image.width() );
142 
143  // RLE bitmap data is 2-bytes aligned
144  unsigned int bytes_needed = n / 2 + n % 2;
145 
146  if ( bytes_needed % 2 )
147  ++bytes_needed;
148 
149  if ( buffer.remaining() < bytes_needed )
150  buffer.read_more( bytes_needed );
151 
152  assert( buffer.remaining() >= bytes_needed );
153 
154  const unsigned char* p =
155  reinterpret_cast<const unsigned char*>(buffer.get_buffer());
156  const unsigned char* last = p + n / 2;
157 
158  for ( ; p != last; ++p, m_x += 2)
159  {
160  m_image[m_y][m_x] = m_palette[ (*p & 0xF0) >> 4 ];
161  m_image[m_y][m_x+1] = m_palette[ *p & 0x0F ];
162  }
163 
164  if ( n % 2 )
165  {
166  m_image[m_y][m_x] = m_palette[ (*p & 0xF0) >> 4 ];
167  ++m_x;
168  }
169 
170  buffer.move( bytes_needed );
171  } // bitmap::reader::rle_bitmap_output_buffer<true>::copy()
172  } // namespace graphic
173 } // namespace claw
174 
175 
176 
177 /*----------------------------------------------------------------------------*/
185 void claw::graphic::bitmap::reader::pixel1_to_pixel32::operator()
186  ( scanline& dest, const char* src, const color_palette_type& palette ) const
187 {
188  assert(palette.size() == 2);
189 
190  scanline::iterator it( dest.begin() );
191  const unsigned int n = dest.size();
192  const unsigned int byte_size = 8; // 8 bits per byte
193  const unsigned int upper_bound = n / byte_size;
194 
195  for (unsigned int i=0; i!=upper_bound; ++i)
196  for (unsigned int j=0; j!=byte_size; ++j, ++it)
197  if ( src[i] & (0x80 >> j) )
198  *it = palette[1];
199  else
200  *it = palette[0];
201 
202  for (unsigned int j = 0; j != (n % byte_size); ++j, ++it)
203  if ( src[upper_bound] & (0x80 >> j) )
204  *it = palette[1];
205  else
206  *it = palette[0];
207 } // bitmap::reader::pixel1_to_pixel32()
208 
209 /*----------------------------------------------------------------------------*/
217 void claw::graphic::bitmap::reader::pixel4_to_pixel32::operator()
218  ( scanline& dest, const char* src, const color_palette_type& palette ) const
219 {
220  assert(palette.size() == 16);
221 
222  scanline::iterator it( dest.begin() );
223  const unsigned int upper_bound = dest.size() / 2;
224 
225  for (unsigned int i=0; i!=upper_bound; ++i, ++src)
226  {
227  *it = palette[ (*src & 0xF0) >> 4 ];
228  ++it;
229  *it = palette[ *src & 0x0F ];
230  ++it;
231  }
232 
233  if (dest.size() % 2)
234  *it = palette[ (*src & 0xF0) >> 4 ];
235 } // bitmap::reader::pixel4_to_pixel32()
236 
237 /*----------------------------------------------------------------------------*/
245 void claw::graphic::bitmap::reader::pixel8_to_pixel32::operator()
246  ( scanline& dest, const char* src, const color_palette_type& palette ) const
247 {
248  assert(palette.size() == 256);
249 
250  const unsigned char* s = reinterpret_cast<const unsigned char*>(src);
251 
252  std::transform(s, s + dest.size(), dest.begin(), palette);
253 } // bitmap::reader::pixel8_to_pixel32()
254 
255 /*----------------------------------------------------------------------------*/
262 void claw::graphic::bitmap::reader::pixel24_to_pixel32::operator()
263  ( scanline& dest, const char* src, const color_palette_type& palette ) const
264 {
265  scanline::iterator it( dest.begin() );
266  const unsigned int upper_bound = 3 * dest.size();
267 
268  for (unsigned int i=0; i!=upper_bound; i+=3)
269  {
270  it->components.alpha = 255;
271  it->components.blue = src[i];
272  it->components.green = src[i+1];
273  it->components.red = src[i+2];
274 
275  ++it;
276  }
277 } // bitmap::reader::pixel24_to_pixel32()
278 
279 
280 
281 
282 /*----------------------------------------------------------------------------*/
288  : m_image( img )
289 {
290 
291 } // bitmap::reader::reader()
292 
293 /*----------------------------------------------------------------------------*/
301  : m_image( img )
302 {
303  load(f);
304 } // bitmap::reader::reader()
305 
306 /*----------------------------------------------------------------------------*/
312 void claw::graphic::bitmap::reader::load( std::istream& f )
313 {
314  CLAW_PRECOND( !!f );
315  std::istream::pos_type init_pos = f.tellg();
316 
317  try
318  {
319  header h;
320 
321  f.read( reinterpret_cast<char*>(&h), sizeof(header) );
322 
323  if ( (h.id[0] == 'B') && (h.id[1] == 'M')
324  && (f.rdstate() == std::ios_base::goodbit) )
325  {
326  m_image.set_size(h.width, h.height);
327 
328  switch(h.bpp)
329  {
330  case 1 : load_1bpp(h, f); break;
331  case 4 : load_4bpp(h, f); break;
332  case 8 : load_8bpp(h, f); break;
333  //case 16 : load_16bpp(h, f); break;
334  case 24 : load_24bpp(h, f); break;
335  default :
336  throw claw::bad_format
337  ("bitmap::bitmap: unsupported color depth.");
338  }
339  }
340  else
341  throw claw::bad_format( "bitmap::bitmap: invalid header." );
342  }
343  catch(...)
344  {
345  f.clear();
346  f.seekg( init_pos, std::ios_base::beg );
347  throw;
348  }
349 } // bitmap::reader::load()
350 
351 /*----------------------------------------------------------------------------*/
359 void claw::graphic::bitmap::reader::load_palette
360 ( const header& h, std::istream& f, color_palette_type& palette ) const
361 {
362  assert(h.bpp <= 8);
363 
364  switch(h.bpp)
365  {
366  case 1 : assert( palette.size() == 2 ); break;
367  case 4 : assert( palette.size() == 16 ); break;
368  case 8 : assert( palette.size() == 256 ); break;
369  }
370 
371  const unsigned int sizeof_color = sizeof(color_palette_type::color_type);
372  const unsigned int buffer_size = sizeof_color * palette.size();
373  char* buffer = new char[buffer_size];
374 
375  f.read(buffer, buffer_size);
376 
377  for (unsigned int i=0, j=0; i!=buffer_size; i+=sizeof_color, ++j)
378  {
379  palette[j].components.alpha = 255;
380  palette[j].components.blue = buffer[i];
381  palette[j].components.green = buffer[i+1];
382  palette[j].components.red = buffer[i+2];
383  }
384 
385  delete[] buffer;
386 } // bitmap::reader::load_palette()
387 
388 /*----------------------------------------------------------------------------*/
395 void
396 claw::graphic::bitmap::reader::load_1bpp( const header& h, std::istream& f )
397 {
398  assert(h.bpp == 1);
399  //assert(h.compression == BMP_COMPRESSION_BITFIELDS);
400 
401  color_palette_type palette(2);
402  unsigned int buffer_size = m_image.width() / (sizeof(char) * 8);
403 
404  if ( m_image.width() % (sizeof(char) * 8) )
405  ++buffer_size;
406 
407  load_palette(h, f, palette);
408  f.seekg(h.data_offset);
409 
410  load_rgb_data(f, buffer_size, palette, pixel1_to_pixel32());
411 } // bitmap::reader::load_1bpp()
412 
413 /*----------------------------------------------------------------------------*/
420 void
421 claw::graphic::bitmap::reader::load_4bpp( const header& h, std::istream& f )
422 {
423  assert(h.bpp == 4);
424  assert( (h.compression == BMP_COMPRESSION_RGB)
425  || (h.compression == BMP_COMPRESSION_RLE4) );
426 
427  color_palette_type palette(16);
428  load_palette(h, f, palette);
429 
430  if (h.compression == BMP_COMPRESSION_RLE4)
431  load_4bpp_rle(h, f, palette);
432  else
433  load_4bpp_rgb(h, f, palette);
434 } // bitmap::reader::load_4bpp()
435 
436 /*----------------------------------------------------------------------------*/
443 void
444 claw::graphic::bitmap::reader::load_8bpp( const header& h, std::istream& f )
445 {
446  assert(h.bpp == 8);
447  assert( (h.compression == BMP_COMPRESSION_RGB)
448  || (h.compression == BMP_COMPRESSION_RLE8) );
449 
450  color_palette_type palette(256);
451  load_palette(h, f, palette);
452 
453  if (h.compression == BMP_COMPRESSION_RLE8)
454  load_8bpp_rle(h, f, palette);
455  else
456  load_8bpp_rgb(h, f, palette);
457 } // bitmap::reader::load_8bpp()
458 
459 /*----------------------------------------------------------------------------*/
466 void
467 claw::graphic::bitmap::reader::load_24bpp( const header& h, std::istream& f )
468 {
469  assert(h.bpp == 24);
470 
471  unsigned int buffer_size = m_image.width() * 3;
472  color_palette_type palette(0);
473 
474  f.seekg(h.data_offset);
475 
476  load_rgb_data(f, buffer_size, palette, pixel24_to_pixel32());
477 } // bitmap::reader::load_24bpp()
478 
479 /*----------------------------------------------------------------------------*/
488 void claw::graphic::bitmap::reader::load_4bpp_rle
489 ( const header& h, std::istream& f, const color_palette_type& palette )
490 {
491  assert(h.bpp == 4);
492  assert(h.compression == BMP_COMPRESSION_RLE4);
493  assert(palette.size() == 16);
494 
495  f.seekg(h.data_offset);
496 
497  rle4_decoder decoder;
498  rle4_decoder::output_buffer_type output_buffer( palette, m_image );
499  file_input_buffer input_buffer(f);
500 
501  decoder.decode( input_buffer, output_buffer );
502 } // bitmap::reader::load_4bpp_rle()
503 
504 /*----------------------------------------------------------------------------*/
513 void claw::graphic::bitmap::reader::load_4bpp_rgb
514 ( const header& h, std::istream& f, const color_palette_type& palette )
515 {
516  assert(h.bpp == 4);
517  assert(h.compression == BMP_COMPRESSION_RGB);
518  assert(palette.size() == 16);
519 
520  unsigned int buffer_size = m_image.width() / 2 + m_image.width() % 2;
521 
522  f.seekg(h.data_offset);
523 
524  load_rgb_data(f, buffer_size, palette, pixel4_to_pixel32());
525 } // bitmap::reader::load_4bpp_rgb()
526 
527 /*----------------------------------------------------------------------------*/
536 void claw::graphic::bitmap::reader::load_8bpp_rle
537 ( const header& h, std::istream& f, const color_palette_type& palette )
538 {
539  assert(h.bpp == 8);
540  assert(h.compression == BMP_COMPRESSION_RLE8);
541  assert(palette.size() == 256);
542 
543  f.seekg(h.data_offset);
544 
545  rle8_decoder decoder;
546  rle8_decoder::output_buffer_type output_buffer( palette, m_image );
547  file_input_buffer input_buffer(f);
548 
549  decoder.decode( input_buffer, output_buffer );
550 } // bitmap::reader::load_8bpp_rle()
551 
552 /*----------------------------------------------------------------------------*/
561 void claw::graphic::bitmap::reader::load_8bpp_rgb
562 ( const header& h, std::istream& f, const color_palette_type& palette )
563 {
564  assert(h.bpp == 8);
565  assert(h.compression == BMP_COMPRESSION_RGB);
566  assert(palette.size() == 256);
567 
568  unsigned int buffer_size = m_image.width();
569 
570  f.seekg(h.data_offset);
571 
572  load_rgb_data(f, buffer_size, palette, pixel8_to_pixel32());
573 } // bitmap::reader::load_8bpp_rgb()