Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

TGALoader.cpp

Go to the documentation of this file.
00001 
00006 #include "TGALoader.h"
00007 /*
00008 * This file came from Alex Klaminsky it has been changed to 
00009 * fit into this implementation.
00010 */
00011 
00012 using namespace ParticleSystems;
00013 
00014 TGALoader::TGALoader() {
00015     for(int i = 0; i < 12; i++) {
00016         if(i == 2) {
00017             uTGAcompare[i] = 2;
00018             cTGAcompare[i] = 10;
00019         } else {
00020             uTGAcompare[i] = 0;
00021             cTGAcompare[i] = 0;
00022         }
00023     }
00024 }
00025 
00026 TGALoader::~TGALoader() {
00027 }
00028 
00029 bool TGALoader::LoadTGA(Texture * texture, char * filename)                             // Load a TGA file
00030 {
00031         FILE * fTGA;                                                                                            // File pointer to texture file
00032         fTGA = fopen(filename, "rb");                                                           // Open file for reading
00033 
00034         if(fTGA == NULL)                                                                                        // If it didn't open....
00035         {
00036                 //MessageBox(NULL, "Could not open texture file", "ERROR", MB_OK);      // Display an error message
00037                 return false;                                                                                                           // Exit function
00038         }
00039 
00040         if(fread(&tgaheader, sizeof(TGAHeader), 1, fTGA) == 0)                                  // Attempt to read 12 byte header from file
00041         {
00042                 //MessageBox(NULL, "Could not read file header", "ERROR", MB_OK);               // If it fails, display an error message 
00043                 if(fTGA != NULL)                                                                                                        // Check to seeiffile is still open
00044                 {
00045                         fclose(fTGA);                                                                                                   // If it is, close it
00046                 }
00047                 return false;                                                                                                           // Exit function
00048         }
00049 
00050         if(memcmp(uTGAcompare, &tgaheader, sizeof(tgaheader)) == 0)                             // See if header matches the predefined header of
00051         {                                                                                                                                               // an Uncompressed TGA image
00052                 LoadUncompressedTGA(texture, filename, fTGA);                                           // If so, jump to Uncompressed TGA loading code
00053         }
00054         else if(memcmp(cTGAcompare, &tgaheader, sizeof(tgaheader)) == 0)                // See if header matches the predefined header of
00055         {                                                                                                                                               // an RLE compressed TGA image
00056                 LoadCompressedTGA(texture, filename, fTGA);                                                     // If so, jump to Compressed TGA loading code
00057         }
00058         else                                                                                                                                    // If header matches neither type
00059         {
00060                 //MessageBox(NULL, "TGA file be type 2 or type 10 ", "Invalid Image", MB_OK);   // Display an error
00061                 fclose(fTGA);
00062                 return false;                                                                                                                           // Exit function
00063         }
00064         return true;                                                                                                                    // All went well, continue on
00065 }
00066 
00067 bool TGALoader::LoadUncompressedTGA(Texture * texture, char * filename, FILE * fTGA)    // Load an uncompressed TGA (note, much of this code is based on NeHe's
00068 {                                                                                                                                                       // TGA Loading code nehe.gamedev.net)
00069         if(fread(tga.header, sizeof(tga.header), 1, fTGA) == 0)                                 // Read TGA header
00070         {                                                                               
00071                 //MessageBox(NULL, "Could not read info header", "ERROR", MB_OK);               // Display error
00072                 if(fTGA != NULL)                                                                                                        // if file is still open
00073                 {
00074                         fclose(fTGA);                                                                                                   // Close it
00075                 }
00076                 return false;                                                                                                           // Return failular
00077         }       
00078 
00079         texture->width  = tga.header[1] * 256 + tga.header[0];                                  // Determine The TGA Width      (highbyte*256+lowbyte)
00080         texture->height = tga.header[3] * 256 + tga.header[2];                                  // Determine The TGA Height     (highbyte*256+lowbyte)
00081         texture->bpp    = tga.header[4];                                                                                // Determine the bits per pixel
00082         tga.Width               = texture->width;                                                                               // Copy width into local structure                                              
00083         tga.Height              = texture->height;                                                                              // Copy height into local structure
00084         tga.Bpp                 = texture->bpp;                                                                                 // Copy BPP into local structure
00085 
00086         if((texture->width <= 0) || (texture->height <= 0) || ((texture->bpp != 24) && (texture->bpp !=32)))    // Make sure all information is valid
00087         {
00088                 //MessageBox(NULL, "Invalid texture information", "ERROR", MB_OK);      // Display Error
00089                 if(fTGA != NULL)                                                                                                        // Check if file is still open
00090                 {
00091                         fclose(fTGA);                                                                                                   // If so, close it
00092                 }
00093                 return false;                                                                                                           // Return failed
00094         }
00095 
00096         if(texture->bpp == 24)                                                                                                  //If the BPP of the image is 24...
00097         {
00098                 texture->type   = GL_RGB;                                                                                       // Set Image type to GL_RGB
00099         }
00100         else                                                                                                                                    // Else if its 32 BPP
00101         {
00102                 texture->type   = GL_RGBA;                                                                                      // Set image type to GL_RGBA
00103         }
00104 
00105         tga.bytesPerPixel       = (tga.Bpp / 8);                                                                        // Compute the number of BYTES per pixel
00106         tga.imageSize           = (tga.bytesPerPixel * tga.Width * tga.Height);         // Compute the total amout ofmemory needed to store data
00107         texture->imageData      = (GLubyte *)malloc(tga.imageSize);                                     // Allocate that much memory
00108 
00109         if(texture->imageData == NULL)                                                                                  // If no space was allocated
00110         {
00111                 //MessageBox(NULL, "Could not allocate memory for image", "ERROR", MB_OK);      // Display Error
00112                 fclose(fTGA);                                                                                                           // Close the file
00113                 return false;                                                                                                           // Return failed
00114         }
00115 
00116         if(fread(texture->imageData, 1, tga.imageSize, fTGA) != tga.imageSize)  // Attempt to read image data
00117         {
00118                 //MessageBox(NULL, "Could not read image data", "ERROR", MB_OK);                // Display Error
00119                 if(texture->imageData != NULL)                                                                          // If imagedata has data in it
00120                 {
00121                         free(texture->imageData);                                                                               // Delete data from memory
00122                 }
00123                 fclose(fTGA);                                                                                                           // Close file
00124                 return false;                                                                                                           // Return failed
00125         }
00126 
00127         // Byte Swapping Optimized By Steve Thomas
00128         for(GLuint cswap = 0; cswap < (int)tga.imageSize; cswap += tga.bytesPerPixel)
00129         {
00130                 texture->imageData[cswap] ^= texture->imageData[cswap+2] ^=
00131                 texture->imageData[cswap] ^= texture->imageData[cswap+2];
00132         }
00133 
00134         fclose(fTGA);                                                                                                                   // Close file
00135         return true;                                                                                                                    // Return success
00136 }
00137 
00138 bool TGALoader::LoadCompressedTGA(Texture * texture, char * filename, FILE * fTGA)              // Load COMPRESSED TGAs
00139 { 
00140         if(fread(tga.header, sizeof(tga.header), 1, fTGA) == 0)                                 // Attempt to read header
00141         {
00142                 //MessageBox(NULL, "Could not read info header", "ERROR", MB_OK);               // Display Error
00143                 if(fTGA != NULL)                                                                                                        // If file is open
00144                 {
00145                         fclose(fTGA);                                                                                                   // Close it
00146                 }
00147                 return false;                                                                                                           // Return failed
00148         }
00149 
00150         texture->width  = tga.header[1] * 256 + tga.header[0];                                  // Determine The TGA Width      (highbyte*256+lowbyte)
00151         texture->height = tga.header[3] * 256 + tga.header[2];                                  // Determine The TGA Height     (highbyte*256+lowbyte)
00152         texture->bpp    = tga.header[4];                                                                                // Determine Bits Per Pixel
00153         tga.Width               = texture->width;                                                                               // Copy width to local structure
00154         tga.Height              = texture->height;                                                                              // Copy width to local structure
00155         tga.Bpp                 = texture->bpp;                                                                                 // Copy width to local structure
00156 
00157         if((texture->width <= 0) || (texture->height <= 0) || ((texture->bpp != 24) && (texture->bpp !=32)))    //Make sure all texture info is ok
00158         {
00159                 //MessageBox(NULL, "Invalid texture information", "ERROR", MB_OK);      // If it isnt...Display error
00160                 if(fTGA != NULL)                                                                                                        // Check if file is open
00161                 {
00162                         fclose(fTGA);                                                                                                   // Ifit is, close it
00163                 }
00164                 return false;                                                                                                           // Return failed
00165         }
00166 
00167         tga.bytesPerPixel       = (tga.Bpp / 8);                                                                        // Compute BYTES per pixel
00168         tga.imageSize           = (tga.bytesPerPixel * tga.Width * tga.Height);         // Compute amout of memory needed to store image
00169         texture->imageData      = (GLubyte *)malloc(tga.imageSize);                                     // Allocate that much memory
00170 
00171         if(texture->imageData == NULL)                                                                                  // If it wasnt allocated correctly..
00172         {
00173                 //MessageBox(NULL, "Could not allocate memory for image", "ERROR", MB_OK);      // Display Error
00174                 fclose(fTGA);                                                                                                           // Close file
00175                 return false;                                                                                                           // Return failed
00176         }
00177 
00178         GLuint pixelcount       = tga.Height * tga.Width;                                                       // Nuber of pixels in the image
00179         GLuint currentpixel     = 0;                                                                                            // Current pixel being read
00180         GLuint currentbyte      = 0;                                                                                            // Current byte 
00181         GLubyte * colorbuffer = (GLubyte *)malloc(tga.bytesPerPixel);                   // Storage for 1 pixel
00182 
00183         do
00184         {
00185                 GLubyte chunkheader = 0;                                                                                        // Storage for "chunk" header
00186 
00187                 if(fread(&chunkheader, sizeof(GLubyte), 1, fTGA) == 0)                          // Read in the 1 byte header
00188                 {
00189                         //MessageBox(NULL, "Could not read RLE header", "ERROR", MB_OK);        // Display Error
00190                         if(fTGA != NULL)                                                                                                // If file is open
00191                         {
00192                                 fclose(fTGA);                                                                                           // Close file
00193                         }
00194                         if(texture->imageData != NULL)                                                                  // If there is stored image data
00195                         {
00196                                 free(texture->imageData);                                                                       // Delete image data
00197                         }
00198                         return false;                                                                                                   // Return failed
00199                 }
00200 
00201                 if(chunkheader < 128)                                                                                           // If the ehader is < 128, it means the that is the number of RAW color packets minus 1
00202                 {                                                                                                                                       // that follow the header
00203                         chunkheader++;                                                                                                  // add 1 to get number of following color values
00204                         for(short counter = 0; counter < chunkheader; counter++)                // Read RAW color values
00205                         {
00206                                 if(fread(colorbuffer, 1, tga.bytesPerPixel, fTGA) != tga.bytesPerPixel) // Try to read 1 pixel
00207                                 {
00208                                         //MessageBox(NULL, "Could not read image data", "ERROR", MB_OK);                // IF we cant, display an error
00209 
00210                                         if(fTGA != NULL)                                                                                                        // See if file is open
00211                                         {
00212                                                 fclose(fTGA);                                                                                                   // If so, close file
00213                                         }
00214 
00215                                         if(colorbuffer != NULL)                                                                                         // See if colorbuffer has data in it
00216                                         {
00217                                                 free(colorbuffer);                                                                                              // If so, delete it
00218                                         }
00219 
00220                                         if(texture->imageData != NULL)                                                                          // See if there is stored Image data
00221                                         {
00222                                                 free(texture->imageData);                                                                               // If so, delete it too
00223                                         }
00224 
00225                                         return false;                                                                                                           // Return failed
00226                                 }
00227                                                                                                                                                                                 // write to memory
00228                                 texture->imageData[currentbyte          ] = colorbuffer[2];                                 // Flip R and B vcolor values around in the process 
00229                                 texture->imageData[currentbyte + 1      ] = colorbuffer[1];
00230                                 texture->imageData[currentbyte + 2      ] = colorbuffer[0];
00231 
00232                                 if(tga.bytesPerPixel == 4)                                                                                              // if its a 32 bpp image
00233                                 {
00234                                         texture->imageData[currentbyte + 3] = colorbuffer[3];                           // copy the 4th byte
00235                                 }
00236 
00237                                 currentbyte += tga.bytesPerPixel;                                                                               // Increase thecurrent byte by the number of bytes per pixel
00238                                 currentpixel++;                                                                                                                 // Increase current pixel by 1
00239 
00240                                 if(currentpixel > pixelcount)                                                                                   // Make sure we havent read too many pixels
00241                                 {
00242                                         //MessageBox(NULL, "Too many pixels read", "ERROR", NULL);                      // if there is too many... Display an error!
00243 
00244                                         if(fTGA != NULL)                                                                                                        // If there is a file open
00245                                         {
00246                                                 fclose(fTGA);                                                                                                   // Close file
00247                                         }       
00248 
00249                                         if(colorbuffer != NULL)                                                                                         // If there is data in colorbuffer
00250                                         {
00251                                                 free(colorbuffer);                                                                                              // Delete it
00252                                         }
00253 
00254                                         if(texture->imageData != NULL)                                                                          // If there is Image data
00255                                         {
00256                                                 free(texture->imageData);                                                                               // delete it
00257                                         }
00258 
00259                                         return false;                                                                                                           // Return failed
00260                                 }
00261                         }
00262                 }
00263                 else                                                                                                                                                    // chunkheader > 128 RLE data, next color reapeated chunkheader - 127 times
00264                 {
00265                         chunkheader -= 127;                                                                                                                     // Subteact 127 to get rid of the ID bit
00266                         if(fread(colorbuffer, 1, tga.bytesPerPixel, fTGA) != tga.bytesPerPixel)         // Attempt to read following color values
00267                         {       
00268                                 //MessageBox(NULL, "Could not read from file", "ERROR", MB_OK);                 // If attempt fails.. Display error (again)
00269 
00270                                 if(fTGA != NULL)                                                                                                                // If thereis a file open
00271                                 {
00272                                         fclose(fTGA);                                                                                                           // Close it
00273                                 }
00274 
00275                                 if(colorbuffer != NULL)                                                                                                 // If there is data in the colorbuffer
00276                                 {
00277                                         free(colorbuffer);                                                                                                      // delete it
00278                                 }
00279 
00280                                 if(texture->imageData != NULL)                                                                                  // If thereis image data
00281                                 {
00282                                         free(texture->imageData);                                                                                       // delete it
00283                                 }
00284 
00285                                 return false;                                                                                                                   // return failed
00286                         }
00287 
00288                         for(short counter = 0; counter < chunkheader; counter++)                                        // copy the color into the image data as many times as dictated 
00289                         {                                                                                                                                                       // by the header
00290                                 texture->imageData[currentbyte          ] = colorbuffer[2];                                     // switch R and B bytes areound while copying
00291                                 texture->imageData[currentbyte + 1      ] = colorbuffer[1];
00292                                 texture->imageData[currentbyte + 2      ] = colorbuffer[0];
00293 
00294                                 if(tga.bytesPerPixel == 4)                                                                                              // If TGA images is 32 bpp
00295                                 {
00296                                         texture->imageData[currentbyte + 3] = colorbuffer[3];                           // Copy 4th byte
00297                                 }
00298 
00299                                 currentbyte += tga.bytesPerPixel;                                                                               // Increase current byte by the number of bytes per pixel
00300                                 currentpixel++;                                                                                                                 // Increase pixel count by 1
00301 
00302                                 if(currentpixel > pixelcount)                                                                                   // Make sure we havent written too many pixels
00303                                 {
00304                                         //MessageBox(NULL, "Too many pixels read", "ERROR", NULL);                      // if there is too many... Display an error!
00305 
00306                                         if(fTGA != NULL)                                                                                                        // If there is a file open
00307                                         {
00308                                                 fclose(fTGA);                                                                                                   // Close file
00309                                         }       
00310 
00311                                         if(colorbuffer != NULL)                                                                                         // If there is data in colorbuffer
00312                                         {
00313                                                 free(colorbuffer);                                                                                              // Delete it
00314                                         }
00315 
00316                                         if(texture->imageData != NULL)                                                                          // If there is Image data
00317                                         {
00318                                                 free(texture->imageData);                                                                               // delete it
00319                                         }
00320 
00321                                         return false;                                                                                                           // Return failed
00322                                 }
00323                         }
00324                 }
00325         }
00326 
00327         while(currentpixel < pixelcount);                                                                                                       // Loop while there are still pixels left
00328         fclose(fTGA);                                                                                                                                           // Close the file
00329         return true;                                                                                                                                            // return success
00330 }

Generated on Thu Mar 24 11:05:02 2005 for ParticleSystem by  doxygen 1.4.1