Main Page Namespace List Class Hierarchy Alphabetical List Data Structures File List Namespace Members 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 }*/