Main Page   Class Hierarchy   Compound List   File List   Compound Members  

gfxImageReaderPNM.cpp

00001 //////////////////////////////////////////////////////////////////////
00002 // Copyright (c) 2001-2003 David Pritchard <drpritch@alumni.uwaterloo.ca>
00003 // 
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public License
00006 // as published by the Free Software Foundation; either
00007 // version 2 of the License, or (at your option) any later
00008 // version.
00009 // 
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU Lesser General Public License for more details.
00014 // 
00015 // You should have received a copy of the GNU Lesser General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018 
00019 #include <freecloth/gfx/gfxImageReaderPNM.h>
00020 #include <freecloth/gfx/gfxImage.h>
00021 #include <freecloth/resmgt/rcShdPtr.h>
00022 #include <freecloth/base/fstream>
00023 #include <freecloth/base/ctype.h>
00024 #include <freecloth/base/limits.h>
00025 
00026 
00027 ////////////////////////////////////////////////////////////////////////////////
00028 // LOCAL DECLARATIONS
00029 
00030 namespace {
00031 
00032 //------------------------------------------------------------------------------
00033 
00034 void stripSpaceComments( std::istream& in )
00035 {
00036     while( 1 ) {
00037         while ( isspace( in.peek() ) ) in.get();
00038         if (in.peek() == '#') {
00039             in.ignore( INT_MAX, '\n' );
00040         }
00041         else {
00042             return;
00043         }
00044     }
00045 }
00046 
00047 }
00048 
00049 ////////////////////////////////////////////////////////////////////////////////
00050 // CLASS GfxImageReaderPNM
00051 
00052 //------------------------------------------------------------------------------
00053 
00054 bool GfxImageReaderPNM::canRead( const String& path )
00055 {
00056     // Note that string comparison is case-sensitive.
00057     //
00058     // Also note that string::compare w/ 3 args is not implemented in a standard
00059     // manner in gcc 3.0 right now. gcc 2.95 complies to standard.
00060     // (why...???)
00061     return
00062         path.length() >= 4 &&
00063         ( path.substr( path.length() - 4, 4 ).compare( ".ppm" ) == 0 ||
00064           path.substr( path.length() - 4, 4 ).compare( ".pgm" ) == 0 ||
00065           path.substr( path.length() - 4, 4 ).compare( ".pnm" ) == 0);
00066 }
00067 
00068 //------------------------------------------------------------------------------
00069 
00070 GfxImageReaderPNM::GfxImageReaderPNM( const String& path )
00071     : _path( path )
00072 {
00073 }
00074 
00075 //------------------------------------------------------------------------------
00076 
00077 GfxImageReader::ImagePtr GfxImageReaderPNM::readImage() const
00078 {
00079     DGFX_TRACE_ENTER( "GfxImageReaderPNM::readImage()" );
00080     DGFX_TRACE( "path = " << _path );
00081 
00082     if ( _path == "-" ) {
00083         return readImage( std::cin );
00084     }
00085     else {
00086         // FIXME: non-portable: need some way of switching ascii/binary for
00087         // binary files under Win32
00088         std::ifstream in( _path.c_str() );
00089         if ( in.good() ) {
00090             return readImage( in );
00091         }
00092         else {
00093             return ImagePtr();
00094         }
00095     }
00096 }
00097 
00098 //------------------------------------------------------------------------------
00099 
00100 GfxImageReader::ImagePtr GfxImageReaderPNM::readImage(
00101     std::istream& in
00102 ) const {
00103     stripSpaceComments( in );
00104     char c;
00105     c = in.get();
00106     DGFX_ASSERT( c == 'P' );
00107 
00108     char type;
00109     UInt32 width, height, maxCol;
00110 
00111     type = in.get();
00112     stripSpaceComments( in );
00113     in >> width;
00114     stripSpaceComments( in );
00115     in >> height;
00116     if ( type == '4' ) {
00117         maxCol = 1;
00118     }
00119     else {
00120         stripSpaceComments( in );
00121         in >> maxCol;
00122         DGFX_ASSERT( maxCol == 0xff || maxCol == 0xffff );
00123     }
00124 
00125     bool isBinary = false;
00126     GfxImage::Format format = GfxImage::GREY8;
00127 
00128     switch ( type ) {
00129         case '2': {
00130             isBinary = false;
00131             format = GfxImage::GREY8;
00132             DGFX_ASSERT( maxCol == 0xff );
00133         } break;
00134 
00135         case '3': {
00136             isBinary = false;
00137             format = GfxImage::RGB24;
00138             DGFX_ASSERT( maxCol == 0xff );
00139         } break;
00140 
00141         case '4': {
00142             isBinary = true;
00143             // No 1-bit format yet
00144             format = GfxImage::GREY8;
00145             DGFX_ASSERT( maxCol == 1 );
00146         } break;
00147 
00148         case '5': {
00149             isBinary = true;
00150             format = GfxImage::GREY8;
00151             DGFX_ASSERT( maxCol == 0xff );
00152         } break;
00153 
00154         case '6': {
00155             isBinary = true;
00156             format = GfxImage::RGB24;
00157             DGFX_ASSERT( maxCol == 0xff );
00158         } break;
00159 
00160         default: {
00161             DGFX_ASSERT( 0 );
00162         } break;
00163     }
00164     c = in.get();
00165     DGFX_ASSERT( isspace( c ) );
00166 
00167     ImagePtr image( new GfxImage( width, height, format ) );
00168     UInt32 i,j;
00169     UInt32 bits = maxCol == 1 ? 1 : image->getBitsPerComponent();
00170     switch ( bits ) {
00171         case 1: {
00172             DGFX_ASSERT( isBinary );
00173             UInt8* data = image->getRawData();
00174             for ( j = 0; j < height; ++j ) {
00175                 for ( i = 0; i < width; ) {
00176                     UInt8 val = in.get();
00177                     for ( UInt8 k = 0x80; k > 0 && i < width; k >>= 1,++i) {
00178                         *data = (val & k) == 0 ? 255 : 0;
00179                         ++data;
00180                     }
00181                 }
00182             }
00183         } break;
00184 
00185         case 8: {
00186             if ( isBinary ) {
00187                 in.read(
00188                     reinterpret_cast<char*>( image->getRawData() ),
00189                     image->getRawSize()
00190                 );
00191             }
00192             else {
00193                 UInt32 val;
00194                 UInt8* data = image->getRawData();
00195                 for ( i = 0; i < image->getRawSize(); ++i ) {
00196                     in >> val;
00197                     *data = val;
00198                     ++data;
00199                 }
00200             }
00201         } break;
00202 
00203         default: {
00204             DGFX_ASSERT( 0 );
00205         } break;
00206     }
00207     return image;
00208 }

Generated on Wed Apr 23 15:58:52 2003 for Freecloth by doxygen1.3-rc3