- Main Page
- Classes
- Files

- File List
- File Members

# flTextureBMP.c

Go to the documentation of this file.

    00001 #include "flGlobal.h"
    00002 #if FL_TEXTURE_BMP != 0
    00003 #include <stdlib.h>
    00004 #include <string.h>
    00005 #include <pspgu.h>
    00006
    00007 #if FL_INCLUDE_ALL_C == 0
    00008 #include "flTextureBMP.h"
    00009 #include "flMemory.h"
    00010 #include "flFile.h"
    00011
    00012 #if FL_DEBUG != 0
    00013 #include "flDebug.h"
    00014 #endif
    00015 #endif
    00016
    00017 #include "flTextureBMPWinPal.c"
    00018
    00019 typedef struct {
    00020      u8  bmpSignature[2];
    00021      u32 bmpFileSize;
    00022      s16 bmpReserved[2];
    00023      u32 bmpDataOffset;
    00024 } bmpHeader;
    00025
    00026 /* THESE STRUCTS ARE KEPT HERE FOR REFERENCE
    00027
    00028 typedef struct {
    00029     u16 Type;
    00030     u16 Width;
    00031     u16 Height;
    00032     u16 bmpByteWidth;
    00033     u8  bmpPlanes;
    00034     u8  bmpBPP;
    00035 } bmpInfoHeaderWV1;
    00036
    00037 typedef struct {
    00038      u32 bmpSize;
    00039      u16 bmpWidth;
    00040      u16 bmpHeight;
    00041      u16 bmpPlanes;
    00042      u16 bmpBPP;
    00043 } bmpInfoHeaderWV2;
    00044
    00045 typedef struct {
    00046      u32 bmpSize;
    00047      s32 bmpWidth;
    00048      s32 bmpHeight;
    00049      u16 bmpPlanes;
    00050      u16 bmpBPP;
    00051      u32 bmpCompression;
    00052      u32 bmpImageSize;
    00053      s32 bmpXResolution;
    00054      s32 bmpYResolution;
    00055      u32 bmpColorsUsed;
    00056      u32 bmpColorsImportant;
    00057 } bmpInfoHeaderWV3;
    00058
    00059 typedef struct {
    00060      u32 bmpSize;
    00061      s32 bmpWidth;
    00062      s32 bmpHeight;
    00063      u16 bmpPlanes;
    00064      u16 bmpBPP;
    00065      u32 bmpCompression;
    00066      u32 bmpSizeImage;
    00067      s32 bmpXResolution;
    00068      s32 bmpYResolution;
    00069      u32 bmpColorsUsed;
    00070      u32 bmpColorsImportant;
    00071      u32 bmpRedMask;
    00072      u32 bmpGreenMask;
    00073      u32 bmpBlueMask;
    00074      u32 bmpAlphaMask;
    00075      u32 bmpCSType;
    00076      s32 bmpEndpoints[9];
    00077      u32 bmpGammaRed;
    00078      u32 bmpGammaGreen;
    00079      u32 bmpGammaBlue;
    00080 } bmpInfoHeaderWV4;
    00081
    00082 typedef struct {
    00083      u32 bmpSize;
    00084      s32 bmpWidth;
    00085      s32 bmpHeight;
    00086      u16 bmpPlanes;
    00087      u16 bmpBPP;
    00088      u32 bmpCompression;
    00089      u32 bmpImageSize;
    00090      s32 bmpXResolution;
    00091      s32 bmpYResolution;
    00092      u32 bmpColorsUsed;
    00093      u32 bmpColorsImportant;
    00094      u32 bmpRedMask;
    00095      u32 bmpGreenMask;
    00096      u32 bmpBlueMask;
    00097      u32 bmpAlphaMask;
    00098      u32 bmpCSType;
    00099      s32 bmpEndpoints[9];
    00100      u32 bmpGammaRed;
    00101      u32 bmpGammaGreen;
    00102      u32 bmpGammaBlue;
    00103      u32 bmpIntent;
    00104      u32 bmpProfileData;
    00105      u32 bmpProfileSize;
    00106      u32 bmpReserved;
    00107 } bmpInfoHeaderWV5;
    00108
    00109 typedef struct {
    00110      u32 bmpSize;
    00111      u16 bmpWidth;
    00112      u16 bmpHeight;
    00113      u16 bmpPlanes;
    00114      u16 bmpBPP;
    00115 } bmpInfoHeaderOS2V1;
    00116
    00117 typedef struct {
    00118      u32 bmpSize;
    00119      u32 bmpWidth;
    00120      u32 bmpHeight;
    00121      u16 bmpPlanes;
    00122      u16 bmpBPP;
    00123      u32 bmpCompression;
    00124      u32 bmpImageSize;
    00125      u32 bmpXResolution;
    00126      u32 bmpYResolution;
    00127      u32 bmpColorsUsed;
    00128      u32 bmpColorsImportant;
    00129      u16 bmpUnits;
    00130      u16 bmpReserved;
    00131      u16 bmpRecording;
    00132      u16 bmpRendering;
    00133      u32 bmpSize1;
    00134      u32 bmpSize2;
    00135      u32 bmpColorEncoding;
    00136      u32 bmpIdentifier;
    00137 } bmpInfoHeaderOS2V2;*/
    00138
    00139 typedef struct {
    00140      u16 bmpType;
    00141      u32 bmpSize;
    00142      s32 bmpWidth;
    00143      s32 bmpHeight;
    00144      u16 bmpByteWidth;
    00145      u16 bmpPlanes;
    00146      u16 bmpBPP;
    00147      u32 bmpCompression;
    00148      u32 bmpImageSize;
    00149      s32 bmpXResolution;
    00150      s32 bmpYResolution;
    00151      u32 bmpColorsUsed;
    00152      u32 bmpColorsImportant;
    00153      u32 bmpRedMask;
    00154      u32 bmpGreenMask;
    00155      u32 bmpBlueMask;
    00156      u32 bmpAlphaMask;
    00157      u32 bmpCSType;
    00158      s32 bmpEndpoints[9];
    00159      u32 bmpGammaRed;
    00160      u32 bmpGammaGreen;
    00161      u32 bmpGammaBlue;
    00162      u32 bmpIntent;
    00163      u32 bmpProfileData;
    00164      u32 bmpProfileSize;
    00165      u16 bmpUnits;
    00166      u16 bmpReserved;
    00167      u16 bmpRecording;
    00168      u16 bmpRendering;
    00169      u32 bmpSize1;
    00170      u32 bmpSize2;
    00171      u32 bmpColorEncoding;
    00172      u32 bmpIdentifier;
    00173 } bmpInfoHeaderGeneric;
    00174
    00175 #define BMP_WIN_COMPRESSION_RGB       0
    00176 #define BMP_WIN_COMPRESSION_RLE8      1
    00177 #define BMP_WIN_COMPRESSION_RLE4      2
    00178 #define BMP_WIN_COMPRESSION_BITFIELDS 3
    00179 #define BMP_WIN_COMPRESSION_JPEG      4
    00180 #define BMP_WIN_COMPRESSION_PNG       5
    00181
    00182 #define BMP_OS2_COMPRESSION_NONE      0
    00183 #define BMP_OS2_COMPRESSION_RLE8      1
    00184 #define BMP_OS2_COMPRESSION_RLE4      2
    00185 #define BMP_OS2_COMPRESSION_HUFF1D    3
    00186 #define BMP_OS2_COMPRESSION_RLE24     4
    00187
    00188 #define BMP_GEN_COMPRESSION_RGB       0
    00189 #define BMP_GEN_COMPRESSION_RLE4      1
    00190 #define BMP_GEN_COMPRESSION_RLE8      2
    00191 #define BMP_GEN_COMPRESSION_HUFF1D    3
    00192 #define BMP_GEN_COMPRESSION_RLE24     4
    00193 #define BMP_GEN_COMPRESSION_BITFIELDS 5
    00194 #define BMP_GEN_COMPRESSION_JPEG      6
    00195 #define BMP_GEN_COMPRESSION_PNG       7
    00196
    00197 #define BMP_HEADER_OS2V1 12
    00198 #define BMP_HEADER_OS2V2 64
    00199 #define BMP_HEADER_WV1   10
    00200 #define BMP_HEADER_WV2   12
    00201 #define BMP_HEADER_WV3   40
    00202 #define BMP_HEADER_WV4   108
    00203 #define BMP_HEADER_WV5   124
    00204
    00205
    00206 Texture* texLoadBMP(char* inPath) {
    00207      #if FL_FILE != 0
    00208      File* tempFile = fileOpen(inPath, FILE_MODE_READ | FILE_MODE_BINARY);
    00209      #else
    00210      FILE* tempFile = fopen(inPath, "rb");
    00211      #endif
    00212      if(!tempFile) {
    00213           #if FL_DEBUG_ERROR != 0
    00214           char tempString[256];
    00215           sprintf(tempString, "BMP load error (%s).\nFile cannot be opened", inPath);
    00216           debugError(tempString);
    00217           #endif
    00218           return NULL;
    00219      }
    00220
    00221      bmpHeader tempHeader;
    00222      fileRead(tempHeader.bmpSignature, 2, tempFile);
    00223      fileRead(&tempHeader.bmpFileSize, 4, tempFile);
    00224      fileRead(tempHeader.bmpReserved, 4, tempFile);
    00225      fileRead(&tempHeader.bmpDataOffset, 4, tempFile);
    00226
    00227      if((tempHeader.bmpSignature[0] != 'B') || (tempHeader.bmpSignature[1] != 'M')) {
    00228           fileClose(tempFile);
    00229           #if FL_DEBUG_WARNING != 0
    00230           debugWarning("Only BM type bitmaps are supported, not icons, pointers, arrays, etc.");
    00231           #endif
    00232           return NULL;
    00233      }
    00234
    00235      int i, j, k;
    00236
    00237      bmpInfoHeaderGeneric tempInfoHeader;
    00238      fileRead(&tempInfoHeader.bmpSize, 4, tempFile);
    00239      tempInfoHeader.bmpType = 0;
    00240      tempInfoHeader.bmpSize = tempInfoHeader.bmpSize;
    00241      tempInfoHeader.bmpWidth = 0;
    00242      tempInfoHeader.bmpHeight = 0;
    00243      tempInfoHeader.bmpByteWidth = 0;
    00244      tempInfoHeader.bmpPlanes = 1;
    00245      tempInfoHeader.bmpBPP = 24;
    00246      tempInfoHeader.bmpCompression = 0;
    00247      tempInfoHeader.bmpImageSize = 0;
    00248      tempInfoHeader.bmpXResolution = 0;
    00249      tempInfoHeader.bmpYResolution = 0;
    00250      tempInfoHeader.bmpColorsUsed = 0;
    00251      tempInfoHeader.bmpColorsImportant = 0;
    00252      tempInfoHeader.bmpRedMask = 0;
    00253      tempInfoHeader.bmpGreenMask = 0;
    00254      tempInfoHeader.bmpBlueMask = 0;
    00255      tempInfoHeader.bmpAlphaMask = 0xFF000000;
    00256      tempInfoHeader.bmpCSType = 1;
    00257      for(i = 0; i < 9; i++)
    00258           tempInfoHeader.bmpEndpoints[i] = 0;
    00259      tempInfoHeader.bmpGammaRed = 0;
    00260      tempInfoHeader.bmpGammaGreen = 0;
    00261      tempInfoHeader.bmpGammaBlue = 0;
    00262      tempInfoHeader.bmpIntent = 0;
    00263      tempInfoHeader.bmpProfileData = 0;
    00264      tempInfoHeader.bmpProfileSize = 0;
    00265      tempInfoHeader.bmpReserved = 0;
    00266      tempInfoHeader.bmpUnits = 0;
    00267      tempInfoHeader.bmpRecording = 0;
    00268      tempInfoHeader.bmpRendering = 0;
    00269      tempInfoHeader.bmpSize1 = 0;
    00270      tempInfoHeader.bmpSize2 = 0;
    00271      tempInfoHeader.bmpColorEncoding = 0;
    00272      tempInfoHeader.bmpIdentifier = 0;
    00273
    00274      if(tempInfoHeader.bmpSize == BMP_HEADER_WV1) {
    00275           fileRead(&tempInfoHeader.bmpType, 2, tempFile);
    00276           if(tempInfoHeader.bmpType) {
    00277                fileClose(tempFile);
    00278                #if FL_DEBUG_WARNING != 0
    00279                debugWarning("Windows bitmap type value not supported.");
    00280                #endif
    00281                return NULL;
    00282           }
    00283           fileRead(&tempInfoHeader.bmpWidth, 2, tempFile);
    00284           fileRead(&tempInfoHeader.bmpHeight, 2, tempFile);
    00285           fileRead(&tempInfoHeader.bmpByteWidth, 2, tempFile);
    00286           fileRead(&tempInfoHeader.bmpPlanes, 1, tempFile);
    00287           fileRead(&tempInfoHeader.bmpBPP, 1, tempFile);
    00288      } else if((tempInfoHeader.bmpSize == BMP_HEADER_WV3) || (tempInfoHeader.bmpSize == BMP_HEADER_WV4) || (tempInfoHeader.bmpSize == BMP_HEADER_WV5)) {
    00289           fileRead(&tempInfoHeader.bmpWidth, 4, tempFile);
    00290           fileRead(&tempInfoHeader.bmpHeight, 4, tempFile);
    00291           fileRead(&tempInfoHeader.bmpPlanes, 2, tempFile);
    00292           fileRead(&tempInfoHeader.bmpBPP, 2, tempFile);
    00293           fileRead(&tempInfoHeader.bmpCompression, 4, tempFile);
    00294           fileRead(&tempInfoHeader.bmpImageSize, 4, tempFile);
    00295           fileRead(&tempInfoHeader.bmpXResolution, 4, tempFile);
    00296           fileRead(&tempInfoHeader.bmpYResolution, 4, tempFile);
    00297           fileRead(&tempInfoHeader.bmpColorsUsed, 4, tempFile);
    00298           fileRead(&tempInfoHeader.bmpColorsImportant, 4, tempFile);
    00299           if(tempInfoHeader.bmpSize >= BMP_HEADER_WV4) {
    00300                fileRead(&tempInfoHeader.bmpRedMask, 4, tempFile);
    00301                fileRead(&tempInfoHeader.bmpGreenMask, 4, tempFile);
    00302                fileRead(&tempInfoHeader.bmpBlueMask, 4, tempFile);
    00303                fileRead(&tempInfoHeader.bmpAlphaMask, 4, tempFile);
    00304                fileRead(&tempInfoHeader.bmpCSType, 4, tempFile);
    00305                fileRead(tempInfoHeader.bmpEndpoints, 36, tempFile);
    00306                fileRead(&tempInfoHeader.bmpGammaRed, 4, tempFile);
    00307                fileRead(&tempInfoHeader.bmpGammaGreen, 4, tempFile);
    00308                fileRead(&tempInfoHeader.bmpGammaBlue, 4, tempFile);
    00309                if(tempInfoHeader.bmpSize == BMP_HEADER_WV5) {
    00310                          fileRead(&tempInfoHeader.bmpIntent, 4, tempFile);
    00311                          fileRead(&tempInfoHeader.bmpProfileData, 4, tempFile);
    00312                          fileRead(&tempInfoHeader.bmpProfileSize, 4, tempFile);
    00313                          fileRead(&tempInfoHeader.bmpReserved, 4, tempFile);
    00314                }
    00315           }
    00316           if((tempInfoHeader.bmpCompression == 3) && (tempInfoHeader.bmpSize == BMP_HEADER_WV3)) {
    00317                fileRead(&tempInfoHeader.bmpRedMask, 4, tempFile);
    00318                fileRead(&tempInfoHeader.bmpGreenMask, 4, tempFile);
    00319                fileRead(&tempInfoHeader.bmpBlueMask, 4, tempFile);
    00320                tempInfoHeader.bmpCompression += 2;
    00321           } else if(tempInfoHeader.bmpCompression >= 3) {
    00322                fileClose(tempFile);
    00323                #if FL_DEBUG_WARNING != 0
    00324                switch(tempInfoHeader.bmpCompression) {
    00325                     case BMP_WIN_COMPRESSION_JPEG:
    00326                          debugWarning("JPEG compression not supported.");
    00327                          return NULL;
    00328                     case BMP_WIN_COMPRESSION_PNG:
    00329                          debugWarning("PNG compression not supported within bitmaps.");
    00330                          return NULL;
    00331                }
    00332                debugWarning("Unknown bitmap compression type.");
    00333                #endif
    00334                return NULL;
    00335                //tempInfoHeader.bmpCompression += 2;
    00336           }
    00337      } else if(tempInfoHeader.bmpSize == BMP_HEADER_OS2V1) {
    00338           fileRead(&tempInfoHeader.bmpWidth, 2, tempFile);
    00339           fileRead(&tempInfoHeader.bmpHeight, 2, tempFile);
    00340           fileRead(&tempInfoHeader.bmpPlanes, 2, tempFile);
    00341           fileRead(&tempInfoHeader.bmpBPP, 2, tempFile);
    00342      } else if(tempInfoHeader.bmpSize == BMP_HEADER_OS2V2) {
    00343           fileRead(&tempInfoHeader.bmpWidth, 4, tempFile);
    00344           fileRead(&tempInfoHeader.bmpHeight, 4, tempFile);
    00345           fileRead(&tempInfoHeader.bmpPlanes, 2, tempFile);
    00346           fileRead(&tempInfoHeader.bmpBPP, 2, tempFile);
    00347           fileRead(&tempInfoHeader.bmpCompression, 4, tempFile);
    00348           fileRead(&tempInfoHeader.bmpImageSize, 4, tempFile);
    00349           fileRead(&tempInfoHeader.bmpXResolution, 4, tempFile);
    00350           fileRead(&tempInfoHeader.bmpYResolution, 4, tempFile);
    00351           fileRead(&tempInfoHeader.bmpColorsUsed, 4, tempFile);
    00352           fileRead(&tempInfoHeader.bmpColorsImportant, 4, tempFile);
    00353           fileRead(&tempInfoHeader.bmpUnits, 2, tempFile);
    00354           fileRead(&tempInfoHeader.bmpReserved, 2, tempFile);
    00355           fileRead(&tempInfoHeader.bmpRecording, 2, tempFile);
    00356           fileRead(&tempInfoHeader.bmpRendering, 2, tempFile);
    00357           fileRead(&tempInfoHeader.bmpSize1, 4, tempFile);
    00358           fileRead(&tempInfoHeader.bmpSize2, 4, tempFile);
    00359           fileRead(&tempInfoHeader.bmpColorEncoding,4, tempFile);
    00360           fileRead(&tempInfoHeader.bmpIdentifier, 4, tempFile);
    00361           if(tempInfoHeader.bmpCompression == 3) {
    00362                fileClose(tempFile);
    00363                #if FL_DEBUG_WARNING != 0
    00364                debugWarning("Huffman 1D compression not supported.");
    00365                #endif
    00366                return NULL;
    00367           } else if(tempInfoHeader.bmpCompression >= 5) {
    00368                fileClose(tempFile);
    00369                #if FL_DEBUG_WARNING != 0
    00370                debugWarning("Unknown bitmap compression type.");
    00371                #endif
    00372                return NULL;
    00373           }
    00374      } else {
    00375           fileClose(tempFile);
    00376           #if FL_DEBUG_WARNING != 0
    00377           debugWarning("Bitmap header type invalid.");
    00378           #endif
    00379           return NULL;
    00380      }
    00381
    00382      if((!tempInfoHeader.bmpWidth) || (!tempInfoHeader.bmpHeight)) {
    00383           fileClose(tempFile);
    00384           #if FL_DEBUG_WARNING != 0
    00385           debugWarning("Bitmap dimensions invalid.");
    00386           #endif
    00387           return NULL;
    00388      }
    00389
    00390      if((tempInfoHeader.bmpColorEncoding) || (tempInfoHeader.bmpCSType != 1)) {
    00391           fileClose(tempFile);
    00392           #if FL_DEBUG_WARNING != 0
    00393           debugWarning("Invalid color model / color space.");
    00394           #endif
    00395           return NULL;
    00396      }
    00397      if(tempInfoHeader.bmpRecording) {
    00398           fileClose(tempFile);
    00399           #if FL_DEBUG_WARNING != 0
    00400           debugWarning("Invalid recording mode.");
    00401           #endif
    00402           return NULL;
    00403      }
    00404      if(tempInfoHeader.bmpPlanes & 0xFE) {
    00405           fileClose(tempFile);
    00406           #if FL_DEBUG_WARNING != 0
    00407           debugWarning("Multiple color planes not supported.");
    00408           #endif
    00409           return NULL;
    00410      }
    00411
    00412      bool tempVFlip = !(tempInfoHeader.bmpHeight < 0);
    00413      bool tempHFlip = (tempInfoHeader.bmpWidth < 0);
    00414      tempInfoHeader.bmpWidth = pos(tempInfoHeader.bmpWidth);
    00415      tempInfoHeader.bmpHeight = pos(tempInfoHeader.bmpHeight);
    00416
    00417      if(tempInfoHeader.bmpBPP == 1) {
    00418           while(tempInfoHeader.bmpWidth & 7)
    00419                tempInfoHeader.bmpWidth++;
    00420      } else if(tempInfoHeader.bmpBPP == 2) {
    00421           while(tempInfoHeader.bmpWidth & 3)
    00422                tempInfoHeader.bmpWidth++;
    00423      } else if(tempInfoHeader.bmpBPP == 4) {
    00424           if(tempInfoHeader.bmpWidth & 1)
    00425                tempInfoHeader.bmpWidth++;
    00426      }
    00427
    00428      if(!tempInfoHeader.bmpByteWidth) {
    00429           if(tempInfoHeader.bmpSize == BMP_HEADER_WV1) {
    00430                tempInfoHeader.bmpByteWidth = (tempInfoHeader.bmpWidth * tempInfoHeader.bmpBPP);
    00431                while(tempInfoHeader.bmpByteWidth & 7)
    00432                     tempInfoHeader.bmpByteWidth++;
    00433                tempInfoHeader.bmpByteWidth >>= 3;
    00434           } else {
    00435                tempInfoHeader.bmpByteWidth = (tempInfoHeader.bmpWidth * tempInfoHeader.bmpBPP);
    00436                while(tempInfoHeader.bmpByteWidth & 7)
    00437                     tempInfoHeader.bmpByteWidth++;
    00438                tempInfoHeader.bmpByteWidth >>= 3;
    00439                while(tempInfoHeader.bmpByteWidth & 3)
    00440                     tempInfoHeader.bmpByteWidth++;
    00441           }
    00442      }
    00443
    00444      if(!tempInfoHeader.bmpImageSize)
    00445           tempInfoHeader.bmpImageSize = ((tempInfoHeader.bmpWidth * tempInfoHeader.bmpHeight * tempInfoHeader.bmpBPP) >> 3);
    00446
    00447      int tempPixelFormat;
    00448      #if FL_TEXTURE_PRESERVENONALPHA != 0
    00449      bool tempAlpha = false;
    00450      #endif
    00451      switch(tempInfoHeader.bmpBPP) {
    00452           case 1:
    00453           case 2:
    00454           case 4:
    00455                tempPixelFormat = GU_PSM_T4;
    00456                break;
    00457           case 8:
    00458                tempPixelFormat = GU_PSM_T8;
    00459                break;
    00460           case 16:
    00461                if(tempInfoHeader.bmpSize >= BMP_HEADER_WV4) {
    00462                     if(tempInfoHeader.bmpAlphaMask == 0x0000F000) {
    00463                          tempPixelFormat = GU_PSM_4444;
    00464                          #if FL_TEXTURE_PRESERVENONALPHA != 0
    00465                          tempAlpha = true;
    00466                          #endif
    00467                     } else if(tempInfoHeader.bmpAlphaMask == 0x00008000) {
    00468                          tempPixelFormat = GU_PSM_5551;
    00469                          #if FL_TEXTURE_PRESERVENONALPHA != 0
    00470                          tempAlpha = true;
    00471                          #endif
    00472                     } else {
    00473                          tempPixelFormat = GU_PSM_5650;
    00474                     }
    00475                } else {
    00476                     tempPixelFormat = GU_PSM_5650;
    00477                }
    00478                break;
    00479           case 24:
    00480                tempPixelFormat = GU_PSM_8888;
    00481                break;
    00482           case 32:
    00483                tempPixelFormat = GU_PSM_8888;
    00484                #if FL_TEXTURE_PRESERVENONALPHA != 0
    00485                tempAlpha = true;
    00486                #endif
    00487                break;
    00488           default:
    00489                fileClose(tempFile);
    00490                #if FL_DEBUG_WARNING != 0
    00491                debugWarning("BPP not supported.");
    00492                #endif
    00493                return NULL;
    00494      }
    00495
    00496      Palette* tempPal = NULL;
    00497      int tempPalEntries = tempInfoHeader.bmpColorsUsed;
    00498      if(!tempPalEntries)
    00499           tempPalEntries = (1 << tempInfoHeader.bmpBPP);
    00500      if(tempPixelFormat > GU_PSM_8888) {
    00501           if((tempInfoHeader.bmpSize >= BMP_HEADER_OS2V1) || (tempInfoHeader.bmpBPP == 8))
    00502                tempPal = palCreate(tempPalEntries, GU_PSM_8888, false);
    00503           else if(tempInfoHeader.bmpBPP == 4)
    00504                tempPal = palCreateDefaultColorT4();
    00505           else
    00506                tempPal = palCreateGrayscaleT4();
    00507           if(!tempPal) {
    00508                fileClose(tempFile);
    00509                #if FL_DEBUG_WARNING != 0
    00510                debugWarning("Couldn't create bmp palette, probably out of memory.");
    00511                #endif
    00512                return NULL;
    00513           }
    00514           if(tempInfoHeader.bmpSize >= BMP_HEADER_OS2V1) {
    00515                for(i = 0; i < tempPalEntries; i++) {
    00516                     fileRead(&tempPal->palData[(i << 2) + 0], 1, tempFile);
    00517                     fileRead(&tempPal->palData[(i << 2) + 1], 1, tempFile);
    00518                     fileRead(&tempPal->palData[(i << 2) + 2], 1, tempFile);
    00519                     if(tempInfoHeader.bmpSize > BMP_HEADER_OS2V1)
    00520                          fileRead(&tempPal->palData[(i << 2) + 3], 1, tempFile);
    00521                     tempPal->palData[(i << 2) + 3] = 0xFF;
    00522                }
    00523           } else {
    00524                memCopy(tempPal->palData, bmpWinPal, 0x300);
    00525           }
    00526      }
    00527
    00528      if(tempHeader.bmpDataOffset != 0)
    00529           fileSeek(tempFile, tempHeader.bmpDataOffset, FILE_SEEK_SET);
    00530
    00531      u8* tempData = (u8*)memQalloc((tempInfoHeader.bmpWidth * tempInfoHeader.bmpHeight * tempInfoHeader.bmpBPP) >> 3);
    00532      if(!tempData) {
    00533           fileClose(tempFile);
    00534           if(tempPal)
    00535                palFree(tempPal);
    00536           #if FL_DEBUG_WARNING != 0
    00537           debugWarning("Couldn't create data buffer while loading bmp.\nProbably out of memory.");
    00538           #endif
    00539           return NULL;
    00540      }
    00541
    00542      int tempLineSize = ((tempInfoHeader.bmpWidth * tempInfoHeader.bmpBPP) >> 3);
    00543      u32 tempStride = tempLineSize - tempInfoHeader.bmpByteWidth;
    00544      if(tempInfoHeader.bmpCompression) {
    00545           i = 0; j = 0; k = 0;
    00546           u8 tempRleBlock[4];
    00547           if(tempInfoHeader.bmpCompression == BMP_GEN_COMPRESSION_RLE4) {
    00548                while(flRunning && (fileRead(tempRleBlock, 2, tempFile) == 2)) {
    00549                     if(!tempRleBlock[0]) {
    00550                          if(!tempRleBlock[1]) {
    00551                               j++;
    00552                               if(j >= tempInfoHeader.bmpHeight)
    00553                                    break;
    00554                               continue;
    00555                          } else if(tempRleBlock[1] == 1) {
    00556                               break;
    00557                          } else if(tempRleBlock[1] == 2) {
    00558                               fileRead(tempRleBlock, 2, tempFile);
    00559                               j -= tempRleBlock[0];
    00560                               i += ((tempRleBlock[1] + 1) >> 1);
    00561                               if(i >= tempInfoHeader.bmpWidth) {
    00562                                    j++;
    00563                                    i -= tempLineSize;
    00564                               }
    00565                               if((j < 0) || (j >= tempInfoHeader.bmpHeight)) {
    00566                                    #if FL_DEBUG_WARNING != 0
    00567                                    debugWarning("BMP RLE4 decoding error.");
    00568                                    #endif
    00569                                    break;
    00570                               }
    00571                          } else {
    00572                               for(k = 0; k < ((tempRleBlock[0] + 1) >> 1); k++) {
    00573                                    if(j >= tempInfoHeader.bmpHeight)
    00574                                         break;
    00575                                    fileRead(&tempData[(j * tempLineSize) + i], 1, tempFile);
    00576                                    if((k == (tempRleBlock[0] >> 1)) && (tempRleBlock[0] & 1))
    00577                                         tempData[(j * tempLineSize) + i] &= 0xF0;
    00578                                    i++;
    00579                                    if(i >= tempInfoHeader.bmpWidth) {
    00580                                         j++;
    00581                                         i -= tempLineSize;
    00582                                    }
    00583                               }
    00584                               if(j >= tempInfoHeader.bmpHeight) {
    00585                                    #if FL_DEBUG_WARNING != 0
    00586                                    debugWarning("BMP RLE4 decoding error.");
    00587                                    #endif
    00588                                    break;
    00589                               }
    00590                          }
    00591                     } else {
    00592                          for(k = 0; k < ((tempRleBlock[0] + 1) >> 1); k++) {
    00593                               if(j >= tempInfoHeader.bmpHeight)
    00594                                    break;
    00595                               tempData[(j * tempLineSize) + i] = tempRleBlock[1];
    00596                               if((k == (tempRleBlock[0] >> 1)) && (tempRleBlock[0] & 1))
    00597                                    tempData[(j * tempLineSize) + i] &= 0xF0;
    00598                               i++;
    00599                               if(i >= tempInfoHeader.bmpWidth) {
    00600                                    j++;
    00601                                    i -= tempLineSize;
    00602                               }
    00603                          }
    00604                          if(j >= tempInfoHeader.bmpHeight) {
    00605                               #if FL_DEBUG_WARNING != 0
    00606                               debugWarning("BMP RLE4 decoding error.");
    00607                               #endif
    00608                               break;
    00609                          }
    00610                     }
    00611                }
    00612           } else if(tempInfoHeader.bmpCompression == BMP_GEN_COMPRESSION_RLE8) {
    00613                while(flRunning && (fileRead(tempRleBlock, 2, tempFile) == 2)) {
    00614                     if(!tempRleBlock[0]) {
    00615                          if(!tempRleBlock[1]) {
    00616                               j++;
    00617                               if(j >= tempInfoHeader.bmpHeight)
    00618                                    break;
    00619                               continue;
    00620                          } else if(tempRleBlock[1] == 1) {
    00621                               break;
    00622                          } else if(tempRleBlock[1] == 2) {
    00623                               fileRead(tempRleBlock, 2, tempFile);
    00624                               j -= tempRleBlock[0];
    00625                               i += tempRleBlock[1];
    00626                               if(i >= tempInfoHeader.bmpWidth) {
    00627                                    j++;
    00628                                    i -= tempLineSize;
    00629                               }
    00630                               if((j < 0) || (j >= tempInfoHeader.bmpHeight)) {
    00631                                    #if FL_DEBUG_WARNING != 0
    00632                                    debugWarning("BMP RLE8 decoding error.");
    00633                                    #endif
    00634                                    break;
    00635                               }
    00636                          } else {
    00637                               for(k = 0; k < tempRleBlock[1]; k++) {
    00638                                    if(j >= tempInfoHeader.bmpHeight)
    00639                                         break;
    00640                                    fileRead(&tempData[(j * tempLineSize) + i], 1, tempFile);
    00641                                    i++;
    00642                                    if(i >= tempInfoHeader.bmpWidth) {
    00643                                         j++;
    00644                                         i -= tempLineSize;
    00645                                    }
    00646                               }
    00647                               if(j >= tempInfoHeader.bmpHeight) {
    00648                                    #if FL_DEBUG_WARNING != 0
    00649                                    debugWarning("BMP RLE8 decoding error.");
    00650                                    #endif
    00651                                    break;
    00652                               }
    00653                          }
    00654                     } else {
    00655                          for(k = 0; k < tempRleBlock[0]; k++) {
    00656                               if(j >= tempInfoHeader.bmpHeight)
    00657                                    break;
    00658                               tempData[(j * tempLineSize) + i] = tempRleBlock[1];
    00659                               i++;
    00660                               if(i >= tempInfoHeader.bmpWidth) {
    00661                                    j++;
    00662                                    i -= tempLineSize;
    00663                               }
    00664                          }
    00665                          if(j >= tempInfoHeader.bmpHeight) {
    00666                               #if FL_DEBUG_WARNING != 0
    00667                               debugWarning("BMP RLE8 decoding error.");
    00668                               #endif
    00669                               break;
    00670                          }
    00671                     }
    00672                }
    00673           } else if(tempInfoHeader.bmpCompression == BMP_GEN_COMPRESSION_RLE24) {
    00674                while(flRunning && (fileRead(tempRleBlock, 2, tempFile) == 2)) {
    00675                     if(!tempRleBlock[0]) {
    00676                          if(!tempRleBlock[1]) {
    00677                               j++;
    00678                               if(j >= tempInfoHeader.bmpHeight)
    00679                                    break;
    00680                               continue;
    00681                          } else if(tempRleBlock[1] == 1) {
    00682                               break;
    00683                          } else if(tempRleBlock[1] == 2) {
    00684                               fileRead(tempRleBlock, 2, tempFile);
    00685                               j -= tempRleBlock[0];
    00686                               i += (tempRleBlock[1] * 3);
    00687                               if(i >= tempLineSize) {
    00688                                    j++;
    00689                                    i -= tempLineSize;
    00690                               }
    00691                               if((j < 0) || (j >= tempInfoHeader.bmpHeight)) {
    00692                                    #if FL_DEBUG_WARNING != 0
    00693                                    debugWarning("BMP RLE24 decoding error.");
    00694                                    #endif
    00695                                    break;
    00696                               }
    00697                          } else {
    00698                               for(k = 0; k < tempRleBlock[1]; k++) {
    00699                                    if(j >= tempInfoHeader.bmpHeight)
    00700                                         break;
    00701                                    fileRead(&tempData[(j * tempLineSize) + (i * 3)], 3, tempFile);
    00702                                    i += 3;
    00703                                    if(i >= tempLineSize) {
    00704                                         j++;
    00705                                         i -= tempLineSize;
    00706                                    }
    00707                               }
    00708                               if(j >= tempInfoHeader.bmpHeight) {
    00709                                    #if FL_DEBUG_WARNING != 0
    00710                                    debugWarning("BMP RLE24 decoding error.");
    00711                                    #endif
    00712                                    break;
    00713                               }
    00714                          }
    00715                     } else {
    00716                          fileRead(&tempRleBlock[2], 2, tempFile);
    00717                          for(k = 0; k < tempRleBlock[0]; k++) {
    00718                               if(j >= tempInfoHeader.bmpHeight)
    00719                                    break;
    00720                               tempData[(j * tempLineSize) + i + 0] = tempRleBlock[1];
    00721                               tempData[(j * tempLineSize) + i + 1] = tempRleBlock[2];
    00722                               tempData[(j * tempLineSize) + i + 2] = tempRleBlock[3];
    00723                               i += 3;
    00724                               if(i >= tempLineSize) {
    00725                                    j++;
    00726                                    i -= tempLineSize;
    00727                               }
    00728                          }
    00729                          if(j >= tempInfoHeader.bmpHeight) {
    00730                               #if FL_DEBUG_WARNING != 0
    00731                               debugWarning("BMP RLE24 decoding error.");
    00732                               #endif
    00733                               break;
    00734                          }
    00735                     }
    00736                }
    00737           }
    00738      } else {
    00739           for(i = (tempInfoHeader.bmpHeight - 1); i >= 0; i--) {
    00740                fileRead(&tempData[i * tempLineSize], tempLineSize, tempFile);
    00741                if(tempStride)
    00742                     fileSeek(tempFile, tempStride, SEEK_CUR);
    00743           }
    00744           tempVFlip = !tempVFlip;
    00745      }
    00746
    00747      fileClose(tempFile);
    00748
    00749      u8* tempLine = NULL;
    00750      if(tempVFlip) {
    00751           tempLine = memAlloc(tempLineSize);
    00752           if(!tempLine) {
    00753                if(tempPal)
    00754                     palFree(tempPal);
    00755                memFree(tempData);
    00756                #if FL_DEBUG_WARNING != 0
    00757                debugWarning("Couldn't create VFlip buffer while loading bmp.\nProbably out of memory.");
    00758                #endif
    00759                return NULL;
    00760           }
    00761           for(i = 0; i < (tempInfoHeader.bmpHeight >> 1); i++) {
    00762                memCopy(tempLine, &tempData[i * tempLineSize], tempLineSize);
    00763                memCopy(&tempData[i * tempLineSize], &tempData[((tempInfoHeader.bmpHeight - 1) - i) * tempLineSize], tempLineSize);
    00764                memCopy(&tempData[((tempInfoHeader.bmpHeight - 1) - i) * tempLineSize], tempLine, tempLineSize);
    00765           }
    00766           memFree(tempLine);
    00767      }
    00768      if(tempHFlip) {
    00769           u8 tempPixel[4];
    00770           for(j = 0; j < tempInfoHeader.bmpHeight; j++) {
    00771                for(i = 0; i < (tempInfoHeader.bmpWidth >> 1); i++) {
    00772                     memCopy(tempPixel, &tempData[(j * tempLineSize) + (i * (tempInfoHeader.bmpBPP >> 3))], (tempInfoHeader.bmpBPP >> 3));
    00773                     memCopy(&tempData[(j * tempLineSize) + (i * (tempInfoHeader.bmpBPP >> 3))], &tempData[(j * tempLineSize) + (((tempInfoHeader.bmpWidth - 1) - i) * (tempInfoHeader.bmpBPP >> 3))], (tempInfoHeader.bmpBPP >> 3));
    00774                     memCopy(&tempData[(j * tempLineSize) + (((tempInfoHeader.bmpWidth - 1) - i) * (tempInfoHeader.bmpBPP >> 3))], tempPixel, (tempInfoHeader.bmpBPP >> 3));
    00775                }
    00776           }
    00777      }
    00778
    00779      if(tempInfoHeader.bmpRedMask || tempInfoHeader.bmpGreenMask || tempInfoHeader.bmpBlueMask) {
    00780           // TODO - Decode bit fields if they exist
    00781           #if FL_DEBUG_WARNING != 0
    00782           debugWarning("Bitmap contains bit-fields, which are currently unsupported.\nSkipping may cause corruption of colors.");
    00783           #endif
    00784      }
    00785
    00786      Texture* tempOut = texCreate(tempInfoHeader.bmpWidth, tempInfoHeader.bmpHeight, tempPixelFormat);
    00787      if(!tempOut) {
    00788           if(tempPal)
    00789                palFree(tempPal);
    00790           memFree(tempData);
    00791           fileClose(tempFile);
    00792           #if FL_DEBUG_WARNING != 0
    00793           char tempString[256];
    00794           sprintf(tempString, "Couldn't create texture struct, while loading \"%s\".\nOut of memory.", inPath);
    00795           debugWarning(tempString);
    00796           #endif
    00797           return NULL;
    00798      }
    00799      tempOut->texPalette = tempPal;
    00800      #if FL_TEXTURE_PRESERVENONALPHA != 0
    00801      tempOut->texAlpha = tempAlpha;
    00802      #endif
    00803
    00804      if((tempInfoHeader.bmpBPP == 32) || (tempInfoHeader.bmpBPP == 16) || (tempInfoHeader.bmpBPP == 8) || (tempInfoHeader.bmpBPP == 4)) {
    00805           for(i = 0; i < tempInfoHeader.bmpHeight; i++)
    00806                memCopy(&tempOut->texData[i * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)], &tempData[i * tempLineSize], tempLineSize);
    00807      } else if(tempInfoHeader.bmpBPP == 24) {
    00808           for(j = 0; j < tempInfoHeader.bmpHeight; j++) {
    00809                for(i = 0; i < tempInfoHeader.bmpWidth; i++) {
    00810                      tempOut->texData[(j * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)) + (i << 2) + 0] = tempData[(j * tempLineSize) + (i * 3) + 0];
    00811                      tempOut->texData[(j * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)) + (i << 2) + 1] = tempData[(j * tempLineSize) + (i * 3) + 1];
    00812                      tempOut->texData[(j * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)) + (i << 2) + 2] = tempData[(j * tempLineSize) + (i * 3) + 2];
    00813                      tempOut->texData[(j * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)) + (i << 2) + 3] = 0xFF;
    00814                }
    00815           }
    00816      } else if(tempInfoHeader.bmpBPP == 2) {
    00817           for(j = 0; j < tempInfoHeader.bmpHeight; j++) {
    00818                if(tempInfoHeader.bmpSize == BMP_HEADER_WV1) {
    00819                     for(i = 0; i < (tempInfoHeader.bmpWidth >> 2); i++) {
    00820                          tempOut->texData[(j * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)) + (i << 1) + 0] = (((tempData[(j * tempLineSize) + i] & 0x03) << 4) / 3);
    00821                          tempOut->texData[(j * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)) + (i << 1) + 0] += ((((tempData[(j * tempLineSize) + i] & 0x0C) << 2) / 3) << 4);
    00822                          tempOut->texData[(j * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)) + (i << 1) + 1] = ((tempData[(j * tempLineSize) + i] & 0x30) / 3);
    00823                          tempOut->texData[(j * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)) + (i << 1) + 1] += ((((tempData[(j * tempLineSize) + i] & 0xC0) >> 2) / 3) << 4);
    00824                     }
    00825                } else {
    00826                     for(i = 0; i < (tempInfoHeader.bmpWidth >> 2); i++) {
    00827                          tempOut->texData[(j * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)) + (i << 1) + 0] = (tempData[(j * tempLineSize) + i] & 0x03);
    00828                          tempOut->texData[(j * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)) + (i << 1) + 0] += ((tempData[(j * tempLineSize) + i] & 0x0C) >> 2);
    00829                          tempOut->texData[(j * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)) + (i << 1) + 1] = ((tempData[(j * tempLineSize) + i] & 0x30) >> 4);
    00830                          tempOut->texData[(j * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)) + (i << 1) + 1] += ((tempData[(j * tempLineSize) + i] & 0xC0) >> 6);
    00831                     }
    00832                }
    00833           }
    00834      } else if(tempInfoHeader.bmpBPP == 1) {
    00835           for(j = 0; j < tempInfoHeader.bmpHeight; j++) {
    00836                for(i = 0; i < (tempInfoHeader.bmpWidth >> 3); i++) {
    00837                      tempOut->texData[(j * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)) + (i << 2) + 0] = (tempData[(j * tempLineSize) + i] & 0x01);
    00838                      tempOut->texData[(j * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)) + (i << 2) + 0] += ((tempData[(j * tempLineSize) + i] & 0x02) << 3);
    00839                      tempOut->texData[(j * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)) + (i << 2) + 1] = ((tempData[(j * tempLineSize) + i] & 0x04) >> 2);
    00840                      tempOut->texData[(j * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)) + (i << 2) + 1] += ((tempData[(j * tempLineSize) + i] & 0x08) << 1);
    00841                      tempOut->texData[(j * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)) + (i << 2) + 2] = (tempData[(j * tempLineSize) + i] & 0x10);
    00842                      tempOut->texData[(j * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)) + (i << 2) + 2] += ((tempData[(j * tempLineSize) + i] & 0x20) >> 1);
    00843                      tempOut->texData[(j * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)) + (i << 2) + 3] = ((tempData[(j * tempLineSize) + i] & 0x40) >> 6);
    00844                      tempOut->texData[(j * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)) + (i << 2) + 3] += ((tempData[(j * tempLineSize) + i] & 0x80) >> 3);
    00845                      if(tempInfoHeader.bmpSize == BMP_HEADER_WV1) {
    00846                           tempOut->texData[(j * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)) + (i << 2) + 0] <<= 3;
    00847                           tempOut->texData[(j * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)) + (i << 2) + 1] <<= 3;
    00848                           tempOut->texData[(j * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)) + (i << 2) + 2] <<= 3;
    00849                           tempOut->texData[(j * ((tempOut->texDataWidth * texBPP(tempOut)) >> 3)) + (i << 2) + 3] <<= 3;
    00850                      }
    00851                }
    00852           }
    00853      }
    00854
    00855      memFree(tempData);
    00856      return tempOut;
    00857 }
    00858
    00859 bool texSaveBMP(Texture* inTex, char* inPath) {
    00860      #if FL_DEBUG_WARNING != 0
    00861      debugWarning("BMP saving is not yet supported.");
    00862      #endif
    00863      return false;
    00864 }
    00865
    00866 #endif