pcx_reader.cpp

Go to the documentation of this file.
00001 /*
00002   CLAW - a C++ Library Absolutely Wonderful
00003 
00004   CLAW is a free library without any particular aim but being useful to 
00005   anyone.
00006 
00007   Copyright (C) 2005-2008 Julien Jorge
00008 
00009   This library is free software; you can redistribute it and/or
00010   modify it under the terms of the GNU Lesser General Public
00011   License as published by the Free Software Foundation; either
00012   version 2.1 of the License, or (at your option) any later version.
00013 
00014   This library is distributed in the hope that it will be useful,
00015   but WITHOUT ANY WARRANTY; without even the implied warranty of
00016   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017   Lesser General Public License for more details.
00018 
00019   You should have received a copy of the GNU Lesser General Public
00020   License along with this library; if not, write to the Free Software
00021   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00022 
00023   contact: julien_jorge@yahoo.fr
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   const pixel32 white(255, 255, 255, 255);
00049   const pixel32 black(0, 0, 0, 255);
00050 
00051   unsigned int x=0;
00052 
00053   for ( unsigned int code=0; x!=img.width(); ++code )
00054     {
00055       u_int_8 c = scanline[0][code]; // only one color plane for monochrome pcx
00056 
00057       for( unsigned int i=0; (i!=8) && (x!=img.width()); ++x, ++i, c<<=1 )
00058         if ( c & 0x80 )
00059           img[y][x] = white;
00060         else
00061           img[y][x] = black;
00062     }
00063 } // pcx::reader::converter_mono::operator()()
00064 
00065 /*----------------------------------------------------------------------------*/
00070 claw::graphic::pcx::reader::converter_16::converter_16( const header& h )
00071   : m_header(h)
00072 {
00073 
00074 } // pcx::reader::converter_16::converter_16()
00075 
00076 /*----------------------------------------------------------------------------*/
00083 void claw::graphic::pcx::reader::converter_16::operator()
00084 ( const std::vector<color_plane_type>& scanline, image& img,
00085   unsigned int y ) const
00086 {
00087   CLAW_PRECOND( scanline.size() == 4 );
00088 
00089   unsigned int x=0;
00090 
00091   for ( unsigned int code=0; x!=img.width(); ++code )
00092     {
00093       u_int_8 c0 = scanline[0][code];
00094       u_int_8 c1 = scanline[1][code];
00095       u_int_8 c2 = scanline[2][code];
00096       u_int_8 c3 = scanline[3][code];
00097 
00098       for( unsigned int i=0; (i!=8) && (x!=img.width()); ++x, ++i )
00099         {
00100           unsigned int index =
00101             ( (c3 & 0x80) >> 4 )
00102             | ( (c2 & 0x80) >> 5 )
00103             | ( (c1 & 0x80) >> 6 )
00104             | ( (c0 & 0x80) >> 7 );
00105 
00106           img[y][x] = m_header.color_map[index];
00107 
00108           c0 <<= 1;
00109           c1 <<= 1;
00110           c2 <<= 1;
00111           c3 <<= 1;
00112         }
00113     }
00114 } // pcx::reader::converter_16::operator()()
00115 
00116 /*----------------------------------------------------------------------------*/
00121 claw::graphic::pcx::reader::converter_256::converter_256
00122 ( const color_palette32& palette )
00123   : m_palette(palette)
00124 {
00125 
00126 } // pcx::reader::converter_256::converter_256()
00127 
00128 /*----------------------------------------------------------------------------*/
00135 void claw::graphic::pcx::reader::converter_256::operator()
00136 ( const std::vector<color_plane_type>& scanline, image& img,
00137   unsigned int y ) const
00138 {
00139   CLAW_PRECOND( scanline.size() == 1 );
00140 
00141   for ( unsigned int x=0; x!=img.width(); ++x )
00142     img[y][x] = m_palette[ scanline[0][x] ];
00143 } // pcx::reader::converter_256::operator()()
00144 
00145 /*----------------------------------------------------------------------------*/
00152 void claw::graphic::pcx::reader::converter_true_color::operator()
00153 ( const std::vector<color_plane_type>& scanline, image& img,
00154   unsigned int y ) const
00155 {
00156   CLAW_PRECOND( scanline.size() == 3 );
00157 
00158   for ( unsigned int x=0; x!=img.width(); ++x )
00159     {
00160       img[y][x].components.red = scanline[0][x];
00161       img[y][x].components.green = scanline[1][x];
00162       img[y][x].components.blue = scanline[2][x];
00163       img[y][x].components.alpha =
00164         std::numeric_limits<pixel32::component_type>::max();
00165     }
00166 } // pcx::reader::converter_true_color::operator()()
00167 
00168 
00169 
00170 
00171 /*----------------------------------------------------------------------------*/
00177 claw::graphic::pcx::reader::rle_pcx_output_buffer::rle_pcx_output_buffer
00178 ( color_plane_type& result )
00179   : m_result(result), m_position(0)
00180 {
00181 
00182 } // pcx::reader::rle_pcx_output_buffer::rle_pcx_output_buffer()
00183 
00184 /*----------------------------------------------------------------------------*/
00190 void claw::graphic::pcx::reader::rle_pcx_output_buffer::fill
00191 ( unsigned int n, u_int_8 pattern )
00192 {
00193   CLAW_PRECOND( m_position + n <= m_result.size() );
00194 
00195   for (unsigned int i=0; i!=n; ++i)
00196     m_result[m_position + i] = pattern;
00197 
00198   m_position += n;
00199 } // pcx::reader::rle_pcx_output_buffer::fill()
00200 
00201 /*----------------------------------------------------------------------------*/
00207 void claw::graphic::pcx::reader::rle_pcx_output_buffer::copy
00208 ( unsigned int n, rle_pcx_input_buffer& buffer )
00209 {
00210   CLAW_ASSERT( false, "This method should not have been called" );
00211 } // pcx::reader::rle_pcx_output_buffer::copy()
00212 
00213 /*----------------------------------------------------------------------------*/
00217 bool claw::graphic::pcx::reader::rle_pcx_output_buffer::completed() const
00218 {
00219   return m_position == m_result.size();
00220 } // pcx::reader::rle_pcx_output_buffer::completed()
00221 
00222 
00223 
00224 
00225 
00226 /*----------------------------------------------------------------------------*/
00232 void claw::graphic::pcx::reader::rle_pcx_decoder::read_mode
00233 ( rle_pcx_input_buffer& input, rle_pcx_output_buffer& output )
00234 {
00235   this->m_mode = this->stop;
00236   bool ok = !output.completed();
00237 
00238   if ( ok && (input.remaining() < 1) )
00239     ok = input.read_more(1);
00240 
00241   if (ok)
00242     {
00243       unsigned char key = input.get_next();
00244       this->m_mode = this->compressed;
00245       
00246       if ( (key & 0xC0) == 0xC0 )
00247         {
00248           this->m_count = key & 0x3F;
00249 
00250           if ( input.remaining() < 1 )
00251             input.read_more(1);
00252 
00253           this->m_pattern = input.get_next();
00254         }
00255       else
00256         {
00257           this->m_count = 1;
00258           this->m_pattern = key;
00259         }
00260     }
00261 } // pcx::reader::rle_pcx_decoder::read_mode()
00262 
00263 
00264 
00265 
00266 
00267 
00268 /*----------------------------------------------------------------------------*/
00273 claw::graphic::pcx::reader::reader( image& img )
00274   : m_image( img )
00275 {
00276 
00277 } // pcx::reader::reader()
00278 
00279 /*----------------------------------------------------------------------------*/
00286 claw::graphic::pcx::reader::reader( image& img, std::istream& f )
00287   : m_image( img )
00288 {
00289   load(f);
00290 } // pcx::reader::reader()
00291 
00292 /*----------------------------------------------------------------------------*/
00297 void claw::graphic::pcx::reader::load( std::istream& f )
00298 {
00299   CLAW_PRECOND( !!f );
00300   std::istream::pos_type init_pos = f.tellg();
00301 
00302   try
00303     {
00304       header h;
00305 
00306       f.read( reinterpret_cast<char*>(&h), sizeof(header) );
00307       
00308       if ( f.rdstate() == std::ios_base::goodbit )
00309         {
00310           check_if_pcx(h);
00311 
00312           m_image.set_size( h.window.x_max - h.window.x_min + 1,
00313                             h.window.y_max - h.window.y_min + 1 );
00314 
00315           bool supported_format = true;
00316 
00317           switch(h.color_planes)
00318             {
00319             case 1:
00320               if (h.bpp == 1)
00321                 load_mono(h, f);
00322               else if (h.bpp == 8)
00323                 load_256_color_mapped(h, f);
00324               else
00325                 supported_format = false;
00326               break;
00327             case 3:
00328               if (h.bpp == 8)
00329                 load_true_color(h, f);
00330               else
00331                 supported_format = false;
00332               break;
00333             case 4:
00334               if (h.bpp == 1)
00335                 load_16_color_mapped(h, f);
00336               else
00337                 supported_format = false;
00338               break;
00339             default :
00340               supported_format = false;
00341             }
00342 
00343           if ( supported_format == false )
00344             throw claw::bad_format
00345               ( "pcx::reader::pcx: unsupported image type" );
00346         }
00347       else
00348         throw claw::bad_format
00349           ( "claw::pcx::reader::pcx: can't read header" );
00350     }
00351   catch(...)
00352     {
00353       f.clear();
00354       f.seekg( init_pos, std::ios_base::beg );
00355       throw;
00356     }
00357 } // pcx::reader::load()
00358 
00359 /*----------------------------------------------------------------------------*/
00364 void claw::graphic::pcx::reader::check_if_pcx( const header& h ) const
00365 {
00366   if ( h.manufacturer != 0x0A )
00367     throw CLAW_EXCEPTION( "Not a Pcx file." );
00368 } // pcx::reader::check_if_pcx()
00369 
00370 /*----------------------------------------------------------------------------*/
00376 void claw::graphic::pcx::reader::load_mono( const header& h, std::istream& f )
00377 {
00378   assert( h.color_planes == 1 );
00379 
00380   converter_mono convert;
00381   decompress( h, f, convert );
00382 } // pcx::reader::load_mono()
00383 
00384 /*----------------------------------------------------------------------------*/
00390 void claw::graphic::pcx::reader::load_16_color_mapped
00391 ( const header& h, std::istream& f )
00392 {
00393   assert( h.color_planes == 4 );
00394 
00395   converter_16 convert(h);
00396   decompress( h, f, convert );
00397 } // pcx::reader::load_16_color_mapped()
00398 
00399 /*----------------------------------------------------------------------------*/
00405 void
00406 claw::graphic::pcx::reader::load_true_color( const header& h, std::istream& f )
00407 {
00408   assert( h.color_planes == 3 );
00409 
00410   converter_true_color convert;
00411   decompress( h, f, convert );
00412 } // pcx::reader::load_true_color()
00413 
00414 /*----------------------------------------------------------------------------*/
00420 void claw::graphic::pcx::reader::load_256_color_mapped
00421 ( const header& h, std::istream& f )
00422 {
00423   assert( h.color_planes == 1 );
00424 
00425   // 256 RGB triplets
00426   const unsigned int palette_length = 256 * 3;
00427 
00428   color_palette32 palette(256);
00429   std::istream::pos_type init_pos = f.tellg();
00430 
00431   // -1 for the check byte
00432   f.seekg( -(std::istream::off_type)palette_length - 1, std::ios_base::end ); 
00433 
00434   char check;
00435   f.read(&check, 1);
00436   
00437   if ( check != 12 )
00438     throw CLAW_EXCEPTION( "PCX: The color palette is missing." );
00439 
00440   char buffer[palette_length];
00441   f.read(buffer, palette_length);
00442 
00443   for (unsigned int i=0, j=0; i!=palette_length; i+=3, ++j)
00444     {
00445       palette[j].components.alpha = 255;
00446       palette[j].components.red   = buffer[i];
00447       palette[j].components.green = buffer[i+1];
00448       palette[j].components.blue  = buffer[i+2];
00449     }
00450 
00451   f.seekg( init_pos );
00452   converter_256 convert(palette);
00453   decompress( h, f, convert );
00454 } // pcx::reader::load_256_color_mapped()
00455 
00456 /*----------------------------------------------------------------------------*/
00462 void claw::graphic::pcx::reader::decompress_line
00463 ( std::istream& f, color_plane_type& scanline ) const
00464 {
00465   rle_pcx_input_buffer input(f);
00466   rle_pcx_output_buffer output(scanline);
00467 
00468   rle_pcx_decoder decoder;
00469 
00470   decoder.decode( input, output );
00471 } // pcx::reader::decompress_line()

Generated on Thu Jun 26 09:35:04 2008 for CLAW Library (a C++ Library Absolutely Wonderful) by  doxygen 1.5.6