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   unsigned int x=0;
00049 
00050   for ( unsigned int code=0; x!=img.width(); ++code )
00051     {
00052       u_int_8 c = scanline[0][code]; // only one color plane for monochrome pcx
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 } // pcx::reader::converter_mono::operator()()
00061 
00062 /*----------------------------------------------------------------------------*/
00067 claw::graphic::pcx::reader::converter_16::converter_16( const header& h )
00068   : m_header(h)
00069 {
00070 
00071 } // pcx::reader::converter_16::converter_16()
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 } // pcx::reader::converter_16::operator()()
00112 
00113 /*----------------------------------------------------------------------------*/
00118 claw::graphic::pcx::reader::converter_256::converter_256
00119 ( const color_palette32& palette )
00120   : m_palette(palette)
00121 {
00122 
00123 } // pcx::reader::converter_256::converter_256()
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 } // pcx::reader::converter_256::operator()()
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 } // pcx::reader::converter_true_color::operator()()
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 } // pcx::reader::rle_pcx_output_buffer::rle_pcx_output_buffer()
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 } // pcx::reader::rle_pcx_output_buffer::fill()
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 } // pcx::reader::rle_pcx_output_buffer::copy()
00209 
00210 /*----------------------------------------------------------------------------*/
00214 bool claw::graphic::pcx::reader::rle_pcx_output_buffer::completed() const
00215 {
00216   return m_position == m_result.size();
00217 } // pcx::reader::rle_pcx_output_buffer::completed()
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 } // pcx::reader::rle_pcx_decoder::read_mode()
00259 
00260 
00261 
00262 
00263 
00264 
00265 /*----------------------------------------------------------------------------*/
00270 claw::graphic::pcx::reader::reader( image& img )
00271   : m_image( img )
00272 {
00273 
00274 } // pcx::reader::reader()
00275 
00276 /*----------------------------------------------------------------------------*/
00283 claw::graphic::pcx::reader::reader( image& img, std::istream& f )
00284   : m_image( img )
00285 {
00286   load(f);
00287 } // pcx::reader::reader()
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 } // pcx::reader::load()
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 } // pcx::reader::check_if_pcx()
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 } // pcx::reader::load_mono()
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 } // pcx::reader::load_16_color_mapped()
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 } // pcx::reader::load_true_color()
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   // 256 RGB triplets
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   // -1 for the check byte
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 } // pcx::reader::load_256_color_mapped()
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 } // pcx::reader::decompress_line()

Generated on 9 Nov 2009 for CLAW Library (a C++ Library Absolutely Wonderful) by  doxygen 1.6.1