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
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
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
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
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