00001 #include "main.h"
00002 #pragma pack(1)
00003
00004 struct BMP_SIGNATURE {
00005 BMP_SIGNATURE() {
00006 this->c[0] = 'B';
00007 this->c[1] = 'M';
00008 }
00009 union {
00010 unsigned short int s;
00011 unsigned char c[2];
00012 };
00013 };
00014
00015 const BMP_SIGNATURE bmpSignature;
00016 const unsigned short int BITMAP_SIGNATURE = bmpSignature.s;
00017
00018 typedef struct {
00019 unsigned short int Signature;
00020 unsigned int Size;
00021 unsigned int Reserved;
00022 unsigned int BitsOffset;
00023 } BITMAP_FILEHEADER;
00024
00025 #define BITMAP_FILEHEADER_SIZE 14
00026
00027 typedef struct {
00028 unsigned int HeaderSize;
00029 int Width;
00030 int Height;
00031 unsigned short int Planes;
00032 unsigned short int BitCount;
00033 unsigned int Compression;
00034 unsigned int SizeImage;
00035 int PelsPerMeterX;
00036 int PelsPerMeterY;
00037 unsigned int ClrUsed;
00038 unsigned int ClrImportant;
00039 unsigned int RedMask;
00040 unsigned int GreenMask;
00041 unsigned int BlueMask;
00042 unsigned int AlphaMask;
00043 unsigned int CsType;
00044 unsigned int Endpoints[9];
00045 unsigned int GammaRed;
00046 unsigned int GammaGreen;
00047 unsigned int GammaBlue;
00048 } BITMAP_HEADER;
00049
00050 typedef struct {
00051 unsigned char Red;
00052 unsigned char Green;
00053 unsigned char Blue;
00054 unsigned char Alpha;
00055 } RGBA;
00056
00057 typedef struct {
00058 unsigned char Blue;
00059 unsigned char Green;
00060 unsigned char Red;
00061 unsigned char Alpha;
00062 } BGRA;
00063
00064 typedef struct {
00065 unsigned char Blue;
00066 unsigned char Green;
00067 unsigned char Red;
00068 } BGR;
00069
00070 typedef struct {
00071 unsigned short int Blue:5;
00072 unsigned short int Green:5;
00073 unsigned short int Red:5;
00074 unsigned short int Reserved:1;
00075 } BGR16;
00076
00077 uint ShiftRightByMask(uint Color, uint Mask, uint DistributeToBits = 8) {
00078 if (Mask == 0) return 0;
00079
00080 uint ShiftCount = 0;
00081 uint Test = 0x00000001;
00082
00083 while((ShiftCount<32) && !(Mask & Test)){
00084 Test <<= 1;
00085 ShiftCount++;
00086 }
00087
00088 uint BitCount = 32;
00089 Test = 0x80000000;
00090
00091 while(BitCount && !((Mask >> ShiftCount) & Test)){
00092 Test >>= 1;
00093 BitCount--;
00094 }
00095
00096 uint BaseColor = (Color & Mask) >> ShiftCount;
00097
00098 if(DistributeToBits > BitCount){
00099
00100 uint BitsToFill = DistributeToBits - BitCount;
00101 while(BitsToFill--) {
00102 BaseColor <<= 1;
00103 if(BaseColor & 1)
00104 BaseColor |= 1;
00105 }
00106 }else if(DistributeToBits < BitCount){
00107 BaseColor >>= (BitCount - DistributeToBits);
00108 }
00109 return BaseColor;
00110 }
00111
00112 bool Level::loadBMP(const wchar* filename, int& width, int& height, Pixel** outData){
00113 FILE* file = 0;
00114 BITMAP_FILEHEADER m_BitmapFileHeader;
00115 BITMAP_HEADER m_BitmapHeader;
00116 RGBA* m_BitmapData = 0;
00117 uchar *Line = 0;
00118 uint m_BitmapSize = 0;
00119 BGRA m_ColorTable[256];
00120 uint m_ColorTableSize = 0;
00121 int bmpWidth = 0, bmpHeight = 0;
00122
00123 #define SAVEEXIT(rs) {\
00124 if(file){fclose(file);file=0;}\
00125 SAVEFREE(m_BitmapData);\
00126 SAVEFREE(Line);\
00127 return rs;}
00128
00129 if(_wfopen_s(&file, filename, TEXT("rb")) != 0)
00130 return false;
00131
00132 fread(&m_BitmapFileHeader, BITMAP_FILEHEADER_SIZE, 1, file);
00133 if(m_BitmapFileHeader.Signature != BITMAP_SIGNATURE)
00134 return false;
00135
00136 fread(&m_BitmapHeader, sizeof(BITMAP_HEADER), 1, file);
00137
00138
00139 fseek(file, BITMAP_FILEHEADER_SIZE + m_BitmapHeader.HeaderSize, SEEK_SET);
00140
00141 switch(m_BitmapHeader.BitCount){
00142 case 1: m_ColorTableSize = 2; break;
00143 case 4: m_ColorTableSize = 16; break;
00144 case 8: m_ColorTableSize = 256; break;
00145 default: break;
00146 }
00147
00148 if(m_ColorTableSize>0)
00149 fread(m_ColorTable, sizeof(BGRA), m_ColorTableSize, file);
00150
00151
00152 bmpWidth = m_BitmapHeader.Width < 0 ? -m_BitmapHeader.Width : m_BitmapHeader.Width;
00153 bmpHeight = m_BitmapHeader.Height < 0 ? -m_BitmapHeader.Height : m_BitmapHeader.Height;
00154
00155 if(width > 0 && height > 0 && width != bmpWidth && height != bmpHeight){
00156 fclose(file);
00157 return false;
00158 }
00159
00160 width = bmpWidth;
00161 height = bmpHeight;
00162
00163 if(outData == 0){
00164 fclose(file);
00165 return true;
00166 }
00167
00168 m_BitmapSize = bmpWidth * bmpHeight;
00169 m_BitmapData = (RGBA*)malloc(sizeof(RGBA)*m_BitmapSize);
00170
00171 uint LineWidth = (bmpWidth * m_BitmapHeader.BitCount/8 + 3) & ~3;
00172 Line = (uchar*)malloc(sizeof(uchar)*LineWidth);
00173
00174 fseek(file, m_BitmapFileHeader.BitsOffset, SEEK_SET);
00175
00176 int Index = 0;
00177
00178 switch(m_BitmapHeader.Compression){
00179
00180 case 0:{
00181 for (int i = 0; i < bmpHeight; i++) {
00182 fread(Line, LineWidth, 1, file);
00183 uchar *LinePtr = Line;
00184
00185 switch(m_BitmapHeader.BitCount) {
00186 case 1:
00187 for(int j = 0; j < bmpWidth; j++){
00188 uint Color = *((uchar*) LinePtr);
00189 for (int k = 0; k < 8; k++) {
00190 m_BitmapData[Index].Red = m_ColorTable[Color & 0x80 ? 1 : 0].Red;
00191 m_BitmapData[Index].Green = m_ColorTable[Color & 0x80 ? 1 : 0].Green;
00192 m_BitmapData[Index].Blue = m_ColorTable[Color & 0x80 ? 1 : 0].Blue;
00193 m_BitmapData[Index].Alpha = m_ColorTable[Color & 0x80 ? 1 : 0].Alpha;
00194 Index++;
00195 Color <<= 1;
00196 }
00197 LinePtr++;
00198 j += 7;
00199 }
00200 break;
00201 case 4:
00202 for(int j = 0; j < bmpWidth; j++){
00203 uint Color = *((uchar*) LinePtr);
00204 m_BitmapData[Index].Red = m_ColorTable[(Color >> 4) & 0x0f].Red;
00205 m_BitmapData[Index].Green = m_ColorTable[(Color >> 4) & 0x0f].Green;
00206 m_BitmapData[Index].Blue = m_ColorTable[(Color >> 4) & 0x0f].Blue;
00207 m_BitmapData[Index].Alpha = m_ColorTable[(Color >> 4) & 0x0f].Alpha;
00208 Index++;
00209 m_BitmapData[Index].Red = m_ColorTable[Color & 0x0f].Red;
00210 m_BitmapData[Index].Green = m_ColorTable[Color & 0x0f].Green;
00211 m_BitmapData[Index].Blue = m_ColorTable[Color & 0x0f].Blue;
00212 m_BitmapData[Index].Alpha = m_ColorTable[Color & 0x0f].Alpha;
00213 Index++;
00214 LinePtr++;
00215 j++;
00216 }
00217 break;
00218 case 8:
00219 for(int j = 0; j < bmpWidth; j++){
00220 uint Color = *((uchar*) LinePtr);
00221 m_BitmapData[Index].Red = m_ColorTable[Color].Red;
00222 m_BitmapData[Index].Green = m_ColorTable[Color].Green;
00223 m_BitmapData[Index].Blue = m_ColorTable[Color].Blue;
00224 m_BitmapData[Index].Alpha = m_ColorTable[Color].Alpha;
00225 Index++;
00226 LinePtr++;
00227 }
00228 break;
00229 case 16:
00230 for(int j = 0; j < bmpWidth; j++){
00231 uint Color = *((unsigned short int*) LinePtr);
00232 m_BitmapData[Index].Red = ((Color >> 10) & 0x1f) << 3;
00233 m_BitmapData[Index].Green = ((Color >> 5) & 0x1f) << 3;
00234 m_BitmapData[Index].Blue = (Color & 0x1f) << 3;
00235 m_BitmapData[Index].Alpha = 255;
00236 Index++;
00237 LinePtr += 2;
00238 }
00239 break;
00240 case 24:
00241 for(int j = 0; j < bmpWidth; j++){
00242 uint Color = *((uint*) LinePtr);
00243 m_BitmapData[Index].Blue = Color & 0xff;
00244 m_BitmapData[Index].Green = (Color >> 8) & 0xff;
00245 m_BitmapData[Index].Red = (Color >> 16) & 0xff;
00246 m_BitmapData[Index].Alpha = 255;
00247 Index++;
00248 LinePtr += 3;
00249 }
00250 break;
00251 case 32:
00252 for(int j = 0; j < bmpWidth; j++){
00253 uint Color = *((uint*) LinePtr);
00254 m_BitmapData[Index].Blue = Color & 0xff;
00255 m_BitmapData[Index].Green = (Color >> 8) & 0xff;
00256 m_BitmapData[Index].Red = (Color >> 16) & 0xff;
00257 m_BitmapData[Index].Alpha = Color >> 24;
00258 Index++;
00259 LinePtr += 4;
00260 }
00261 break;
00262 default:
00263 SAVEEXIT(false);
00264 }
00265 }
00266 break;
00267 }
00268
00269 case 1:{
00270 uchar Count = 0;
00271 uchar ColorIndex = 0;
00272 int x = 0, y = 0;
00273
00274 for(bool run = true; !feof(file) && run; ){
00275 fread(&Count, 1, 1, file);
00276 fread(&ColorIndex, 1, 1, file);
00277
00278 if (Count > 0) {
00279 Index = x + y * bmpWidth;
00280 for (int k = 0; k < Count; k++) {
00281 m_BitmapData[Index + k].Red = m_ColorTable[ColorIndex].Red;
00282 m_BitmapData[Index + k].Green = m_ColorTable[ColorIndex].Green;
00283 m_BitmapData[Index + k].Blue = m_ColorTable[ColorIndex].Blue;
00284 m_BitmapData[Index + k].Alpha = m_ColorTable[ColorIndex].Alpha;
00285 }
00286 x += Count;
00287 } else if (Count == 0) {
00288 int Flag = ColorIndex;
00289 switch(Flag){
00290 case 0: x = 0; y++; break;
00291 case 1: run = false; break;
00292 case 2:{
00293 char rx = 0;
00294 char ry = 0;
00295 fread(&rx, 1, 1, file);
00296 fread(&ry, 1, 1, file);
00297 x += rx;
00298 y += ry;
00299 break;
00300 }
00301 default:{
00302 Count = Flag;
00303 Index = x + y * bmpWidth;
00304 for(int k = 0; k < Count; k++){
00305 fread(&ColorIndex, 1, 1, file);
00306 m_BitmapData[Index + k].Red = m_ColorTable[ColorIndex].Red;
00307 m_BitmapData[Index + k].Green = m_ColorTable[ColorIndex].Green;
00308 m_BitmapData[Index + k].Blue = m_ColorTable[ColorIndex].Blue;
00309 m_BitmapData[Index + k].Alpha = m_ColorTable[ColorIndex].Alpha;
00310 }
00311 x += Count;
00312 if (ftell(file) & 1) fseek(file, 1, SEEK_CUR);
00313 break;
00314 }
00315 }
00316 }
00317 }
00318 break;
00319 }
00320
00321
00322
00323 case 3:{
00324
00325 for(int i=0; i<bmpHeight; i++){
00326 fread(Line, LineWidth, 1, file);
00327 uchar *LinePtr = Line;
00328
00329 for(int j=0; j < bmpWidth; j++){
00330 uint Color = 0;
00331
00332 if (m_BitmapHeader.BitCount == 16) {
00333 Color = *((unsigned short int*) LinePtr);
00334 LinePtr += 2;
00335 } else if (m_BitmapHeader.BitCount == 32) {
00336 Color = *((uint*) LinePtr);
00337 LinePtr += 4;
00338 }
00339 m_BitmapData[Index].Red = ShiftRightByMask(Color, m_BitmapHeader.RedMask);
00340 m_BitmapData[Index].Green = ShiftRightByMask(Color, m_BitmapHeader.GreenMask);
00341 m_BitmapData[Index].Blue = ShiftRightByMask(Color, m_BitmapHeader.BlueMask);
00342 m_BitmapData[Index].Alpha = ShiftRightByMask(Color, m_BitmapHeader.AlphaMask);
00343
00344 Index++;
00345 }
00346 }
00347 break;
00348 }
00349 default:
00350 SAVEEXIT(false);
00351 }
00352
00353 SAVEFREE(Line);
00354 fclose(file);
00355
00356 *outData = (Pixel*)m_BitmapData;
00357 return true;
00358 #undef SAVEEXIT
00359 }