00001
00008 #include "RgbImage.h"
00009
00010 #ifndef RGBIMAGE_DONT_USE_OPENGL
00011 #include <windows.h>
00012 #include "GL/gl.h"
00013 #endif
00014
00019 RgbImage::RgbImage( int numRows, int numCols )
00020 {
00021 NumRows = numRows;
00022 NumCols = numCols;
00023 ImagePtr = new unsigned char[NumRows*GetNumBytesPerRow()];
00024 if ( !ImagePtr ) {
00025 fprintf(stderr, "Unable to allocate memory for %ld x %ld bitmap.\n",
00026 NumRows, NumCols);
00027 Reset();
00028 ErrorCode = MemoryError;
00029 }
00030
00031 unsigned char* c = ImagePtr;
00032 int rowLen = GetNumBytesPerRow();
00033 for ( int i=0; i<NumRows; i++ )
00034 {
00035 for ( int j=0; j<rowLen; j++ )
00036 {
00037 *(c++) = 0;
00038 }
00039 }
00040 }
00041
00042
00043
00044
00045
00046
00047
00048
00054 bool RgbImage::LoadBmpFile( const char* filename )
00055 {
00056 Reset();
00057 FILE* infile = fopen( filename, "rb" );
00058 if ( !infile ) {
00059 fprintf(stderr, "Unable to open file: %s\n", filename);
00060 ErrorCode = OpenError;
00061 return false;
00062 }
00063
00064 bool fileFormatOK = false;
00065 int bChar = fgetc( infile );
00066 int mChar = fgetc( infile );
00067 if ( bChar=='B' && mChar=='M' ) {
00068 skipChars( infile, 4+2+2+4+4 );
00069 NumCols = readLong( infile );
00070 NumRows = readLong( infile );
00071 skipChars( infile, 2 );
00072 int bitsPerPixel = readShort( infile );
00073 skipChars( infile, 4+4+4+4+4+4 );
00074
00075 if ( NumCols>0 && NumCols<=100000 && NumRows>0 && NumRows<=100000
00076 && bitsPerPixel==24 && !feof(infile) ) {
00077 fileFormatOK = true;
00078 }
00079 }
00080 if ( !fileFormatOK ) {
00081 Reset();
00082 ErrorCode = FileFormatError;
00083 fprintf(stderr, "Not a valid 24-bit bitmap file: %s.\n", filename);
00084 fclose ( infile );
00085 return false;
00086 }
00087
00088
00089 ImagePtr = new unsigned char[NumRows*GetNumBytesPerRow()];
00090 if ( !ImagePtr ) {
00091 fprintf(stderr, "Unable to allocate memory for %ld x %ld bitmap: %s.\n",
00092 NumRows, NumCols, filename);
00093 Reset();
00094 ErrorCode = MemoryError;
00095 fclose ( infile );
00096 return false;
00097 }
00098
00099 unsigned char* cPtr = ImagePtr;
00100 for ( int i=0; i<NumRows; i++ ) {
00101 int j;
00102 for ( j=0; j<NumCols; j++ ) {
00103 *(cPtr+2) = fgetc( infile );
00104 *(cPtr+1) = fgetc( infile );
00105 *cPtr = fgetc( infile );
00106 cPtr += 3;
00107 }
00108 int k=3*NumCols;
00109 for ( ; k<GetNumBytesPerRow(); k++ ) {
00110 fgetc( infile );
00111 *(cPtr++) = 0;
00112 }
00113 }
00114 if ( feof( infile ) ) {
00115 fprintf( stderr, "Premature end of file: %s.\n", filename );
00116 Reset();
00117 ErrorCode = ReadError;
00118 fclose ( infile );
00119 return false;
00120 }
00121 fclose( infile );
00122 return true;
00123 }
00128 short RgbImage::readShort( FILE* infile )
00129 {
00130
00131 unsigned char lowByte, hiByte;
00132 lowByte = fgetc(infile);
00133 hiByte = fgetc(infile);
00134
00135
00136 short ret = hiByte;
00137 ret <<= 8;
00138 ret |= lowByte;
00139 return ret;
00140 }
00145 long RgbImage::readLong( FILE* infile )
00146 {
00147
00148 unsigned char byte0, byte1, byte2, byte3;
00149 byte0 = fgetc(infile);
00150 byte1 = fgetc(infile);
00151 byte2 = fgetc(infile);
00152 byte3 = fgetc(infile);
00153
00154
00155 long ret = byte3;
00156 ret <<= 8;
00157 ret |= byte2;
00158 ret <<= 8;
00159 ret |= byte1;
00160 ret <<= 8;
00161 ret |= byte0;
00162 return ret;
00163 }
00168 void RgbImage::skipChars( FILE* infile, int numChars )
00169 {
00170 for ( int i=0; i<numChars; i++ ) {
00171 fgetc( infile );
00172 }
00173 }
00174
00175
00176
00177
00178
00179
00180
00181
00187 bool RgbImage::WriteBmpFile( const char* filename )
00188 {
00189 FILE* outfile = fopen( filename, "wb" );
00190 if ( !outfile ) {
00191 fprintf(stderr, "Unable to open file: %s\n", filename);
00192 ErrorCode = OpenError;
00193 return false;
00194 }
00195
00196 fputc('B',outfile);
00197 fputc('M',outfile);
00198 int rowLen = GetNumBytesPerRow();
00199 writeLong( 40+14+NumRows*rowLen, outfile );
00200 writeShort( 0, outfile );
00201 writeShort( 0, outfile );
00202 writeLong( 40+14, outfile );
00203 writeLong( 40, outfile );
00204 writeLong( NumCols, outfile );
00205 writeLong( NumRows, outfile );
00206 writeShort( 1, outfile );
00207 writeShort( 24, outfile );
00208 writeLong( 0, outfile );
00209 writeLong( 0, outfile );
00210 writeLong( 0, outfile );
00211 writeLong( 0, outfile );
00212 writeLong( 0, outfile );
00213 writeLong( 0, outfile );
00214
00215
00216 unsigned char* cPtr = ImagePtr;
00217 for ( int i=0; i<NumRows; i++ ) {
00218
00219 int j;
00220 for ( j=0; j<NumCols; j++ ) {
00221 fputc( *(cPtr+2), outfile);
00222 fputc( *(cPtr+1), outfile);
00223 fputc( *(cPtr+0), outfile);
00224 cPtr+=3;
00225 }
00226
00227 int k=3*NumCols;
00228 for ( ; k<GetNumBytesPerRow(); k++ ) {
00229 fputc( 0, outfile );
00230 cPtr++;
00231 }
00232 }
00233
00234 fclose( outfile );
00235 return true;
00236 }
00241 void RgbImage::writeLong( long data, FILE* outfile )
00242 {
00243
00244 unsigned char byte0, byte1, byte2, byte3;
00245 byte0 = (unsigned char)(data&0x000000ff);
00246 byte1 = (unsigned char)((data>>8)&0x000000ff);
00247 byte2 = (unsigned char)((data>>16)&0x000000ff);
00248 byte3 = (unsigned char)((data>>24)&0x000000ff);
00249
00250 fputc( byte0, outfile );
00251 fputc( byte1, outfile );
00252 fputc( byte2, outfile );
00253 fputc( byte3, outfile );
00254 }
00259 void RgbImage::writeShort( short data, FILE* outfile )
00260 {
00261
00262 unsigned char byte0, byte1;
00263 byte0 = data&0x000000ff;
00264 byte1 = (data>>8)&0x000000ff;
00265
00266 fputc( byte0, outfile );
00267 fputc( byte1, outfile );
00268 }
00269
00270
00271
00272
00273
00281 void RgbImage::SetRgbPixelf( long row, long col, double red, double green, double blue )
00282 {
00283 SetRgbPixelc( row, col, doubleToUnsignedChar(red),
00284 doubleToUnsignedChar(green),
00285 doubleToUnsignedChar(blue) );
00286 }
00294 void RgbImage::SetRgbPixelc( long row, long col,
00295 unsigned char red, unsigned char green, unsigned char blue )
00296 {
00297 assert ( row<NumRows && col<NumCols );
00298 unsigned char* thePixel = GetRgbPixel( row, col );
00299 *(thePixel++) = red;
00300 *(thePixel++) = green;
00301 *(thePixel) = blue;
00302 }
00303
00309 unsigned char RgbImage::doubleToUnsignedChar( double x )
00310 {
00311 if ( x>=1.0 ) {
00312 return (unsigned char)255;
00313 }
00314 else if ( x<=0.0 ) {
00315 return (unsigned char)0;
00316 }
00317 else {
00318 return (unsigned char)(x*255.0);
00319 }
00320 }
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344 #ifndef RGBIMAGE_DONT_USE_OPENGL
00345
00347 bool RgbImage::LoadFromOpenglBuffer()
00348 {
00349 int viewportData[4];
00350 glGetIntegerv( GL_VIEWPORT, viewportData );
00351 int& vWidth = viewportData[2];
00352 int& vHeight = viewportData[3];
00353
00354 if ( ImagePtr==0 ) {
00355 NumRows = vHeight;
00356 NumCols = vWidth;
00357 ImagePtr = new unsigned char[NumRows*GetNumBytesPerRow()];
00358 if ( !ImagePtr ) {
00359 fprintf(stderr, "Unable to allocate memory for %ld x %ld buffer.\n",
00360 NumRows, NumCols);
00361 Reset();
00362 ErrorCode = MemoryError;
00363 return false;
00364 }
00365 }
00366 assert ( vWidth>=NumCols && vHeight>=NumRows );
00367 int oldGlRowLen;
00368 if ( vWidth>=NumCols ) {
00369 glGetIntegerv( GL_UNPACK_ROW_LENGTH, &oldGlRowLen );
00370 glPixelStorei( GL_UNPACK_ROW_LENGTH, NumCols );
00371 }
00372 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
00373
00374
00375 glReadPixels( 0, 0, NumCols, NumRows, GL_RGB, GL_UNSIGNED_BYTE, ImagePtr);
00376
00377
00378 if ( vWidth>=NumCols ) {
00379 glPixelStorei( GL_UNPACK_ROW_LENGTH, oldGlRowLen );
00380 }
00381 return true;
00382 }
00383
00384 #endif // RGBIMAGE_DONT_USE_OPENGL