2
CLAW - a C++ Library Absolutely Wonderful
4
CLAW is a free library without any particular aim but being useful to
7
Copyright (C) 2005-2008 Julien Jorge
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.
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.
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
23
contact: julien_jorge@yahoo.fr
26
* \file bitmap_reader.cpp
27
* \brief Implementation of the claw::graphic::bitmap::reader class.
28
* \author Julien Jorge
30
#include <claw/bitmap.hpp>
37
/*------------------------------------------------------------------------*/
39
* \brief Copy a color a certain number of times.
40
* \param n Number of copies.
41
* \param pattern The index of the color to copy.
42
* \remark This method is for 8bpp bitmaps.
45
void bitmap::reader::rle_bitmap_output_buffer<false>::fill
46
( unsigned int n, unsigned char pattern )
48
assert( m_x + n <= m_image.width() );
50
std::fill(&m_image[m_y][m_x], &m_image[m_y][m_x] + n, m_palette[pattern]);
53
} // bitmap::reader::rle_bitmap_output_buffer<false>::fill()
54
} // namespace graphic
61
/*------------------------------------------------------------------------*/
63
* \brief Copy a pair of colors a certain number of times.
64
* \param n Number of pixels to fill.
65
* \param pattern The index of the two colors to copy.
66
* \remark This method is for 4bpp bitmaps.
69
void bitmap::reader::rle_bitmap_output_buffer<true>::fill
70
( unsigned int n, unsigned char pattern )
72
assert( m_x + n <= m_image.width() );
74
for (unsigned int i = 0; i != n / 2; ++i, m_x += 2)
76
m_image[m_y][m_x] = m_palette[ (pattern & 0xF0) >> 4 ];
77
m_image[m_y][m_x+1] = m_palette[ pattern & 0x0F ];
82
m_image[m_y][m_x] = m_palette[ (pattern & 0xF0) >> 4 ];
85
} // bitmap::reader::rle_bitmap_output_buffer<false>::fill()
86
} // namespace graphic
93
/*------------------------------------------------------------------------*/
95
* \brief Copy some pixels directly.
96
* \param n The number of pixels to copy.
97
* \param buffer The input buffer, to copy from.
98
* \remark This method is for 8bpp bitmaps.
101
void bitmap::reader::rle_bitmap_output_buffer<false>::copy
102
( unsigned int n, file_input_buffer& buffer )
104
assert( m_x + n <= m_image.width() );
106
// RLE bitmap data is 2-bytes aligned
107
const unsigned int bytes_needed = n + n % 2;
109
if ( buffer.remaining() < bytes_needed )
110
buffer.read_more(bytes_needed);
112
assert( buffer.remaining() >= bytes_needed );
114
const unsigned char* p =
115
reinterpret_cast<const unsigned char*>(buffer.get_buffer());
117
std::transform( p, p + n, &m_image[m_y][m_x], m_palette );
121
buffer.move(bytes_needed);
122
} // bitmap::reader::rle_bitmap_output_buffer<false>::copy()
123
} // namespace graphic
130
/*------------------------------------------------------------------------*/
132
* \brief Copy some pixels directly.
133
* \param n The number of pixels to copy.
134
* \param buffer The input buffer, to copy from.
135
* \remark This method is for 4bpp bitmaps.
138
void bitmap::reader::rle_bitmap_output_buffer<true>::copy
139
( unsigned int n, file_input_buffer& buffer )
141
assert( m_x + n <= m_image.width() );
143
// RLE bitmap data is 2-bytes aligned
144
unsigned int bytes_needed = n / 2 + n % 2;
146
if ( bytes_needed % 2 )
149
if ( buffer.remaining() < bytes_needed )
150
buffer.read_more( bytes_needed );
152
assert( buffer.remaining() >= bytes_needed );
154
const unsigned char* p =
155
reinterpret_cast<const unsigned char*>(buffer.get_buffer());
156
const unsigned char* last = p + n / 2;
158
for ( ; p != last; ++p, m_x += 2)
160
m_image[m_y][m_x] = m_palette[ (*p & 0xF0) >> 4 ];
161
m_image[m_y][m_x+1] = m_palette[ *p & 0x0F ];
166
m_image[m_y][m_x] = m_palette[ (*p & 0xF0) >> 4 ];
170
buffer.move( bytes_needed );
171
} // bitmap::reader::rle_bitmap_output_buffer<true>::copy()
172
} // namespace graphic
177
/*----------------------------------------------------------------------------*/
179
* \brief Convert a bitset array to a pixel32 scanline.
180
* \param dest (out) Filled scanline.
181
* \param src Pixel array to convert.
182
* \param palette Color palette.
183
* \pre palette.size() == 2
185
void claw::graphic::bitmap::reader::pixel1_to_pixel32::operator()
186
( scanline& dest, const char* src, const color_palette_type& palette ) const
188
assert(palette.size() == 2);
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;
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) )
202
for (unsigned int j = 0; j != (n % byte_size); ++j, ++it)
203
if ( src[upper_bound] & (0x80 >> j) )
207
} // bitmap::reader::pixel1_to_pixel32()
209
/*----------------------------------------------------------------------------*/
211
* \brief Convert a 4bpp array to a pixel32 scanline.
212
* \param dest (out) Filled scanline.
213
* \param src Pixel array to convert.
214
* \param palette Color palette.
215
* \pre palette.size() == 16
217
void claw::graphic::bitmap::reader::pixel4_to_pixel32::operator()
218
( scanline& dest, const char* src, const color_palette_type& palette ) const
220
assert(palette.size() == 16);
222
scanline::iterator it( dest.begin() );
223
const unsigned int upper_bound = dest.size() / 2;
225
for (unsigned int i=0; i!=upper_bound; ++i, ++src)
227
*it = palette[ (*src & 0xF0) >> 4 ];
229
*it = palette[ *src & 0x0F ];
234
*it = palette[ (*src & 0xF0) >> 4 ];
235
} // bitmap::reader::pixel4_to_pixel32()
237
/*----------------------------------------------------------------------------*/
239
* \brief Convert a 8bpp array to a pixel32 scanline.
240
* \param dest (out) Filled scanline.
241
* \param src Pixel array to convert.
242
* \param palette Color palette.
243
* \pre palette.size() == 256
245
void claw::graphic::bitmap::reader::pixel8_to_pixel32::operator()
246
( scanline& dest, const char* src, const color_palette_type& palette ) const
248
assert(palette.size() == 256);
250
const unsigned char* s = reinterpret_cast<const unsigned char*>(src);
252
std::transform(s, s + dest.size(), dest.begin(), palette);
253
} // bitmap::reader::pixel8_to_pixel32()
255
/*----------------------------------------------------------------------------*/
257
* \brief Convert a BGR array to a pixel32 scanline.
258
* \param dest (out) Filled scanline.
259
* \param src Pixel array to convert.
260
* \param palette (not used) Color palette.
262
void claw::graphic::bitmap::reader::pixel24_to_pixel32::operator()
263
( scanline& dest, const char* src, const color_palette_type& palette ) const
265
scanline::iterator it( dest.begin() );
266
const unsigned int upper_bound = 3 * dest.size();
268
for (unsigned int i=0; i!=upper_bound; i+=3)
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];
277
} // bitmap::reader::pixel24_to_pixel32()
282
/*----------------------------------------------------------------------------*/
284
* \brief Constructor.
285
* \param img The image in which the data will be stored.
287
claw::graphic::bitmap::reader::reader( image& img )
291
} // bitmap::reader::reader()
293
/*----------------------------------------------------------------------------*/
295
* \brief Constructor.
296
* \param img The image in which the data will be stored.
297
* \param f The file from which we read the data.
298
* \post img contains the data from \a f.
300
claw::graphic::bitmap::reader::reader( image& img, std::istream& f )
304
} // bitmap::reader::reader()
306
/*----------------------------------------------------------------------------*/
308
* \brief Load the image data from a stream.
309
* \param f The file from which we read the data.
310
* \post The image passed to the constructor contains the data from \a f.
312
void claw::graphic::bitmap::reader::load( std::istream& f )
315
std::istream::pos_type init_pos = f.tellg();
321
f.read( reinterpret_cast<char*>(&h), sizeof(header) );
323
if ( (h.id[0] == 'B') && (h.id[1] == 'M')
324
&& (f.rdstate() == std::ios_base::goodbit) )
326
m_image.set_size(h.width, h.height);
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;
336
throw claw::bad_format
337
("bitmap::bitmap: unsupported color depth.");
341
throw claw::bad_format( "bitmap::bitmap: invalid header." );
346
f.seekg( init_pos, std::ios_base::beg );
349
} // bitmap::reader::load()
351
/*----------------------------------------------------------------------------*/
353
* \brief Load the palette of the image.
354
* \param h File's header, must have been read before call.
355
* \param f Bitmap file.
356
* \param palette The loaded palette.
359
void claw::graphic::bitmap::reader::load_palette
360
( const header& h, std::istream& f, color_palette_type& palette ) const
366
case 1 : assert( palette.size() == 2 ); break;
367
case 4 : assert( palette.size() == 16 ); break;
368
case 8 : assert( palette.size() == 256 ); break;
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];
375
f.read(buffer, buffer_size);
377
for (unsigned int i=0, j=0; i!=buffer_size; i+=sizeof_color, ++j)
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];
386
} // bitmap::reader::load_palette()
388
/*----------------------------------------------------------------------------*/
390
* \brief Load a monochrome bitmap file.
391
* \param h File's header, must have been read before call.
392
* \param f Bitmap file.
396
claw::graphic::bitmap::reader::load_1bpp( const header& h, std::istream& f )
399
//assert(h.compression == BMP_COMPRESSION_BITFIELDS);
401
color_palette_type palette(2);
402
unsigned int buffer_size = m_image.width() / (sizeof(char) * 8);
404
if ( m_image.width() % (sizeof(char) * 8) )
407
load_palette(h, f, palette);
408
f.seekg(h.data_offset);
410
load_rgb_data(f, buffer_size, palette, pixel1_to_pixel32());
411
} // bitmap::reader::load_1bpp()
413
/*----------------------------------------------------------------------------*/
415
* \brief Loads a 4 bpp bitmap file.
416
* \param h File's header, must have been read before call.
417
* \param f Bitmap file.
421
claw::graphic::bitmap::reader::load_4bpp( const header& h, std::istream& f )
424
assert( (h.compression == BMP_COMPRESSION_RGB)
425
|| (h.compression == BMP_COMPRESSION_RLE4) );
427
color_palette_type palette(16);
428
load_palette(h, f, palette);
430
if (h.compression == BMP_COMPRESSION_RLE4)
431
load_4bpp_rle(h, f, palette);
433
load_4bpp_rgb(h, f, palette);
434
} // bitmap::reader::load_4bpp()
436
/*----------------------------------------------------------------------------*/
438
* \brief Loads a 8 bpp bitmap file.
439
* \param h File's header, must have been read before call.
440
* \param f Bitmap file.
444
claw::graphic::bitmap::reader::load_8bpp( const header& h, std::istream& f )
447
assert( (h.compression == BMP_COMPRESSION_RGB)
448
|| (h.compression == BMP_COMPRESSION_RLE8) );
450
color_palette_type palette(256);
451
load_palette(h, f, palette);
453
if (h.compression == BMP_COMPRESSION_RLE8)
454
load_8bpp_rle(h, f, palette);
456
load_8bpp_rgb(h, f, palette);
457
} // bitmap::reader::load_8bpp()
459
/*----------------------------------------------------------------------------*/
461
* \brief Loads a 24 bpp bitmap file.
462
* \param h File's header, must have been read before call.
463
* \param f Bitmap file.
467
claw::graphic::bitmap::reader::load_24bpp( const header& h, std::istream& f )
471
unsigned int buffer_size = m_image.width() * 3;
472
color_palette_type palette(0);
474
f.seekg(h.data_offset);
476
load_rgb_data(f, buffer_size, palette, pixel24_to_pixel32());
477
} // bitmap::reader::load_24bpp()
479
/*----------------------------------------------------------------------------*/
481
* \brief Loads a 4 bpp RLE encoded bitmap file.
482
* \param h File's header and palette, must have been read before call.
483
* \param f Bitmap file.
484
* \param palette The color palette to use for converting colors.
485
* \pre (h.bpp == 4) && (h.compression = BMP_COMPRESSION_RLE4)
486
* && (palette.size() == 16)
488
void claw::graphic::bitmap::reader::load_4bpp_rle
489
( const header& h, std::istream& f, const color_palette_type& palette )
492
assert(h.compression == BMP_COMPRESSION_RLE4);
493
assert(palette.size() == 16);
495
f.seekg(h.data_offset);
497
rle4_decoder decoder;
498
rle4_decoder::output_buffer_type output_buffer( palette, m_image );
499
file_input_buffer input_buffer(f);
501
decoder.decode( input_buffer, output_buffer );
502
} // bitmap::reader::load_4bpp_rle()
504
/*----------------------------------------------------------------------------*/
506
* \brief Loads a 4 bpp RGB encoded bitmap file.
507
* \param h File's header and palette, must have been read before call.
508
* \param f Bitmap file.
509
* \param palette The color palette to use for converting colors.
510
* \pre (h.bpp == 4) && (h.compression = BMP_COMPRESSION_RGB)
511
* && (palette.size() == 16)
513
void claw::graphic::bitmap::reader::load_4bpp_rgb
514
( const header& h, std::istream& f, const color_palette_type& palette )
517
assert(h.compression == BMP_COMPRESSION_RGB);
518
assert(palette.size() == 16);
520
unsigned int buffer_size = m_image.width() / 2 + m_image.width() % 2;
522
f.seekg(h.data_offset);
524
load_rgb_data(f, buffer_size, palette, pixel4_to_pixel32());
525
} // bitmap::reader::load_4bpp_rgb()
527
/*----------------------------------------------------------------------------*/
529
* \brief Loads a 8 bpp bitmap file.
530
* \param h File's header and palette, must have been read before call.
531
* \param f Bitmap file.
532
* \param palette The color palette to use for converting colors.
533
* \pre (h.bpp == 8) && (h.compression = BMP_COMPRESSION_RLE8)
534
* && (palette.size() == 256)
536
void claw::graphic::bitmap::reader::load_8bpp_rle
537
( const header& h, std::istream& f, const color_palette_type& palette )
540
assert(h.compression == BMP_COMPRESSION_RLE8);
541
assert(palette.size() == 256);
543
f.seekg(h.data_offset);
545
rle8_decoder decoder;
546
rle8_decoder::output_buffer_type output_buffer( palette, m_image );
547
file_input_buffer input_buffer(f);
549
decoder.decode( input_buffer, output_buffer );
550
} // bitmap::reader::load_8bpp_rle()
552
/*----------------------------------------------------------------------------*/
554
* \brief Loads a 8 bpp RGB encoded bitmap file.
555
* \param h File's header and palette, must have been read before call.
556
* \param f Bitmap file.
557
* \param palette The color palette to use for converting colors.
558
* \pre (h.bpp == 8) && (h.compression = BMP_COMPRESSION_RGB)
559
* && (palette.size() == 256)
561
void claw::graphic::bitmap::reader::load_8bpp_rgb
562
( const header& h, std::istream& f, const color_palette_type& palette )
565
assert(h.compression == BMP_COMPRESSION_RGB);
566
assert(palette.size() == 256);
568
unsigned int buffer_size = m_image.width();
570
f.seekg(h.data_offset);
572
load_rgb_data(f, buffer_size, palette, pixel8_to_pixel32());
573
} // bitmap::reader::load_8bpp_rgb()