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

src/cannonball/src/LevelBMP.cpp

Go to the documentation of this file.
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;//= 'MB';
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]; // see http://msdn2.microsoft.com/en-us/library/ms536569.aspx
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                 /* We have to fill lower bits */
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         /* Load Color Table */
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         /* ... Color Table for 16 or 32 Bit Images are not supported yet */     
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                 // no compression
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                 // RLE 8
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                 //case 2: // RLE 4 /* RLE 4 is not supported */
00321 
00322                 // BITFIELDS
00323                 case 3:{
00324                         /* We assumes that mask of each color component can be in any order */
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 }

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