Claw 1.7.3
pcx_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/pcx.hpp>
31#include <claw/exception.hpp>
32
33#include <limits>
34
35/*----------------------------------------------------------------------------*/
42void claw::graphic::pcx::reader::converter_mono::operator()
43( const std::vector<color_plane_type>& scanline, image& img,
44 unsigned int y ) const
45{
46 CLAW_PRECOND( scanline.size() == 1 );
47
48 unsigned int x=0;
49
50 for ( unsigned int code=0; x!=img.width(); ++code )
51 {
52 u_int_8 c = scanline[0][code]; // only one color plane for monochrome pcx
53
54 for( unsigned int i=0; (i!=8) && (x!=img.width()); ++x, ++i, c<<=1 )
55 if ( c & 0x80 )
56 img[y][x] = white_pixel;
57 else
58 img[y][x] = black_pixel;
59 }
60} // pcx::reader::converter_mono::operator()()
61
62/*----------------------------------------------------------------------------*/
67claw::graphic::pcx::reader::converter_16::converter_16( const header& h )
68 : m_header(h)
69{
70
71} // pcx::reader::converter_16::converter_16()
72
73/*----------------------------------------------------------------------------*/
80void claw::graphic::pcx::reader::converter_16::operator()
81( const std::vector<color_plane_type>& scanline, image& img,
82 unsigned int y ) const
83{
84 CLAW_PRECOND( scanline.size() == 4 );
85
86 unsigned int x=0;
87
88 for ( unsigned int code=0; x!=img.width(); ++code )
89 {
90 u_int_8 c0 = scanline[0][code];
91 u_int_8 c1 = scanline[1][code];
92 u_int_8 c2 = scanline[2][code];
93 u_int_8 c3 = scanline[3][code];
94
95 for( unsigned int i=0; (i!=8) && (x!=img.width()); ++x, ++i )
96 {
97 unsigned int index =
98 ( (c3 & 0x80) >> 4 )
99 | ( (c2 & 0x80) >> 5 )
100 | ( (c1 & 0x80) >> 6 )
101 | ( (c0 & 0x80) >> 7 );
102
103 img[y][x] = m_header.color_map[index];
104
105 c0 <<= 1;
106 c1 <<= 1;
107 c2 <<= 1;
108 c3 <<= 1;
109 }
110 }
111} // pcx::reader::converter_16::operator()()
112
113/*----------------------------------------------------------------------------*/
118claw::graphic::pcx::reader::converter_256::converter_256
119( const color_palette32& palette )
120 : m_palette(palette)
121{
122
123} // pcx::reader::converter_256::converter_256()
124
125/*----------------------------------------------------------------------------*/
132void claw::graphic::pcx::reader::converter_256::operator()
133( const std::vector<color_plane_type>& scanline, image& img,
134 unsigned int y ) const
135{
136 CLAW_PRECOND( scanline.size() == 1 );
137
138 for ( unsigned int x=0; x!=img.width(); ++x )
139 img[y][x] = m_palette[ scanline[0][x] ];
140} // pcx::reader::converter_256::operator()()
141
142/*----------------------------------------------------------------------------*/
149void claw::graphic::pcx::reader::converter_true_color::operator()
150( const std::vector<color_plane_type>& scanline, image& img,
151 unsigned int y ) const
152{
153 CLAW_PRECOND( scanline.size() == 3 );
154
155 for ( unsigned int x=0; x!=img.width(); ++x )
156 {
157 img[y][x].components.red = scanline[0][x];
158 img[y][x].components.green = scanline[1][x];
159 img[y][x].components.blue = scanline[2][x];
160 img[y][x].components.alpha =
161 std::numeric_limits<rgba_pixel_8::component_type>::max();
162 }
163} // pcx::reader::converter_true_color::operator()()
164
165
166
167
168/*----------------------------------------------------------------------------*/
174claw::graphic::pcx::reader::rle_pcx_output_buffer::rle_pcx_output_buffer
175( color_plane_type& result )
176 : m_result(result), m_position(0)
177{
178
179} // pcx::reader::rle_pcx_output_buffer::rle_pcx_output_buffer()
180
181/*----------------------------------------------------------------------------*/
187void claw::graphic::pcx::reader::rle_pcx_output_buffer::fill
188( unsigned int n, u_int_8 pattern )
189{
190 CLAW_PRECOND( m_position + n <= m_result.size() );
191
192 for (unsigned int i=0; i!=n; ++i)
193 m_result[m_position + i] = pattern;
194
195 m_position += n;
196} // pcx::reader::rle_pcx_output_buffer::fill()
197
198/*----------------------------------------------------------------------------*/
204void claw::graphic::pcx::reader::rle_pcx_output_buffer::copy
205( unsigned int n, rle_pcx_input_buffer& buffer )
206{
207 CLAW_ASSERT( false, "This method should not have been called" );
208} // pcx::reader::rle_pcx_output_buffer::copy()
209
210/*----------------------------------------------------------------------------*/
214bool claw::graphic::pcx::reader::rle_pcx_output_buffer::completed() const
215{
216 return m_position == m_result.size();
217} // pcx::reader::rle_pcx_output_buffer::completed()
218
219
220
221
222
223/*----------------------------------------------------------------------------*/
229void claw::graphic::pcx::reader::rle_pcx_decoder::read_mode
230( input_buffer_type& input, output_buffer_type& output )
231{
232 this->m_mode = this->stop;
233 bool ok = !output.completed();
234
235 if ( ok && (input.remaining() < 1) )
236 ok = input.read_more(1);
237
238 if (ok)
239 {
240 unsigned char key = input.get_next();
241 this->m_mode = this->compressed;
242
243 if ( (key & 0xC0) == 0xC0 )
244 {
245 this->m_count = key & 0x3F;
246
247 if ( input.remaining() < 1 )
248 input.read_more(1);
249
250 this->m_pattern = input.get_next();
251 }
252 else
253 {
254 this->m_count = 1;
255 this->m_pattern = key;
256 }
257 }
258} // pcx::reader::rle_pcx_decoder::read_mode()
259
260
261
262
263
264
265/*----------------------------------------------------------------------------*/
271 : m_image( img )
272{
273
274} // pcx::reader::reader()
275
276/*----------------------------------------------------------------------------*/
284 : m_image( img )
285{
286 load(f);
287} // pcx::reader::reader()
288
289/*----------------------------------------------------------------------------*/
294void claw::graphic::pcx::reader::load( std::istream& f )
295{
296 CLAW_PRECOND( !!f );
297 std::istream::pos_type init_pos = f.tellg();
298
299 try
300 {
301 header h;
302
303 f.read( reinterpret_cast<char*>(&h), sizeof(header) );
304
305 if ( f.rdstate() == std::ios_base::goodbit )
306 {
307 check_if_pcx(h);
308
309 m_image.set_size( h.window.x_max - h.window.x_min + 1,
310 h.window.y_max - h.window.y_min + 1 );
311
312 bool supported_format = true;
313
314 switch(h.color_planes)
315 {
316 case 1:
317 if (h.bpp == 1)
318 load_mono(h, f);
319 else if (h.bpp == 8)
320 load_256_color_mapped(h, f);
321 else
322 supported_format = false;
323 break;
324 case 3:
325 if (h.bpp == 8)
326 load_true_color(h, f);
327 else
328 supported_format = false;
329 break;
330 case 4:
331 if (h.bpp == 1)
332 load_16_color_mapped(h, f);
333 else
334 supported_format = false;
335 break;
336 default :
337 supported_format = false;
338 }
339
340 if ( supported_format == false )
341 throw claw::bad_format
342 ( "pcx::reader::pcx: unsupported image type" );
343 }
344 else
345 throw claw::bad_format
346 ( "claw::pcx::reader::pcx: can't read header" );
347 }
348 catch(...)
349 {
350 f.clear();
351 f.seekg( init_pos, std::ios_base::beg );
352 throw;
353 }
354} // pcx::reader::load()
355
356/*----------------------------------------------------------------------------*/
361void claw::graphic::pcx::reader::check_if_pcx( const header& h ) const
362{
363 if ( h.manufacturer != 0x0A )
364 throw CLAW_EXCEPTION( "Not a Pcx file." );
365} // pcx::reader::check_if_pcx()
366
367/*----------------------------------------------------------------------------*/
373void claw::graphic::pcx::reader::load_mono( const header& h, std::istream& f )
374{
375 assert( h.color_planes == 1 );
376
377 converter_mono convert;
378 decompress( h, f, convert );
379} // pcx::reader::load_mono()
380
381/*----------------------------------------------------------------------------*/
387void claw::graphic::pcx::reader::load_16_color_mapped
388( const header& h, std::istream& f )
389{
390 assert( h.color_planes == 4 );
391
392 converter_16 convert(h);
393 decompress( h, f, convert );
394} // pcx::reader::load_16_color_mapped()
395
396/*----------------------------------------------------------------------------*/
402void
403claw::graphic::pcx::reader::load_true_color( const header& h, std::istream& f )
404{
405 assert( h.color_planes == 3 );
406
407 converter_true_color convert;
408 decompress( h, f, convert );
409} // pcx::reader::load_true_color()
410
411/*----------------------------------------------------------------------------*/
417void claw::graphic::pcx::reader::load_256_color_mapped
418( const header& h, std::istream& f )
419{
420 assert( h.color_planes == 1 );
421
422 // 256 RGB triplets
423 const unsigned int palette_length = 256 * 3;
424
425 color_palette32 palette(256);
426 std::istream::pos_type init_pos = f.tellg();
427
428 // -1 for the check byte
429 f.seekg( -(std::istream::off_type)palette_length - 1, std::ios_base::end );
430
431 char check;
432 f.read(&check, 1);
433
434 if ( check != 12 )
435 throw CLAW_EXCEPTION( "PCX: The color palette is missing." );
436
437 char buffer[palette_length];
438 f.read(buffer, palette_length);
439
440 for (unsigned int i=0, j=0; i!=palette_length; i+=3, ++j)
441 {
442 palette[j].components.alpha = 255;
443 palette[j].components.red = buffer[i];
444 palette[j].components.green = buffer[i+1];
445 palette[j].components.blue = buffer[i+2];
446 }
447
448 f.seekg( init_pos );
449 converter_256 convert(palette);
450 decompress( h, f, convert );
451} // pcx::reader::load_256_color_mapped()
452
453/*----------------------------------------------------------------------------*/
459void claw::graphic::pcx::reader::decompress_line
460( std::istream& f, color_plane_type& scanline ) const
461{
462 rle_pcx_input_buffer input(f);
463 rle_pcx_output_buffer output(scanline);
464
465 rle_pcx_decoder decoder;
466
467 decoder.decode( input, output );
468} // pcx::reader::decompress_line()
#define CLAW_PRECOND(b)
Abort the program if a precondition is not true.
Definition assert.hpp:98
#define CLAW_ASSERT(b, s)
Print a message on std::cerr and stop the program if a condition is not true.
Definition assert.hpp:90
Exception thrown when accessing bad formated data.
Definition exception.hpp:72
A class to deal with images.
Definition image.hpp:50
void load(std::istream &f)
Load an image from a pcx file.
reader(image &img)
Constructor.
A simple class to use as exception with string message.
#define CLAW_EXCEPTION(m)
Create an exception and add the name of the current function to the message.
Definition exception.hpp:90
rgba_pixel black_pixel(0, 0, 0, std::numeric_limits< rgba_pixel::component_type >::max())
The black color.
Definition pixel.hpp:136
rgba_pixel white_pixel
The white color.
unsigned_integer_of_size< 8 >::type u_int_8
An unsigned integer on 8 bits.
Definition types.hpp:135
A class for pcx pictures.