Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00030 #include <claw/pcx.hpp>
00031 #include <claw/exception.hpp>
00032
00033 #include <limits>
00034
00035
00042 void claw::graphic::pcx::reader::converter_mono::operator()
00043 ( const std::vector<color_plane_type>& scanline, image& img,
00044 unsigned int y ) const
00045 {
00046 CLAW_PRECOND( scanline.size() == 1 );
00047
00048 unsigned int x=0;
00049
00050 for ( unsigned int code=0; x!=img.width(); ++code )
00051 {
00052 u_int_8 c = scanline[0][code];
00053
00054 for( unsigned int i=0; (i!=8) && (x!=img.width()); ++x, ++i, c<<=1 )
00055 if ( c & 0x80 )
00056 img[y][x] = white_pixel;
00057 else
00058 img[y][x] = black_pixel;
00059 }
00060 }
00061
00062
00067 claw::graphic::pcx::reader::converter_16::converter_16( const header& h )
00068 : m_header(h)
00069 {
00070
00071 }
00072
00073
00080 void claw::graphic::pcx::reader::converter_16::operator()
00081 ( const std::vector<color_plane_type>& scanline, image& img,
00082 unsigned int y ) const
00083 {
00084 CLAW_PRECOND( scanline.size() == 4 );
00085
00086 unsigned int x=0;
00087
00088 for ( unsigned int code=0; x!=img.width(); ++code )
00089 {
00090 u_int_8 c0 = scanline[0][code];
00091 u_int_8 c1 = scanline[1][code];
00092 u_int_8 c2 = scanline[2][code];
00093 u_int_8 c3 = scanline[3][code];
00094
00095 for( unsigned int i=0; (i!=8) && (x!=img.width()); ++x, ++i )
00096 {
00097 unsigned int index =
00098 ( (c3 & 0x80) >> 4 )
00099 | ( (c2 & 0x80) >> 5 )
00100 | ( (c1 & 0x80) >> 6 )
00101 | ( (c0 & 0x80) >> 7 );
00102
00103 img[y][x] = m_header.color_map[index];
00104
00105 c0 <<= 1;
00106 c1 <<= 1;
00107 c2 <<= 1;
00108 c3 <<= 1;
00109 }
00110 }
00111 }
00112
00113
00118 claw::graphic::pcx::reader::converter_256::converter_256
00119 ( const color_palette32& palette )
00120 : m_palette(palette)
00121 {
00122
00123 }
00124
00125
00132 void claw::graphic::pcx::reader::converter_256::operator()
00133 ( const std::vector<color_plane_type>& scanline, image& img,
00134 unsigned int y ) const
00135 {
00136 CLAW_PRECOND( scanline.size() == 1 );
00137
00138 for ( unsigned int x=0; x!=img.width(); ++x )
00139 img[y][x] = m_palette[ scanline[0][x] ];
00140 }
00141
00142
00149 void claw::graphic::pcx::reader::converter_true_color::operator()
00150 ( const std::vector<color_plane_type>& scanline, image& img,
00151 unsigned int y ) const
00152 {
00153 CLAW_PRECOND( scanline.size() == 3 );
00154
00155 for ( unsigned int x=0; x!=img.width(); ++x )
00156 {
00157 img[y][x].components.red = scanline[0][x];
00158 img[y][x].components.green = scanline[1][x];
00159 img[y][x].components.blue = scanline[2][x];
00160 img[y][x].components.alpha =
00161 std::numeric_limits<rgba_pixel_8::component_type>::max();
00162 }
00163 }
00164
00165
00166
00167
00168
00174 claw::graphic::pcx::reader::rle_pcx_output_buffer::rle_pcx_output_buffer
00175 ( color_plane_type& result )
00176 : m_result(result), m_position(0)
00177 {
00178
00179 }
00180
00181
00187 void claw::graphic::pcx::reader::rle_pcx_output_buffer::fill
00188 ( unsigned int n, u_int_8 pattern )
00189 {
00190 CLAW_PRECOND( m_position + n <= m_result.size() );
00191
00192 for (unsigned int i=0; i!=n; ++i)
00193 m_result[m_position + i] = pattern;
00194
00195 m_position += n;
00196 }
00197
00198
00204 void claw::graphic::pcx::reader::rle_pcx_output_buffer::copy
00205 ( unsigned int n, rle_pcx_input_buffer& buffer )
00206 {
00207 CLAW_ASSERT( false, "This method should not have been called" );
00208 }
00209
00210
00214 bool claw::graphic::pcx::reader::rle_pcx_output_buffer::completed() const
00215 {
00216 return m_position == m_result.size();
00217 }
00218
00219
00220
00221
00222
00223
00229 void claw::graphic::pcx::reader::rle_pcx_decoder::read_mode
00230 ( rle_pcx_input_buffer& input, rle_pcx_output_buffer& output )
00231 {
00232 this->m_mode = this->stop;
00233 bool ok = !output.completed();
00234
00235 if ( ok && (input.remaining() < 1) )
00236 ok = input.read_more(1);
00237
00238 if (ok)
00239 {
00240 unsigned char key = input.get_next();
00241 this->m_mode = this->compressed;
00242
00243 if ( (key & 0xC0) == 0xC0 )
00244 {
00245 this->m_count = key & 0x3F;
00246
00247 if ( input.remaining() < 1 )
00248 input.read_more(1);
00249
00250 this->m_pattern = input.get_next();
00251 }
00252 else
00253 {
00254 this->m_count = 1;
00255 this->m_pattern = key;
00256 }
00257 }
00258 }
00259
00260
00261
00262
00263
00264
00265
00270 claw::graphic::pcx::reader::reader( image& img )
00271 : m_image( img )
00272 {
00273
00274 }
00275
00276
00283 claw::graphic::pcx::reader::reader( image& img, std::istream& f )
00284 : m_image( img )
00285 {
00286 load(f);
00287 }
00288
00289
00294 void claw::graphic::pcx::reader::load( std::istream& f )
00295 {
00296 CLAW_PRECOND( !!f );
00297 std::istream::pos_type init_pos = f.tellg();
00298
00299 try
00300 {
00301 header h;
00302
00303 f.read( reinterpret_cast<char*>(&h), sizeof(header) );
00304
00305 if ( f.rdstate() == std::ios_base::goodbit )
00306 {
00307 check_if_pcx(h);
00308
00309 m_image.set_size( h.window.x_max - h.window.x_min + 1,
00310 h.window.y_max - h.window.y_min + 1 );
00311
00312 bool supported_format = true;
00313
00314 switch(h.color_planes)
00315 {
00316 case 1:
00317 if (h.bpp == 1)
00318 load_mono(h, f);
00319 else if (h.bpp == 8)
00320 load_256_color_mapped(h, f);
00321 else
00322 supported_format = false;
00323 break;
00324 case 3:
00325 if (h.bpp == 8)
00326 load_true_color(h, f);
00327 else
00328 supported_format = false;
00329 break;
00330 case 4:
00331 if (h.bpp == 1)
00332 load_16_color_mapped(h, f);
00333 else
00334 supported_format = false;
00335 break;
00336 default :
00337 supported_format = false;
00338 }
00339
00340 if ( supported_format == false )
00341 throw claw::bad_format
00342 ( "pcx::reader::pcx: unsupported image type" );
00343 }
00344 else
00345 throw claw::bad_format
00346 ( "claw::pcx::reader::pcx: can't read header" );
00347 }
00348 catch(...)
00349 {
00350 f.clear();
00351 f.seekg( init_pos, std::ios_base::beg );
00352 throw;
00353 }
00354 }
00355
00356
00361 void claw::graphic::pcx::reader::check_if_pcx( const header& h ) const
00362 {
00363 if ( h.manufacturer != 0x0A )
00364 throw CLAW_EXCEPTION( "Not a Pcx file." );
00365 }
00366
00367
00373 void claw::graphic::pcx::reader::load_mono( const header& h, std::istream& f )
00374 {
00375 assert( h.color_planes == 1 );
00376
00377 converter_mono convert;
00378 decompress( h, f, convert );
00379 }
00380
00381
00387 void claw::graphic::pcx::reader::load_16_color_mapped
00388 ( const header& h, std::istream& f )
00389 {
00390 assert( h.color_planes == 4 );
00391
00392 converter_16 convert(h);
00393 decompress( h, f, convert );
00394 }
00395
00396
00402 void
00403 claw::graphic::pcx::reader::load_true_color( const header& h, std::istream& f )
00404 {
00405 assert( h.color_planes == 3 );
00406
00407 converter_true_color convert;
00408 decompress( h, f, convert );
00409 }
00410
00411
00417 void claw::graphic::pcx::reader::load_256_color_mapped
00418 ( const header& h, std::istream& f )
00419 {
00420 assert( h.color_planes == 1 );
00421
00422
00423 const unsigned int palette_length = 256 * 3;
00424
00425 color_palette32 palette(256);
00426 std::istream::pos_type init_pos = f.tellg();
00427
00428
00429 f.seekg( -(std::istream::off_type)palette_length - 1, std::ios_base::end );
00430
00431 char check;
00432 f.read(&check, 1);
00433
00434 if ( check != 12 )
00435 throw CLAW_EXCEPTION( "PCX: The color palette is missing." );
00436
00437 char buffer[palette_length];
00438 f.read(buffer, palette_length);
00439
00440 for (unsigned int i=0, j=0; i!=palette_length; i+=3, ++j)
00441 {
00442 palette[j].components.alpha = 255;
00443 palette[j].components.red = buffer[i];
00444 palette[j].components.green = buffer[i+1];
00445 palette[j].components.blue = buffer[i+2];
00446 }
00447
00448 f.seekg( init_pos );
00449 converter_256 convert(palette);
00450 decompress( h, f, convert );
00451 }
00452
00453
00459 void claw::graphic::pcx::reader::decompress_line
00460 ( std::istream& f, color_plane_type& scanline ) const
00461 {
00462 rle_pcx_input_buffer input(f);
00463 rle_pcx_output_buffer output(scanline);
00464
00465 rle_pcx_decoder decoder;
00466
00467 decoder.decode( input, output );
00468 }