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 /*----------------------------------------------------------------------------*/
42 void 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 /*----------------------------------------------------------------------------*/
67 claw::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 /*----------------------------------------------------------------------------*/
80 void 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 /*----------------------------------------------------------------------------*/
118 claw::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 /*----------------------------------------------------------------------------*/
132 void 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 /*----------------------------------------------------------------------------*/
149 void 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 /*----------------------------------------------------------------------------*/
174 claw::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 /*----------------------------------------------------------------------------*/
187 void 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 /*----------------------------------------------------------------------------*/
204 void 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 /*----------------------------------------------------------------------------*/
214 bool 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 /*----------------------------------------------------------------------------*/
229 void 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 /*----------------------------------------------------------------------------*/
294 void 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 /*----------------------------------------------------------------------------*/
361 void 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 /*----------------------------------------------------------------------------*/
373 void 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 /*----------------------------------------------------------------------------*/
387 void 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 /*----------------------------------------------------------------------------*/
402 void
403 claw::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 /*----------------------------------------------------------------------------*/
417 void 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 /*----------------------------------------------------------------------------*/
459 void 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()