claw 1.9.0
 
Loading...
Searching...
No Matches
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@stuff-o-matic.com
24*/
31
32#include <algorithm>
33
34namespace claw
35{
36 namespace graphic
37 {
44 template <>
45 void bitmap::reader::rle_bitmap_output_buffer<false>::fill(
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,
51 m_palette[pattern]);
52
53 m_x += n;
54 }
55 }
56}
57
58namespace claw
59{
60 namespace graphic
61 {
68 template <>
69 void
70 bitmap::reader::rle_bitmap_output_buffer<true>::fill(unsigned int n,
71 unsigned char pattern)
72 {
73 assert(m_x + n <= m_image.width());
74
75 for(unsigned int i = 0; i != n / 2; ++i, m_x += 2)
76 {
77 m_image[m_y][m_x] = m_palette[(pattern & 0xF0) >> 4];
78 m_image[m_y][m_x + 1] = m_palette[pattern & 0x0F];
79 }
80
81 if(n % 2)
82 {
83 m_image[m_y][m_x] = m_palette[(pattern & 0xF0) >> 4];
84 ++m_x;
85 }
86 }
87 }
88}
89
90namespace claw
91{
92 namespace graphic
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 }
123 }
124}
125
126namespace claw
127{
128 namespace graphic
129 {
136 template <>
137 void bitmap::reader::rle_bitmap_output_buffer<true>::copy(
138 unsigned int n, file_input_buffer& buffer)
139 {
140 assert(m_x + n <= m_image.width());
141
142 // RLE bitmap data is 2-bytes aligned
143 unsigned int bytes_needed = n / 2 + n % 2;
144
145 if(bytes_needed % 2)
146 ++bytes_needed;
147
148 if(buffer.remaining() < bytes_needed)
149 buffer.read_more(bytes_needed);
150
151 assert(buffer.remaining() >= bytes_needed);
152
153 const unsigned char* p
154 = reinterpret_cast<const unsigned char*>(buffer.get_buffer());
155 const unsigned char* last = p + n / 2;
156
157 for(; p != last; ++p, m_x += 2)
158 {
159 m_image[m_y][m_x] = m_palette[(*p & 0xF0) >> 4];
160 m_image[m_y][m_x + 1] = m_palette[*p & 0x0F];
161 }
162
163 if(n % 2)
164 {
165 m_image[m_y][m_x] = m_palette[(*p & 0xF0) >> 4];
166 ++m_x;
167 }
168
169 buffer.move(bytes_needed);
170 }
171 }
172}
173
181void claw::graphic::bitmap::reader::pixel1_to_pixel32::operator()(
182 scanline& dest, const char* src, const color_palette_type& palette) const
183{
184 assert(palette.size() == 2);
185
186 scanline::iterator it(dest.begin());
187 const unsigned int n = dest.size();
188 const unsigned int byte_size = 8; // 8 bits per byte
189 const unsigned int upper_bound = n / byte_size;
190
191 for(unsigned int i = 0; i != upper_bound; ++i)
192 for(unsigned int j = 0; j != byte_size; ++j, ++it)
193 if(src[i] & (0x80 >> j))
194 *it = palette[1];
195 else
196 *it = palette[0];
197
198 for(unsigned int j = 0; j != (n % byte_size); ++j, ++it)
199 if(src[upper_bound] & (0x80 >> j))
200 *it = palette[1];
201 else
202 *it = palette[0];
203}
204
212void claw::graphic::bitmap::reader::pixel4_to_pixel32::operator()(
213 scanline& dest, const char* src, const color_palette_type& palette) const
214{
215 assert(palette.size() == 16);
216
217 scanline::iterator it(dest.begin());
218 const unsigned int upper_bound = dest.size() / 2;
219
220 for(unsigned int i = 0; i != upper_bound; ++i, ++src)
221 {
222 *it = palette[(*src & 0xF0) >> 4];
223 ++it;
224 *it = palette[*src & 0x0F];
225 ++it;
226 }
227
228 if(dest.size() % 2)
229 *it = palette[(*src & 0xF0) >> 4];
230}
231
239void claw::graphic::bitmap::reader::pixel8_to_pixel32::operator()(
240 scanline& dest, const char* src, const color_palette_type& palette) const
241{
242 assert(palette.size() == 256);
243
244 const unsigned char* s = reinterpret_cast<const unsigned char*>(src);
245
246 std::transform(s, s + dest.size(), dest.begin(), palette);
247}
248
255void claw::graphic::bitmap::reader::pixel24_to_pixel32::operator()(
256 scanline& dest, const char* src, const color_palette_type& palette) const
257{
258 scanline::iterator it(dest.begin());
259 const unsigned int upper_bound = 3 * dest.size();
260
261 for(unsigned int i = 0; i != upper_bound; i += 3)
262 {
263 it->components.alpha = 255;
264 it->components.blue = src[i];
265 it->components.green = src[i + 1];
266 it->components.red = src[i + 2];
267
268 ++it;
269 }
270}
271
277 : m_image(img)
278{}
279
287 : m_image(img)
288{
289 load(f);
290}
291
298{
299 CLAW_PRECOND(!!f);
300 std::istream::pos_type init_pos = f.tellg();
301
302 try
303 {
304 header h;
305
306 f.read(reinterpret_cast<char*>(&h), sizeof(header));
307
308 if((h.id[0] == 'B') && (h.id[1] == 'M')
309 && (f.rdstate() == std::ios_base::goodbit))
310 {
311 m_image.set_size(h.width, h.height);
312
313 switch(h.bpp)
314 {
315 case 1:
316 load_1bpp(h, f);
317 break;
318 case 4:
319 load_4bpp(h, f);
320 break;
321 case 8:
322 load_8bpp(h, f);
323 break;
324 // case 16 : load_16bpp(h, f); break;
325 case 24:
326 load_24bpp(h, f);
327 break;
328 default:
329 throw claw::bad_format(
330 "bitmap::bitmap: unsupported color depth.");
331 }
332 }
333 else
334 throw claw::bad_format("bitmap::bitmap: invalid header.");
335 }
336 catch(...)
337 {
338 f.clear();
339 f.seekg(init_pos, std::ios_base::beg);
340 throw;
341 }
342}
343
351void claw::graphic::bitmap::reader::load_palette(
352 const header& h, std::istream& f, color_palette_type& palette) const
353{
354 assert(h.bpp <= 8);
355
356 switch(h.bpp)
357 {
358 case 1:
359 assert(palette.size() == 2);
360 break;
361 case 4:
362 assert(palette.size() == 16);
363 break;
364 case 8:
365 assert(palette.size() == 256);
366 break;
367 }
368
369 const unsigned int sizeof_color = sizeof(color_palette_type::color_type);
370 const unsigned int buffer_size = sizeof_color * palette.size();
371 char* buffer = new char[buffer_size];
372
373 f.read(buffer, buffer_size);
374
375 for(unsigned int i = 0, j = 0; i != buffer_size; i += sizeof_color, ++j)
376 {
377 palette[j].components.alpha = 255;
378 palette[j].components.blue = buffer[i];
379 palette[j].components.green = buffer[i + 1];
380 palette[j].components.red = buffer[i + 2];
381 }
382
383 delete[] buffer;
384}
385
392void claw::graphic::bitmap::reader::load_1bpp(const header& h, std::istream& f)
393{
394 assert(h.bpp == 1);
395 // assert(h.compression == BMP_COMPRESSION_BITFIELDS);
396
397 color_palette_type palette(2);
398 unsigned int buffer_size = m_image.width() / (sizeof(char) * 8);
399
400 if(m_image.width() % (sizeof(char) * 8))
401 ++buffer_size;
402
403 load_palette(h, f, palette);
404 f.seekg(h.data_offset);
405
406 load_rgb_data(f, buffer_size, palette, pixel1_to_pixel32());
407}
408
415void claw::graphic::bitmap::reader::load_4bpp(const header& h, std::istream& f)
416{
417 assert(h.bpp == 4);
418 assert((h.compression == BMP_COMPRESSION_RGB)
419 || (h.compression == BMP_COMPRESSION_RLE4));
420
421 color_palette_type palette(16);
422 load_palette(h, f, palette);
423
424 if(h.compression == BMP_COMPRESSION_RLE4)
425 load_4bpp_rle(h, f, palette);
426 else
427 load_4bpp_rgb(h, f, palette);
428}
429
436void claw::graphic::bitmap::reader::load_8bpp(const header& h, std::istream& f)
437{
438 assert(h.bpp == 8);
439 assert((h.compression == BMP_COMPRESSION_RGB)
440 || (h.compression == BMP_COMPRESSION_RLE8));
441
442 color_palette_type palette(256);
443 load_palette(h, f, palette);
444
445 if(h.compression == BMP_COMPRESSION_RLE8)
446 load_8bpp_rle(h, f, palette);
447 else
448 load_8bpp_rgb(h, f, palette);
449}
450
457void claw::graphic::bitmap::reader::load_24bpp(const header& h,
458 std::istream& f)
459{
460 assert(h.bpp == 24);
461
462 unsigned int buffer_size = m_image.width() * 3;
463 color_palette_type palette(0);
464
465 f.seekg(h.data_offset);
466
467 load_rgb_data(f, buffer_size, palette, pixel24_to_pixel32());
468}
469
478void claw::graphic::bitmap::reader::load_4bpp_rle(
479 const header& h, std::istream& f, const color_palette_type& palette)
480{
481 assert(h.bpp == 4);
482 assert(h.compression == BMP_COMPRESSION_RLE4);
483 assert(palette.size() == 16);
484
485 f.seekg(h.data_offset);
486
487 rle4_decoder decoder;
488 rle4_decoder::output_buffer_type output_buffer(palette, m_image);
489 file_input_buffer input_buffer(f);
490
491 decoder.decode(input_buffer, output_buffer);
492}
493
502void claw::graphic::bitmap::reader::load_4bpp_rgb(
503 const header& h, std::istream& f, const color_palette_type& palette)
504{
505 assert(h.bpp == 4);
506 assert(h.compression == BMP_COMPRESSION_RGB);
507 assert(palette.size() == 16);
508
509 unsigned int buffer_size = m_image.width() / 2 + m_image.width() % 2;
510
511 f.seekg(h.data_offset);
512
513 load_rgb_data(f, buffer_size, palette, pixel4_to_pixel32());
514}
515
524void claw::graphic::bitmap::reader::load_8bpp_rle(
525 const header& h, std::istream& f, const color_palette_type& palette)
526{
527 assert(h.bpp == 8);
528 assert(h.compression == BMP_COMPRESSION_RLE8);
529 assert(palette.size() == 256);
530
531 f.seekg(h.data_offset);
532
533 rle8_decoder decoder;
534 rle8_decoder::output_buffer_type output_buffer(palette, m_image);
535 file_input_buffer input_buffer(f);
536
537 decoder.decode(input_buffer, output_buffer);
538}
539
548void claw::graphic::bitmap::reader::load_8bpp_rgb(
549 const header& h, std::istream& f, const color_palette_type& palette)
550{
551 assert(h.bpp == 8);
552 assert(h.compression == BMP_COMPRESSION_RGB);
553 assert(palette.size() == 256);
554
555 unsigned int buffer_size = m_image.width();
556
557 f.seekg(h.data_offset);
558
559 load_rgb_data(f, buffer_size, palette, pixel8_to_pixel32());
560}
#define CLAW_PRECOND(b)
Abort the program if a precondition is not true.
Definition assert.hpp:94
A class for bitmap pictures.
Exception thrown when accessing bad formated data.
Definition exception.hpp:74
reader(image &img)
Constructor.
void load(std::istream &f)
Load the image data from a stream.
image()
Constructor. Creates an image without datas.
Definition image.cpp:95
Everything about image structures and processing.
Definition claw.hpp:58
This is the main namespace.
unsigned short bpp
Bits per pixel.
Definition bitmap.hpp:105
unsigned int height
Image's height.
Definition bitmap.hpp:99
char id[2]
File identifier (must be 'BM').
Definition bitmap.hpp:81