pcx_reader.cpp
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 }