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

src/util/src/TextureData.cpp

Go to the documentation of this file.
00001 #pragma once
00002 #include "../pch.h"
00003 
00004 TextureData::TextureData()
00005 {
00006         mipmapsColor = 0;
00007         mipmapsDetail = 0;
00008         color = 0;
00009         detail = 0;
00010 }
00011 
00012 TextureData::~TextureData()
00013 {
00014         mipmapsColor = 0;
00015         mipmapsDetail = 0;
00016         SAVEFREE(color);
00017         detail = 0;
00018 }
00019 
00020 
00021 inline bool loadUnknown(const wchar* filename, int& width, int& height, Pixel** outData)
00022 {
00023         bool ok = true;
00024         size_t filenameLength = wcslen(filename);
00025 
00026         if(wcscmp(&filename[filenameLength-4], TEXT(".bmp")) == 0)
00027                 ok = loadBMP(filename, width, height, outData);
00028         else if(wcscmp(&filename[filenameLength-4], TEXT(".tga")) == 0)
00029                 ok = loadTGA(filename, width, height, outData);
00030         else
00031                 return false;
00032 
00033         if(outData == 0 && width != height)
00034                 return false;
00035 
00036         return ok;
00037 }
00038 
00039 bool loadTextureData(const wchar* colorFilename, const wchar* normalFilename, const wchar* heightFilename, TextureData& out)
00040 {
00041         Pixel* colorData = 0;
00042         Pixel* normalData = 0;
00043         Pixel* heightData = 0;
00044         int widthColor = 0, heightColor = 0;
00045         int widthDetail = 0, heightDetail = 0;
00046         bool ok = true;
00047 
00048         ok = loadUnknown(colorFilename, widthColor, heightColor, 0);
00049         if(ok) ok = loadUnknown(colorFilename, widthColor, heightColor, &colorData);
00050         if(normalFilename){
00051                 ok = loadUnknown(normalFilename, widthDetail, heightDetail, 0);
00052                 if(ok) ok = loadUnknown(normalFilename, widthDetail, heightDetail, &normalData);
00053                 if(ok) ok = loadUnknown(heightFilename, widthDetail, heightDetail, &heightData);
00054         }
00055 
00056         if(ok == false)
00057         {
00058                 SAVEFREE(colorData);
00059                 SAVEFREE(normalData);
00060                 SAVEFREE(heightData);
00061                 return false;
00062         }
00063 
00064         int mipmapsColor = 0;
00065         int mipmapsDetail = 0;
00066         int mipmapPixelsColor = 0;
00067         int mipmapPixelsDetail = 0;
00068         MipMap* colorMipmaps;
00069         MipMap* detailMipmaps;
00070 
00071         for(int w=widthColor; w>0; mipmapPixelsColor+=w*w, w/=2, mipmapsColor++);
00072         if(normalFilename)
00073                 for(int w=widthDetail; w>0; mipmapPixelsDetail+=w*w, w/=2, mipmapsDetail++);
00074 
00075         void* mem = malloc(sizeof(MipMap)*(mipmapsColor+mipmapsDetail) + sizeof(Pixel)*(mipmapPixelsColor+mipmapPixelsDetail));
00076 
00077         colorMipmaps = (MipMap*)mem;
00078         detailMipmaps = &colorMipmaps[mipmapsColor];
00079         Pixel* colorPixels = (Pixel*)&detailMipmaps[mipmapsDetail];
00080         Pixel* detailPixels = &colorPixels[mipmapPixelsColor];
00081 
00082         for(int i=0, w=widthColor, curPixel=0; i<mipmapsColor; curPixel+=w*w, w/=2, i++)
00083         {
00084                 colorMipmaps[i].width = w;
00085                 colorMipmaps[i].height = w;
00086                 colorMipmaps[i].data = &colorPixels[curPixel];
00087         }
00088 
00089         if(normalFilename){
00090                 for(int i=0, w=widthDetail, curPixel=0; i<mipmapsDetail; curPixel+=w*w, w/=2, i++)
00091                 {
00092                         detailMipmaps[i].width = w;
00093                         detailMipmaps[i].height = w;
00094                         detailMipmaps[i].data = &detailPixels[curPixel];
00095                 }
00096         }
00097 
00098         // copy loaded data
00099         for(int y=0; y<colorMipmaps[0].height; y++)
00100         {
00101                 for(int x=0; x<colorMipmaps[0].width; x++)
00102                         colorMipmaps[0].data[(heightColor-1-y)*widthColor+(widthColor-1-x)] = colorData[y*widthColor+x];
00103         }
00104 
00105         // compute color mipmaps
00106         for(int i=0; i<mipmapsColor-1; i++)
00107         {
00108                 for(int y=0; y<colorMipmaps[i+1].height; y++)
00109                 {
00110                         for(int x=0; x<colorMipmaps[i+1].width; x++)
00111                         {
00112                                 int color[4];
00113                                 for(int c=0; c<4; color[c]  = colorMipmaps[i].data[((y+0)* colorMipmaps[i].width + x + 0)*2].canal[c], c++);
00114                                 for(int c=0; c<4; color[c] += colorMipmaps[i].data[((y+0)* colorMipmaps[i].width + x + 1)*2].canal[c], c++);
00115                                 for(int c=0; c<4; color[c] += colorMipmaps[i].data[((y+1)* colorMipmaps[i].width + x + 0)*2].canal[c], c++);
00116                                 for(int c=0; c<4; color[c] += colorMipmaps[i].data[((y+1)* colorMipmaps[i].width + x + 1)*2].canal[c], c++);
00117                                 for(int c=0; c<4; colorMipmaps[i+1].data[y * colorMipmaps[i+1].width + x].canal[c] = uchar(color[c]/4), c++);
00118                         }
00119                 }
00120         }
00121 
00122         if(normalFilename){
00123                 // copy loaded height data
00124                 for(int y=0; y<detailMipmaps[0].height; y++)
00125                 {
00126                         for(int x=0; x<detailMipmaps[0].width; x++)
00127                         {
00128                                 normalData[y*widthDetail+x].a = heightData[y*widthDetail+x].r;
00129                                 detailMipmaps[0].data[y*widthDetail+x] = normalData[y*widthDetail+x];
00130                         }
00131                 }
00132 
00133                 // compute color mipmaps
00134                 for(int i=0; i<mipmapsDetail-1; i++)
00135                 {
00136                         for(int y=0; y<detailMipmaps[i].height/2; y++)
00137                         {
00138                                 for(int x=0; x<detailMipmaps[i].width/2; x++)
00139                                 {
00140                                         int normal[4];
00141                                         for(int c=0; c<4; normal[c]  = detailMipmaps[i].data[((y+0)* detailMipmaps[i].width + x + 0)*2].canal[c], c++);
00142                                         for(int c=0; c<4; normal[c] += detailMipmaps[i].data[((y+0)* detailMipmaps[i].width + x + 1)*2].canal[c], c++);
00143                                         for(int c=0; c<4; normal[c] += detailMipmaps[i].data[((y+1)* detailMipmaps[i].width + x + 0)*2].canal[c], c++);
00144                                         for(int c=0; c<4; normal[c] += detailMipmaps[i].data[((y+1)* detailMipmaps[i].width + x + 1)*2].canal[c], c++);
00145                                         for(int c=0; c<4; detailMipmaps[i+1].data[y * detailMipmaps[i+1].width + x].canal[c] = uchar(normal[c]/4), c++);
00146                                 }
00147                         }
00148                 }
00149         }
00150 
00151         // free temporary data
00152         SAVEFREE(colorData);
00153         SAVEFREE(normalData);
00154         SAVEFREE(heightData);
00155 
00156         // fill output structure
00157         out.mipmapsColor = mipmapsColor;
00158         out.mipmapsDetail = mipmapsDetail;
00159         out.color = colorMipmaps;
00160         out.detail = detailMipmaps;
00161         return true;
00162 }
00163 
00164 
00165 #pragma pack(1)
00166 
00167 struct BMP_SIGNATURE {
00168         BMP_SIGNATURE() {
00169                 this->c[0] = 'B';
00170                 this->c[1] = 'M';
00171         }
00172         union {
00173                 unsigned short int s;//= 'MB';
00174                 unsigned char c[2];
00175         };
00176 };
00177 
00178 const BMP_SIGNATURE bmpSignature;
00179 const unsigned short int BITMAP_SIGNATURE = bmpSignature.s;
00180 
00181 typedef struct {
00182         unsigned short int Signature;
00183         unsigned int Size;
00184         unsigned int Reserved;
00185         unsigned int BitsOffset;
00186 } BITMAP_FILEHEADER;
00187 
00188 #define BITMAP_FILEHEADER_SIZE 14
00189 
00190 typedef struct {
00191         unsigned int HeaderSize;
00192         int Width;
00193         int Height;
00194         unsigned short int Planes;
00195         unsigned short int BitCount;
00196         unsigned int Compression;
00197         unsigned int SizeImage;
00198         int PelsPerMeterX;
00199         int PelsPerMeterY;
00200         unsigned int ClrUsed;
00201         unsigned int ClrImportant;
00202         unsigned int RedMask;
00203         unsigned int GreenMask;
00204         unsigned int BlueMask;
00205         unsigned int AlphaMask;
00206         unsigned int CsType;
00207         unsigned int Endpoints[9]; // see http://msdn2.microsoft.com/en-us/library/ms536569.aspx
00208         unsigned int GammaRed;
00209         unsigned int GammaGreen;
00210         unsigned int GammaBlue;
00211 } BITMAP_HEADER;
00212 
00213 typedef struct {
00214         unsigned char Red;
00215         unsigned char Green;
00216         unsigned char Blue;
00217         unsigned char Alpha;
00218 } RGBA;
00219 
00220 typedef struct {
00221         unsigned char Blue;
00222         unsigned char Green;
00223         unsigned char Red;
00224         unsigned char Alpha;
00225 } BGRA;
00226 
00227 typedef struct {
00228         unsigned char Blue;
00229         unsigned char Green;
00230         unsigned char Red;
00231 } BGR;
00232 
00233 typedef struct {
00234         unsigned short int Blue:5;
00235         unsigned short int Green:5;
00236         unsigned short int Red:5;
00237         unsigned short int Reserved:1;
00238 } BGR16;
00239 
00240 uint myShiftRightByMask(uint Color, uint Mask, uint DistributeToBits) {
00241         if (Mask == 0) return 0;
00242 
00243         uint ShiftCount = 0;
00244         uint Test = 0x00000001;
00245 
00246         while((ShiftCount<32) && !(Mask & Test)){
00247                 Test <<= 1;
00248                 ShiftCount++;
00249         }
00250         
00251         uint BitCount = 32;
00252         Test = 0x80000000;
00253 
00254         while(BitCount && !((Mask >> ShiftCount) & Test)){
00255                 Test >>= 1;
00256                 BitCount--;
00257         }
00258 
00259         uint BaseColor = (Color & Mask) >> ShiftCount;
00260 
00261         if(DistributeToBits > BitCount){
00262                 //We have to fill lower bits
00263                 uint BitsToFill = DistributeToBits - BitCount;
00264                 while(BitsToFill--) {
00265                         BaseColor <<= 1;
00266                         if(BaseColor & 1)
00267                                 BaseColor |= 1;
00268                 }
00269         }else if(DistributeToBits < BitCount){
00270                 BaseColor >>= (BitCount - DistributeToBits);
00271         }
00272         return BaseColor;
00273 }
00274 
00275 bool loadBMP(const wchar* filename, int& width, int& height, Pixel** outData){
00276         FILE* file = 0;
00277         BITMAP_FILEHEADER m_BitmapFileHeader;
00278         BITMAP_HEADER m_BitmapHeader;
00279         RGBA* m_BitmapData = 0;
00280         uchar *Line = 0;
00281         uint m_BitmapSize = 0;
00282         BGRA m_ColorTable[256];
00283         uint m_ColorTableSize = 0;
00284         int bmpWidth = 0, bmpHeight = 0;
00285 
00286         #define SAVEEXIT(rs) {\
00287                 if(file){fclose(file);file=0;}\
00288                 SAVEFREE(m_BitmapData);\
00289                 SAVEFREE(Line);\
00290                 return rs;}
00291  
00292         if(_wfopen_s(&file, filename, TEXT("rb")) != 0)
00293                 return false;
00294         
00295         fread(&m_BitmapFileHeader, BITMAP_FILEHEADER_SIZE, 1, file);
00296         if(m_BitmapFileHeader.Signature != BITMAP_SIGNATURE)
00297                 return false;
00298 
00299         fread(&m_BitmapHeader, sizeof(BITMAP_HEADER), 1, file);
00300         
00301         //Load Color Table
00302         fseek(file, BITMAP_FILEHEADER_SIZE + m_BitmapHeader.HeaderSize, SEEK_SET);
00303         
00304         switch(m_BitmapHeader.BitCount){
00305                 case 1: m_ColorTableSize = 2; break;
00306                 case 4: m_ColorTableSize = 16; break;
00307                 case 8: m_ColorTableSize = 256; break;
00308                 default: break;
00309         }
00310         
00311         if(m_ColorTableSize>0)
00312                 fread(m_ColorTable, sizeof(BGRA), m_ColorTableSize, file);
00313 
00314         /* ... Color Table for 16 or 32 Bit Images are not supported yet */     
00315         bmpWidth = m_BitmapHeader.Width < 0 ? -m_BitmapHeader.Width : m_BitmapHeader.Width;
00316         bmpHeight = m_BitmapHeader.Height < 0 ? -m_BitmapHeader.Height : m_BitmapHeader.Height;
00317 
00318         if(width > 0 && height > 0 && width != bmpWidth && height != bmpHeight){
00319                 fclose(file);
00320                 return false;
00321         }
00322 
00323         width = bmpWidth;
00324         height = bmpHeight;
00325 
00326         if(outData == 0){
00327                 fclose(file);
00328                 return true;
00329         }
00330 
00331         m_BitmapSize = bmpWidth * bmpHeight;
00332         m_BitmapData = (RGBA*)malloc(sizeof(RGBA)*m_BitmapSize);
00333         
00334         uint LineWidth = (bmpWidth * m_BitmapHeader.BitCount/8 + 3) & ~3;
00335         Line = (uchar*)malloc(sizeof(uchar)*LineWidth);
00336         
00337         fseek(file, m_BitmapFileHeader.BitsOffset, SEEK_SET);
00338         
00339         int Index = 0;
00340         
00341         switch(m_BitmapHeader.Compression){
00342                 // no compression
00343                 case 0:{
00344                         for (int i = 0; i < bmpHeight; i++) {
00345                                 fread(Line, LineWidth, 1, file);
00346                                 uchar *LinePtr = Line;
00347 
00348                                 switch(m_BitmapHeader.BitCount) {
00349                                         case 1:
00350                                                 for(int j = 0; j < bmpWidth; j++){
00351                                                         uint Color = *((uchar*) LinePtr);
00352                                                         for (int k = 0; k < 8; k++) {
00353                                                                 m_BitmapData[Index].Red   = m_ColorTable[Color & 0x80 ? 1 : 0].Red;
00354                                                                 m_BitmapData[Index].Green = m_ColorTable[Color & 0x80 ? 1 : 0].Green;
00355                                                                 m_BitmapData[Index].Blue  = m_ColorTable[Color & 0x80 ? 1 : 0].Blue;
00356                                                                 m_BitmapData[Index].Alpha = m_ColorTable[Color & 0x80 ? 1 : 0].Alpha;
00357                                                                 Index++;
00358                                                                 Color <<= 1;
00359                                                         }
00360                                                         LinePtr++;
00361                                                         j += 7;
00362                                                 }
00363                                                 break;
00364                                         case 4:
00365                                                 for(int j = 0; j < bmpWidth; j++){
00366                                                         uint Color = *((uchar*) LinePtr);
00367                                                         m_BitmapData[Index].Red   = m_ColorTable[(Color >> 4) & 0x0f].Red;
00368                                                         m_BitmapData[Index].Green = m_ColorTable[(Color >> 4) & 0x0f].Green;
00369                                                         m_BitmapData[Index].Blue  = m_ColorTable[(Color >> 4) & 0x0f].Blue;
00370                                                         m_BitmapData[Index].Alpha = m_ColorTable[(Color >> 4) & 0x0f].Alpha;
00371                                                         Index++;
00372                                                         m_BitmapData[Index].Red   = m_ColorTable[Color & 0x0f].Red;
00373                                                         m_BitmapData[Index].Green = m_ColorTable[Color & 0x0f].Green;
00374                                                         m_BitmapData[Index].Blue  = m_ColorTable[Color & 0x0f].Blue;
00375                                                         m_BitmapData[Index].Alpha = m_ColorTable[Color & 0x0f].Alpha;
00376                                                         Index++;
00377                                                         LinePtr++;
00378                                                         j++;
00379                                                 }
00380                                                 break;
00381                                         case 8:
00382                                                 for(int j = 0; j < bmpWidth; j++){
00383                                                         uint Color = *((uchar*) LinePtr);
00384                                                         m_BitmapData[Index].Red   = m_ColorTable[Color].Red;
00385                                                         m_BitmapData[Index].Green = m_ColorTable[Color].Green;
00386                                                         m_BitmapData[Index].Blue  = m_ColorTable[Color].Blue;
00387                                                         m_BitmapData[Index].Alpha = m_ColorTable[Color].Alpha;
00388                                                         Index++;
00389                                                         LinePtr++;
00390                                                 }
00391                                                 break;
00392                                         case 16:
00393                                                 for(int j = 0; j < bmpWidth; j++){
00394                                                         uint Color = *((unsigned short int*) LinePtr);
00395                                                         m_BitmapData[Index].Red   = ((Color >> 10) & 0x1f) << 3;
00396                                                         m_BitmapData[Index].Green = ((Color >> 5) & 0x1f) << 3;
00397                                                         m_BitmapData[Index].Blue  = (Color & 0x1f) << 3;
00398                                                         m_BitmapData[Index].Alpha = 255;
00399                                                         Index++;
00400                                                         LinePtr += 2;
00401                                                 }
00402                                                 break;
00403                                         case 24:
00404                                                 for(int j = 0; j < bmpWidth; j++){
00405                                                         uint Color = *((uint*) LinePtr);
00406                                                         m_BitmapData[Index].Blue  = Color & 0xff;
00407                                                         m_BitmapData[Index].Green = (Color >> 8) & 0xff;
00408                                                         m_BitmapData[Index].Red   = (Color >> 16) & 0xff;
00409                                                         m_BitmapData[Index].Alpha = 255;
00410                                                         Index++;
00411                                                         LinePtr += 3;
00412                                                 }
00413                                                 break;
00414                                         case 32:
00415                                                 for(int j = 0; j < bmpWidth; j++){
00416                                                         uint Color = *((uint*) LinePtr);
00417                                                         m_BitmapData[Index].Blue  = Color & 0xff;
00418                                                         m_BitmapData[Index].Green = (Color >> 8) & 0xff;
00419                                                         m_BitmapData[Index].Red   = (Color >> 16) & 0xff;
00420                                                         m_BitmapData[Index].Alpha = Color >> 24;
00421                                                         Index++;
00422                                                         LinePtr += 4;
00423                                                 }
00424                                                 break;
00425                                         default:
00426                                                 SAVEEXIT(false);
00427                                 }
00428                         }
00429                         break;
00430                 }
00431                 // RLE 8
00432                 case 1:{
00433                         uchar Count = 0;
00434                         uchar ColorIndex = 0;
00435                         int x = 0, y = 0;
00436 
00437                         for(bool run = true; !feof(file) && run; ){
00438                                 fread(&Count, 1, 1, file);
00439                                 fread(&ColorIndex, 1, 1, file);
00440 
00441                                 if (Count > 0) {
00442                                         Index = x + y * bmpWidth;
00443                                         for (int k = 0; k < Count; k++) {
00444                                                 m_BitmapData[Index + k].Red   = m_ColorTable[ColorIndex].Red;
00445                                                 m_BitmapData[Index + k].Green = m_ColorTable[ColorIndex].Green;
00446                                                 m_BitmapData[Index + k].Blue  = m_ColorTable[ColorIndex].Blue;
00447                                                 m_BitmapData[Index + k].Alpha = m_ColorTable[ColorIndex].Alpha;
00448                                         }
00449                                         x += Count;
00450                                 } else if (Count == 0) {
00451                                         int Flag = ColorIndex;
00452                                         switch(Flag){
00453                                                 case 0: x = 0; y++; break;
00454                                                 case 1: run = false; break;
00455                                                 case 2:{
00456                                                         char rx = 0;
00457                                                         char ry = 0;
00458                                                         fread(&rx, 1, 1, file);
00459                                                         fread(&ry, 1, 1, file);
00460                                                         x += rx;
00461                                                         y += ry;
00462                                                         break;
00463                                                 }
00464                                                 default:{
00465                                                         Count = Flag;
00466                                                         Index = x + y * bmpWidth;
00467                                                         for(int k = 0; k < Count; k++){
00468                                                                 fread(&ColorIndex, 1, 1, file);
00469                                                                 m_BitmapData[Index + k].Red   = m_ColorTable[ColorIndex].Red;
00470                                                                 m_BitmapData[Index + k].Green = m_ColorTable[ColorIndex].Green;
00471                                                                 m_BitmapData[Index + k].Blue  = m_ColorTable[ColorIndex].Blue;
00472                                                                 m_BitmapData[Index + k].Alpha = m_ColorTable[ColorIndex].Alpha;
00473                                                         }
00474                                                         x += Count;
00475                                                         if (ftell(file) & 1) fseek(file, 1, SEEK_CUR);
00476                                                         break;
00477                                                 }
00478                                         }
00479                                 }
00480                         }
00481                         break;
00482                 }
00483                 //case 2: // RLE 4 /* RLE 4 is not supported */
00484 
00485                 // BITFIELDS
00486                 case 3:{
00487                         /* We assumes that mask of each color component can be in any order */
00488                         for(int i=0; i<bmpHeight; i++){
00489                                 fread(Line, LineWidth, 1, file);
00490                                 uchar *LinePtr = Line;
00491                                 
00492                                 for(int j=0; j < bmpWidth; j++){
00493                                         uint Color = 0;
00494 
00495                                         if (m_BitmapHeader.BitCount == 16) {
00496                                                 Color = *((unsigned short int*) LinePtr);
00497                                                 LinePtr += 2;
00498                                         } else if (m_BitmapHeader.BitCount == 32) {
00499                                                 Color = *((uint*) LinePtr);
00500                                                 LinePtr += 4;
00501                                         }
00502                                         m_BitmapData[Index].Red   = myShiftRightByMask(Color, m_BitmapHeader.RedMask);
00503                                         m_BitmapData[Index].Green = myShiftRightByMask(Color, m_BitmapHeader.GreenMask);
00504                                         m_BitmapData[Index].Blue  = myShiftRightByMask(Color, m_BitmapHeader.BlueMask);
00505                                         m_BitmapData[Index].Alpha = myShiftRightByMask(Color, m_BitmapHeader.AlphaMask);
00506 
00507                                         Index++;
00508                                 }
00509                         }
00510                         break;
00511                 }
00512                 default:
00513                         SAVEEXIT(false);
00514         }
00515 
00516         SAVEFREE(Line);
00517         fclose(file);
00518 
00519         *outData = (Pixel*)m_BitmapData;
00520         return true;
00521         #undef SAVEEXIT
00522 }
00523 
00524 bool myLoadUncompressedTGA(int& width, int& height, Pixel** outData, FILE * datei){
00525         uchar header[6];
00526         uint bytesPerPixel;
00527         uint size;
00528         uchar* data;
00529 
00530         if(fread(header, sizeof(header), 1, datei) == 0)
00531                 return false;
00532 
00533         width  = header[1] * 256 + header[0]; // Determine The TGA Width  (highbyte*256+lowbyte)
00534         height = header[3] * 256 + header[2]; // Determine The TGA Height (highbyte*256+lowbyte)
00535 
00536         if((width <= 0) || (height <= 0))
00537                 return false;
00538 
00539         bytesPerPixel = header[4] / 8;
00540         size = bytesPerPixel * width * height;
00541         data = (uchar*)malloc(sizeof(Pixel) * width * height);
00542 
00543         if(fread(data, 1, size, datei) != size){
00544                 free(data);
00545                 return false;
00546         }
00547 
00548         for(uint cswap = 0; cswap < size; cswap += bytesPerPixel)
00549                 data[cswap] ^= data[cswap+2] ^= data[cswap] ^= data[cswap+2];
00550 
00551         *outData = (Pixel*)data;
00552 
00553         if(bytesPerPixel == 3)
00554         {
00555                 for(int i=width*height-1, j=3*width*height-3; i>=0; i--, j-=3)
00556                 {
00557                         (*outData)[i].canal[3] = 255;
00558                         (*outData)[i].canal[2] = data[j+2];
00559                         (*outData)[i].canal[1] = data[j+1];
00560                         (*outData)[i].canal[0] = data[j+0];
00561                 }
00562         }
00563 
00564         return true;
00565 }
00566 
00567 bool myLoadCompressedTGA(int& width, int& height, Pixel** outData, FILE * datei){
00568         uchar header[6];
00569         uint bytesPerPixel;
00570         uint size;
00571         uchar* data;
00572         uchar counter;
00573 
00574         if(fread(header, sizeof(header), 1, datei) == 0)
00575                 return false;
00576 
00577         width  = header[1] * 256 + header[0]; // Determine The TGA Width  (highbyte*256+lowbyte)
00578         height = header[3] * 256 + header[2]; // Determine The TGA Height (highbyte*256+lowbyte)
00579 
00580         if((width <= 0) || (height <= 0))
00581                 return false;
00582 
00583         bytesPerPixel = header[4] / 8;
00584         size = bytesPerPixel * width * height;
00585         data = (uchar*)malloc(sizeof(Pixel) * width * height);
00586 
00587         // Nuber of pixels in the image
00588         uint pixelcount = width * height;
00589         // Current pixel being read
00590         uint currentpixel = 0;
00591         // Current byte 
00592         uint currentbyte = 0;
00593         // Storage for 1 pixel
00594         uchar colorbuffer[4];
00595 
00596         do{
00597                 // Storage for "chunk" header
00598                 uchar chunkheader = 0;
00599 
00600                 // Read in the 1 byte header
00601                 if(fread(&chunkheader, sizeof(uchar), 1, datei) == 0){
00602                         free(data);
00603                         return false;
00604                 }
00605 
00606                 if(chunkheader < 128){
00607                         chunkheader++;
00608                         // If the ehader is < 128, it means the that is the number of RAW color packets minus 1
00609                         // that follow the header add 1 to get number of following color values
00610                         // Read RAW color values
00611                         for(counter = 0; counter < chunkheader; counter++){
00612                                 // Try to read 1 pixel
00613                                 if(fread(colorbuffer, 1, bytesPerPixel, datei) != bytesPerPixel){
00614                                         free(data);
00615                                         return false;
00616                                 }
00617                                 
00618                                 // write to memory
00619                                 // Flip R and B vcolor values around in the process
00620                                 data[currentbyte  ] = colorbuffer[2];
00621                                 data[currentbyte+1] = colorbuffer[1];
00622                                 data[currentbyte+2] = colorbuffer[0];
00623 
00624                                 // if its a 32 bpp image
00625                                 // copy the 4th byte
00626                                 if(bytesPerPixel == 4)
00627                                         data[currentbyte+3] = colorbuffer[3];
00628 
00629                                 currentbyte += bytesPerPixel;
00630                                 currentpixel++;
00631 
00632                                 // Make sure we havent read too many pixels
00633                                 if(currentpixel > pixelcount){
00634                                         free(data);
00635                                         return false;
00636                                 }
00637                         }
00638                 }
00639                 // chunkheader > 128 RLE data, next color reapeated chunkheader - 127 times
00640                 else{
00641                         // Subteact 127 to get rid of the ID bit
00642                         chunkheader -= 127;
00643 
00644                         // Attempt to read following color values
00645                         if(fread(colorbuffer, 1, bytesPerPixel, datei) != bytesPerPixel){
00646                                 free(data);
00647                                 return false;
00648                         }
00649 
00650                         // copy the color into the image data as many times as dictated 
00651                         // by the header
00652                         for(counter = 0; counter < chunkheader; counter++){
00653                                 // switch R and B bytes areound while copying
00654                                 data[currentbyte  ] = colorbuffer[2];
00655                                 data[currentbyte+1] = colorbuffer[1];
00656                                 data[currentbyte+2] = colorbuffer[0];
00657 
00658                                 // If TGA images is 32 bpp
00659                                 if(bytesPerPixel == 4)
00660                                         // Copy 4th byte
00661                                         data[currentbyte + 3] = colorbuffer[3];
00662 
00663                                 currentbyte += bytesPerPixel;
00664                                 currentpixel++;
00665 
00666                                 // Make sure we havent written too many pixels
00667                                 if(currentpixel > pixelcount){
00668                                         free(data);
00669                                         return false;
00670                                 }
00671                         }
00672                 }
00673         // Loop while there are still pixels left
00674         }while(currentpixel < pixelcount);
00675 
00676         *outData = (Pixel*)data;
00677 
00678         if(bytesPerPixel == 3)
00679         {
00680                 for(int i=width*height-1, j=3*width*height-3; i>=0; i--, j-=3)
00681                 {
00682                         (*outData)[i].canal[3] = 255;
00683                         (*outData)[i].canal[2] = data[j+2];
00684                         (*outData)[i].canal[1] = data[j+1];
00685                         (*outData)[i].canal[0] = data[j+0];
00686                 }
00687         }
00688         
00689         return true;
00690 }
00691 
00692 bool loadTGA(const wchar* filename, int& width, int& height, Pixel** outData){
00693         bool ok;
00694         FILE* file;
00695         uchar tgaheader[12];
00696         // Uncompressed TGA Header
00697         uchar uTGAcompare[12] = {0,0, 2,0,0,0,0,0,0,0,0,0};
00698         // Compressed TGA Header
00699         uchar cTGAcompare[12] = {0,0,10,0,0,0,0,0,0,0,0,0};
00700 
00701         if(_wfopen_s(&file, filename, TEXT("rb")) != 0)
00702                 return false;
00703 
00704         #define CHECK(_b) if(_b){fclose(file);return false;}
00705 
00706         CHECK(fread(&tgaheader, sizeof(tgaheader), 1, file) == 0);
00707 
00708         // load TGA data
00709         // load uncompressed data
00710         if(memcmp(uTGAcompare, &tgaheader, sizeof(tgaheader)) == 0)
00711                 ok = myLoadUncompressedTGA(width, height, outData, file);
00712         // load compressed data
00713         else if(memcmp(cTGAcompare, &tgaheader, sizeof(tgaheader)) == 0)
00714                 ok = myLoadCompressedTGA(width, height, outData, file);
00715         // this is no TGA file
00716         else
00717                 ok = false;
00718 
00719         // check for errors
00720         CHECK(ok == false);
00721 
00722         // close file
00723         fclose(file);
00724 
00725         #undef CHECK
00726         return true;
00727 }

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