00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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
00051
00052
00053
00054 bool GfxImageReaderPNM::canRead( const String& path )
00055 {
00056
00057
00058
00059
00060
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
00087
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
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 }