Main Page   Namespace List   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals  

ExCImage.cpp

Go to the documentation of this file.
00001 /*
00002  * ExNihilo 3D Engine
00003  * 
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU Library General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  *
00018  * Please read AUTHORS file !!!
00019  * 
00020  * $Id: ExCImage.cpp,v 1.2 2002/08/01 19:37:50 binny Exp $
00021  *
00022  */
00023 
00024 #include "ExCImage.h"
00025 
00026 bool LoadBMP(tImage *image,std::string strFileName)
00027 {
00028         return LoadBMP(image,strFileName.data());
00029 }
00030 
00031 bool LoadTGA(tImage *image,std::string strFileName)
00032 {
00033         return LoadTGA(image,strFileName.data());
00034 }
00035 
00036 bool LoadJPG(tImage *image,std::string strFileName)
00037 {
00038         return LoadJPG(image,strFileName.data());
00039 }
00040 
00041 bool LoadBMP(tImage *image,const char *strFileName)
00042 {
00043         //---------------------------------------------
00044         FILE *file;
00045         unsigned long size;                 // size of the image in uchars.
00046         unsigned long i;                    // standard counter.
00047         unsigned short int planes;          // number of planes in image (must be 1) 
00048         unsigned short int channels;        // number of bits per pixel (must be 24)
00049         char temp;                          // temporary color storage for bgr-rgb conversion.
00050 
00051         // make sure the file is there.
00052         if ((file = fopen(strFileName, "rb"))==NULL)
00053         {
00054                 printf("File Not Found : %s\n",strFileName);
00055                 return false;
00056         }
00057 #ifdef UNIX_SRC
00058         unsigned short int is_bmp;
00059         if (! fread (&is_bmp, sizeof (short int), 1, file))
00060         {
00061                 printf("cannot read %s.\n", strFileName);
00062                 return false;
00063         }
00064         
00065         /* check if file is a bitmap */
00066         if (is_bmp != 19778) 
00067         {
00068                 printf("%s is not a valid bmp file.\n", strFileName);
00069                 return false;
00070         }
00071         
00072         fseek (file, 8, SEEK_CUR);
00073         /* get the position of the actual bitmap data */
00074         long int bfOffBits;
00075         if (! fread (&bfOffBits, sizeof (long int), 1, file)) 
00076         {
00077                 printf("Error reading %s.\n", strFileName);
00078                 return false;
00079         }
00080         /*sprintf(buffer,"Data at offset: %ld.", bfOffBits);
00081         WriteToConsol(buffer);*/
00082         
00083         // seek through the bmp header, up to the width/height:
00084         fseek(file, 4, SEEK_CUR);
00085 #else
00086         fseek(file, 18, SEEK_SET);
00087 #endif
00088         // read the width
00089         if ((i = fread(&image->sizeX, 4, 1, file)) != 1) 
00090         {
00091                 printf("Error reading width from %s.\n", strFileName);
00092                 return false;
00093         }
00094                         
00095         // read the height 
00096         if ((i = fread(&image->sizeY, 4, 1, file)) != 1) 
00097         {
00098                 printf("Error reading height from %s.\n", strFileName);
00099                 return false;
00100         }
00101         
00102         
00103         // calculate the size (assuming 24 bits or 3 uchars per pixel).
00104         size = image->sizeX * image->sizeY * 3;
00105 
00106         // read the planes
00107         if ((fread(&planes, 2, 1, file)) != 1)
00108         {
00109                 printf("Error reading planes from %s.\n", strFileName);
00110                 return false;
00111         }
00112 
00113         if (planes != 1) 
00114         {
00115                 printf("Planes from %s is not 1: %u.\n", strFileName, planes);
00116                 return false;
00117         }
00118 
00119         // read the channels
00120         if ((i = fread(&channels, 2, 1, file)) != 1) 
00121         {
00122                 printf("Error reading channels from %s.\n", strFileName);
00123                 return false;
00124         }
00125         if (channels != 24) 
00126         {
00127                 printf("channels from %s is not 24: %u\n", strFileName, channels);
00128                 return false;
00129         }
00130         
00131         // seek past the rest of the bitmap header.
00132         fseek(file, 24, SEEK_CUR);
00133         // read the data. 
00134         image->data = new unsigned char[size];
00135         //char *foo = new char[size];
00136         //image->data = foo;
00137         
00138         if (image->data == NULL) 
00139         {
00140                 printf("Error allocating memory for color-corrected image data");
00141                 return false;   
00142         }
00143 
00144         if ((i = fread(image->data, size, 1, file)) != 1)
00145         {
00146                 printf("Error reading image data from %s.\n", strFileName);
00147                 return false;
00148         }
00149 
00150         for (i=0;i<size;i+=3) 
00151         { 
00152                 // reverse all of the colors. (bgr -> rgb)
00153                 temp = image->data[i];
00154                 image->data[i] = image->data[i+2];
00155                 image->data[i+2] = temp;
00156         }
00157         //---------------------------------------------
00158         image->type=GL_RGB;
00159         return true;
00160 }
00161 
00162 bool LoadTGA(tImage *image,const char *strFileName)
00163 {
00164         WORD width = 0, height = 0;                     // The dimensions of the image
00165         GLbyte length = 0;                                      // The length in bytes to the pixels
00166         GLbyte imageType = 0;                                   // The image type (RLE, RGB, Alpha...)
00167         GLbyte bits = 0;                                                // The bits per pixel for the image (16, 24, 32)
00168         FILE *pFile = NULL;                                     // The file pointer
00169         int channels = 0;                                       // The channels of the image (3 = RGA : 4 = RGBA)
00170         int stride = 0;                                         // The stride (channels * width)
00171         int i = 0;                                                      // A counter
00172 
00173         // Open a file pointer to the targa file and check if it was found and opened 
00174         if((pFile = fopen(strFileName, "rb")) == NULL) 
00175         {
00176                 // Display an error message saying the file was not found, then return false
00177                 printf("Unable to load TGA File!");
00178                 return false;
00179         }
00180                 
00181         // Allocate the structure that will hold our eventual image data (must free it!)
00182         image = (tImage*)malloc(sizeof(tImage));
00183 
00184         // Read in the length in bytes from the header to the pixel data
00185         fread(&length, sizeof(GLbyte), 1, pFile);
00186         
00187         // Jump over one byte
00188         fseek(pFile,1,SEEK_CUR); 
00189 
00190         // Read in the imageType (RLE, RGB, etc...)
00191         fread(&imageType, sizeof(GLbyte), 1, pFile);
00192         
00193         // Skip past general information we don't care about
00194         fseek(pFile, 9, SEEK_CUR); 
00195 
00196         // Read the width, height and bits per pixel (16, 24 or 32)
00197         fread(&width,  sizeof(WORD), 1, pFile);
00198         fread(&height, sizeof(WORD), 1, pFile);
00199         fread(&bits,   sizeof(GLbyte), 1, pFile);
00200         
00201         // Now we move the file pointer to the pixel data
00202         fseek(pFile, length + 1, SEEK_CUR); 
00203 
00204         // Check if the image is RLE compressed or not
00205         if(imageType != TGA_RLE)
00206         {
00207                 // Check if the image is a 24 or 32-bit image
00208                 if(bits == 24 || bits == 32)
00209                 {
00210                         // Calculate the channels (3 or 4) - (use bits >> 3 for more speed).
00211                         // Next, we calculate the stride and allocate enough memory for the pixels.
00212                         channels = bits / 8;
00213                         stride = channels * width;
00214                         image->data = ((unsigned char*)malloc(sizeof(unsigned char)*stride*height));
00215 
00216                         // Load in all the pixel data line by line
00217                         for(uint y = 0; y < height; y++)
00218                         {
00219                                 // Store a pointer to the current line of pixels
00220                                 unsigned char *pLine = &(image->data[stride * y]);
00221 
00222                                 // Read in the current line of pixels
00223                                 fread(pLine, stride, 1, pFile);
00224                         
00225                                 // Go through all of the pixels and swap the B and R values since TGA
00226                                 // files are stored as BGR instead of RGB (or use GL_BGR_EXT verses GL_RGB)
00227                                 for(i = 0; i < stride; i += channels)
00228                                 {
00229                                         int temp     = pLine[i];
00230                                         pLine[i]     = pLine[i + 2];
00231                                         pLine[i + 2] = temp;
00232                                 }
00233                         }
00234                 }
00235                 // Check if the image is a 16 bit image (RGB stored in 1 unsigned short)
00236                 else if(bits == 16)
00237                 {
00238                         unsigned short pixels = 0;
00239                         int r=0, g=0, b=0;
00240 
00241                         // Since we convert 16-bit images to 24 bit, we hardcode the channels to 3.
00242                         // We then calculate the stride and allocate memory for the pixels.
00243                         channels = 3;
00244                         stride = channels * width;
00245                         image->data = ((unsigned char*)malloc(sizeof(unsigned char)*stride*height));
00246 
00247                         // Load in all the pixel data pixel by pixel
00248                         for(uint i = 0; i < width*height; i++)
00249                         {
00250                                 // Read in the current pixel
00251                                 fread(&pixels, sizeof(unsigned short), 1, pFile);
00252                                 
00253                                 // Convert the 16-bit pixel into an RGB
00254                                 b = (pixels & 0x1f) << 3;
00255                                 g = ((pixels >> 5) & 0x1f) << 3;
00256                                 r = ((pixels >> 10) & 0x1f) << 3;
00257                                 
00258                                 // This essentially assigns the color to our array and swaps the
00259                                 // B and R values at the same time.
00260                                 image->data[i * 3 + 0] = r;
00261                                 image->data[i * 3 + 1] = g;
00262                                 image->data[i * 3 + 2] = b;
00263                         }
00264                 }       
00265                 // Else return a false for a bad or unsupported pixel format
00266                 else
00267                         return false;
00268         }
00269         // Else, it must be Run-Length Encoded (RLE)
00270         else
00271         {
00272                 // Create some variables to hold the rleID, current colors read, channels, & stride.
00273                 GLbyte rleID = 0;
00274                 int colorsRead = 0;
00275                 channels = bits / 8;
00276                 stride = channels * width;
00277 
00278                 // Next we want to allocate the memory for the pixels and create an array,
00279                 // depending on the channel count, to read in for each pixel.
00280                 image->data = ((unsigned char*)malloc(sizeof(unsigned char)*stride*height));
00281                 GLbyte *pColors = ((GLbyte*)malloc(sizeof(GLbyte)*channels));
00282 
00283                 // Load in all the pixel data
00284                 while((unsigned)i < width*height)
00285                 {
00286                         // Read in the current color count + 1
00287                         fread(&rleID, sizeof(GLbyte), 1, pFile);
00288                         
00289                         // Check if we don't have an encoded string of colors
00290                         if(rleID < (unsigned)128)
00291                         {
00292                                 // Increase the count by 1
00293                                 rleID++;
00294 
00295                                 // Go through and read all the unique colors found
00296                                 while(rleID)
00297                                 {
00298                                         // Read in the current color
00299                                         fread(pColors, sizeof(GLbyte) * channels, 1, pFile);
00300 
00301                                         // Store the current pixel in our image array
00302                                         image->data[colorsRead + 0] = pColors[2];
00303                                         image->data[colorsRead + 1] = pColors[1];
00304                                         image->data[colorsRead + 2] = pColors[0];
00305 
00306                                         // If we have a 4 channel 32-bit image, assign one more for the alpha
00307                                         if(bits == 32)
00308                                                 image->data[colorsRead + 3] = pColors[3];
00309 
00310                                         // Increase the current pixels read, decrease the amount
00311                                         // of pixels left, and increase the starting index for the next pixel.
00312                                         i++;
00313                                         rleID--;
00314                                         colorsRead += channels;
00315                                 }
00316                         }
00317                         // Else, let's read in a string of the same character
00318                         else
00319                         {
00320                                 // Minus the 128 ID + 1 (127) to get the color count that needs to be read
00321                                 rleID -= 127;
00322 
00323                                 // Read in the current color, which is the same for a while
00324                                 fread(pColors, sizeof(GLbyte) * channels, 1, pFile);
00325 
00326                                 // Go and read as many pixels as are the same
00327                                 while(rleID)
00328                                 {
00329                                         // Assign the current pixel to the current index in our pixel array
00330                                         image->data[colorsRead + 0] = pColors[2];
00331                                         image->data[colorsRead + 1] = pColors[1];
00332                                         image->data[colorsRead + 2] = pColors[0];
00333 
00334                                         // If we have a 4 channel 32-bit image, assign one more for the alpha
00335                                         if(bits == 32)
00336                                                 image->data[colorsRead + 3] = pColors[3];
00337 
00338                                         // Increase the current pixels read, decrease the amount
00339                                         // of pixels left, and increase the starting index for the next pixel.
00340                                         i++;
00341                                         rleID--;
00342                                         colorsRead += channels;
00343                                 }
00344                                 
00345                         }
00346                                 
00347                 }
00348         }
00349 
00350         // Close the file pointer that opened the file
00351         fclose(pFile);
00352 
00353         // Fill in our tImage structure to pass back
00354         image->channels = channels;
00355         image->sizeX    = width;
00356         image->sizeY    = height;
00357 
00358         // Return the TGA data (remember, you must free this data after you are done)
00359         return true;
00360 }
00361 
00362 bool LoadJPG(tImage *image,const char *strFileName)
00363 {
00364         return true;
00365 }
00366 
00367 /*DecodeJPG(jpeg_decompress_struct* cinfo, tImage *image)
00368 {
00369 }*/

Generated on Tue Aug 6 20:27:07 2002 for ExNihilo by doxygen1.2.17