• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

src/cannonball/src/LevelTGA.cpp

Go to the documentation of this file.
00001 #include "main.h"
00002 
00003 bool LoadUncompressedTGA(int& width, int& height, Pixel** outData, FILE * datei){
00004         uchar header[6];
00005         uint bytesPerPixel;
00006         uint size;
00007         uchar* data;
00008 
00009         if(fread(header, sizeof(header), 1, datei) == 0)
00010                 return false;
00011 
00012         width  = header[1] * 256 + header[0]; // Determine The TGA Width  (highbyte*256+lowbyte)
00013         height = header[3] * 256 + header[2]; // Determine The TGA Height (highbyte*256+lowbyte)
00014 
00015         if((width <= 0) || (height <= 0))
00016                 return false;
00017 
00018         bytesPerPixel = header[4] / 8;
00019         size = bytesPerPixel * width * height;
00020         data = (uchar*)malloc(sizeof(Pixel) * width * height);
00021 
00022         if(fread(data, 1, size, datei) != size){
00023                 free(data);
00024                 return false;
00025         }
00026 
00027         for(uint cswap = 0; cswap < size; cswap += bytesPerPixel)
00028                 data[cswap] ^= data[cswap+2] ^= data[cswap] ^= data[cswap+2];
00029 
00030         *outData = (Pixel*)data;
00031 
00032         if(bytesPerPixel == 3)
00033         {
00034                 for(int i=width*height-1, j=3*width*height-3; i>=0; i--, j-=3)
00035                 {
00036                         (*outData)[i].canal[3] = 255;
00037                         (*outData)[i].canal[2] = data[j+2];
00038                         (*outData)[i].canal[1] = data[j+1];
00039                         (*outData)[i].canal[0] = data[j+0];
00040                 }
00041         }
00042 
00043         return true;
00044 }
00045 
00046 bool LoadCompressedTGA(int& width, int& height, Pixel** outData, FILE * datei){
00047         uchar header[6];
00048         uint bytesPerPixel;
00049         uint size;
00050         uchar* data;
00051         uchar counter;
00052 
00053         if(fread(header, sizeof(header), 1, datei) == 0)
00054                 return false;
00055 
00056         width  = header[1] * 256 + header[0]; // Determine The TGA Width  (highbyte*256+lowbyte)
00057         height = header[3] * 256 + header[2]; // Determine The TGA Height (highbyte*256+lowbyte)
00058 
00059         if((width <= 0) || (height <= 0))
00060                 return false;
00061 
00062         bytesPerPixel = header[4] / 8;
00063         size = bytesPerPixel * width * height;
00064         data = (uchar*)malloc(sizeof(Pixel) * width * height);
00065 
00066         // Nuber of pixels in the image
00067         uint pixelcount = width * height;
00068         // Current pixel being read
00069         uint currentpixel = 0;
00070         // Current byte 
00071         uint currentbyte = 0;
00072         // Storage for 1 pixel
00073         uchar colorbuffer[4];
00074 
00075         do{
00076                 // Storage for "chunk" header
00077                 uchar chunkheader = 0;
00078 
00079                 // Read in the 1 byte header
00080                 if(fread(&chunkheader, sizeof(uchar), 1, datei) == 0){
00081                         free(data);
00082                         return false;
00083                 }
00084 
00085                 if(chunkheader < 128){
00086                         chunkheader++;
00087                         // If the ehader is < 128, it means the that is the number of RAW color packets minus 1
00088                         // that follow the header add 1 to get number of following color values
00089                         // Read RAW color values
00090                         for(counter = 0; counter < chunkheader; counter++){
00091                                 // Try to read 1 pixel
00092                                 if(fread(colorbuffer, 1, bytesPerPixel, datei) != bytesPerPixel){
00093                                         free(data);
00094                                         return false;
00095                                 }
00096                                 
00097                                 // write to memory
00098                                 // Flip R and B vcolor values around in the process
00099                                 data[currentbyte  ] = colorbuffer[2];
00100                                 data[currentbyte+1] = colorbuffer[1];
00101                                 data[currentbyte+2] = colorbuffer[0];
00102 
00103                                 // if its a 32 bpp image
00104                                 // copy the 4th byte
00105                                 if(bytesPerPixel == 4)
00106                                         data[currentbyte+3] = colorbuffer[3];
00107 
00108                                 currentbyte += bytesPerPixel;
00109                                 currentpixel++;
00110 
00111                                 // Make sure we havent read too many pixels
00112                                 if(currentpixel > pixelcount){
00113                                         free(data);
00114                                         return false;
00115                                 }
00116                         }
00117                 }
00118                 // chunkheader > 128 RLE data, next color reapeated chunkheader - 127 times
00119                 else{
00120                         // Subteact 127 to get rid of the ID bit
00121                         chunkheader -= 127;
00122 
00123                         // Attempt to read following color values
00124                         if(fread(colorbuffer, 1, bytesPerPixel, datei) != bytesPerPixel){
00125                                 free(data);
00126                                 return false;
00127                         }
00128 
00129                         // copy the color into the image data as many times as dictated 
00130                         // by the header
00131                         for(counter = 0; counter < chunkheader; counter++){
00132                                 // switch R and B bytes areound while copying
00133                                 data[currentbyte  ] = colorbuffer[2];
00134                                 data[currentbyte+1] = colorbuffer[1];
00135                                 data[currentbyte+2] = colorbuffer[0];
00136 
00137                                 // If TGA images is 32 bpp
00138                                 if(bytesPerPixel == 4)
00139                                         // Copy 4th byte
00140                                         data[currentbyte + 3] = colorbuffer[3];
00141 
00142                                 currentbyte += bytesPerPixel;
00143                                 currentpixel++;
00144 
00145                                 // Make sure we havent written too many pixels
00146                                 if(currentpixel > pixelcount){
00147                                         free(data);
00148                                         return false;
00149                                 }
00150                         }
00151                 }
00152         // Loop while there are still pixels left
00153         }while(currentpixel < pixelcount);
00154 
00155         *outData = (Pixel*)data;
00156 
00157         if(bytesPerPixel == 3)
00158         {
00159                 for(int i=width*height-1, j=3*width*height-3; i>=0; i--, j-=3)
00160                 {
00161                         (*outData)[i].canal[3] = 255;
00162                         (*outData)[i].canal[2] = data[j+2];
00163                         (*outData)[i].canal[1] = data[j+1];
00164                         (*outData)[i].canal[0] = data[j+0];
00165                 }
00166         }
00167         
00168         return true;
00169 }
00170 
00171 bool Level::loadTGA(const wchar* filename, int& width, int& height, Pixel** outData){
00172         bool ok;
00173         FILE* file;
00174         uchar tgaheader[12];
00175         // Uncompressed TGA Header
00176         uchar uTGAcompare[12] = {0,0, 2,0,0,0,0,0,0,0,0,0};
00177         // Compressed TGA Header
00178         uchar cTGAcompare[12] = {0,0,10,0,0,0,0,0,0,0,0,0};
00179 
00180         if(_wfopen_s(&file, filename, TEXT("rb")) != 0)
00181                 return false;
00182 
00183         #define CHECK(_b) if(_b){fclose(file);return false;}
00184 
00185         CHECK(fread(&tgaheader, sizeof(tgaheader), 1, file) == 0);
00186 
00187         // load TGA data
00188         // load uncompressed data
00189         if(memcmp(uTGAcompare, &tgaheader, sizeof(tgaheader)) == 0)
00190                 ok = LoadUncompressedTGA(width, height, outData, file);
00191         // load compressed data
00192         else if(memcmp(cTGAcompare, &tgaheader, sizeof(tgaheader)) == 0)
00193                 ok = LoadCompressedTGA(width, height, outData, file);
00194         // this is no TGA file
00195         else
00196                 ok = false;
00197 
00198         // check for errors
00199         CHECK(ok == false);
00200 
00201         // close file
00202         fclose(file);
00203 
00204         #undef CHECK
00205         return true;
00206 }

Generated on Fri Jun 18 2010 17:48:39 for Cannonball by  doxygen 1.7.0