Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers myBMP.cpp Source File

myBMP.cpp

00001 #include "myBMP.h"
00002 
00003 int BitDepth = 1;
00004 int Width = 1;
00005 int Height = 1;
00006 RGBApixel *Colors;
00007 
00008 bool SafeFread( char* buffer, int size, int number, FILE* fp )
00009 {
00010  using namespace std;
00011  int ItemsRead;
00012  if( feof(fp) )
00013  { return false; }
00014  ItemsRead = (int) fread( buffer , size , number , fp );
00015  if( ItemsRead < number )
00016  { return false; }
00017  return true;
00018 }
00019 
00020 bool Read32bitRow( ebmpBYTE* Buffer, int BufferSize, int Row, NokiaLCD *lcd)
00021 { 
00022  int i;
00023  char Colors[4];
00024  if( Width*4 > BufferSize )
00025  { return false; }
00026  for( i=0 ; i < Width ; i++ )
00027  {
00028     memcpy( (char*) &(Colors), (char*) Buffer+4*i, 4 );
00029      //Blue, Green, Red, Alpha
00030     int color = 0x00000000 | (Colors[2] << 16) | (Colors[1] << 8) | (Colors[0]);
00031     (*lcd).pixel((130-Width)/2+i,(130-Height)/2+Row,color);
00032  }
00033  return true;
00034 }
00035 
00036 bool Read24bitRow( ebmpBYTE* Buffer, int BufferSize, int Row, NokiaLCD *lcd)
00037 { 
00038  int i;
00039  char Colors[4];
00040  if( Width*3 > BufferSize )
00041  { return false; }
00042  for( i=0 ; i < Width ; i++ )
00043  {
00044     memcpy( (char*) &(Colors), (char*) Buffer+3*i, 3 );
00045      //Blue, Green, Red, Alpha
00046     int color = 0x00000000 | (Colors[2] << 16) | (Colors[1] << 8) | (Colors[0]);
00047     (*lcd).pixel((130-Width)/2+i,(130-Height)/2+Row,color);
00048  }
00049  return true;
00050 }
00051 
00052 RGBApixel GetColor( int ColorNumber)
00053 { 
00054  RGBApixel Output;
00055  Output.Red   = 255;
00056  Output.Green = 255;
00057  Output.Blue  = 255;
00058  Output.Alpha = 0;
00059  
00060  if( BitDepth != 1 && BitDepth != 4 && BitDepth != 8 )
00061  {
00062   return Output;
00063  }
00064  if( !Colors )
00065  {
00066   return Output; 
00067  }
00068  Output = Colors[ColorNumber];
00069  return Output;
00070 }
00071 
00072 bool Read8bitRow(  ebmpBYTE* Buffer, int BufferSize, int Row, NokiaLCD *lcd)
00073 {
00074  int i;
00075  if( Width > BufferSize )
00076  { return false; }
00077  for( i=0 ; i < Width ; i++ )
00078  {
00079     int Index = Buffer[i];
00080      //Blue, Green, Red, Alpha
00081     RGBApixel colors = GetColor(Index);
00082     int color = 0x00000000 | (colors.Red<< 16) | (colors.Blue << 8) | (colors.Green);
00083     (*lcd).pixel((130-Width)/2+i,(130-Height)/2+Row,color);
00084  }
00085  return true;
00086 }
00087 
00088 bool Read4bitRow(  ebmpBYTE* Buffer, int BufferSize, int Row, NokiaLCD *lcd)
00089 {
00090  int Shifts[2] = {4  ,0 };
00091  int Masks[2]  = {240,15};
00092  
00093  int i=0;
00094  int j;
00095  int k=0;
00096  if( Width > 2*BufferSize )
00097  { return false; }
00098  while( i < Width )
00099  {
00100   j=0;
00101   while( j < 2 && i < Width )
00102   {
00103    int Index = (int) ( (Buffer[k]&Masks[j]) >> Shifts[j]);
00104    RGBApixel colors = GetColor(Index);
00105    int color = 0x00000000 | (colors.Red<< 16) | (colors.Blue << 8) | (colors.Green);
00106    (*lcd).pixel((130-Width)/2+i,(130-Height)/2+Row,color);
00107    i++; j++;   
00108   }
00109   k++;
00110  }
00111  return true;
00112 }
00113 bool Read1bitRow(  ebmpBYTE* Buffer, int BufferSize, int Row, NokiaLCD *lcd)
00114 {
00115  int Shifts[8] = {7  ,6 ,5 ,4 ,3,2,1,0};
00116  int Masks[8]  = {128,64,32,16,8,4,2,1};
00117  
00118  int i=0;
00119  int j;
00120  int k=0;
00121  
00122  if( Width > 8*BufferSize )
00123  { return false; }
00124  while( i < Width )
00125  {
00126   j=0;
00127   while( j < 8 && i < Width )
00128   {
00129    int Index = (int) ( (Buffer[k]&Masks[j]) >> Shifts[j]);
00130    RGBApixel colors = GetColor(Index);
00131    int color = 0x00000000 | (colors.Red<< 16) | (colors.Blue << 8) | (colors.Green);
00132    (*lcd).pixel((130-Width)/2+i,(130-Height)/2+Row,color);
00133    i++; j++;   
00134   }
00135   k++;
00136  }
00137  return true;
00138 }
00139 
00140 int TellNumberOfColors( int BitDepth )
00141 {
00142  int output = 1 << BitDepth;
00143  if( BitDepth == 32 )
00144  { output = 1 << 24; }
00145  return output;
00146 }
00147 
00148 bool ReadBMPFromFile( const char* FileName, RGBApixel *Colors, NokiaLCD *lcd)
00149 { 
00150  FILE* fp = fopen( FileName, "rb" );
00151  if( fp == NULL )
00152  {
00153   return false;
00154  }
00155  
00156  // read the file header 
00157  
00158  BMFH bmfh;
00159  bool NotCorrupted = true;
00160  
00161  NotCorrupted &= SafeFread( (char*) &(bmfh.bfType) , sizeof(ebmpWORD), 1, fp);
00162  
00163  bool IsBitmap = false;
00164  
00165  if( bmfh.bfType == 19778 )
00166  { IsBitmap = true; }
00167  
00168  if( !IsBitmap ) 
00169  {
00170   fclose( fp ); 
00171   return false;
00172  }
00173 
00174  NotCorrupted &= SafeFread( (char*) &(bmfh.bfSize) , sizeof(ebmpDWORD) , 1, fp); 
00175  NotCorrupted &= SafeFread( (char*) &(bmfh.bfReserved1) , sizeof(ebmpWORD) , 1, fp);
00176  NotCorrupted &= SafeFread( (char*) &(bmfh.bfReserved2) , sizeof(ebmpWORD) , 1, fp);
00177  NotCorrupted &= SafeFread( (char*) &(bmfh.bfOffBits) , sizeof(ebmpDWORD) , 1 , fp);
00178  
00179  // read the info header
00180 
00181  BMIH bmih; 
00182  
00183  NotCorrupted &= SafeFread( (char*) &(bmih.biSize) , sizeof(ebmpDWORD) , 1 , fp);
00184  NotCorrupted &= SafeFread( (char*) &(bmih.biWidth) , sizeof(ebmpDWORD) , 1 , fp); 
00185  NotCorrupted &= SafeFread( (char*) &(bmih.biHeight) , sizeof(ebmpDWORD) , 1 , fp);
00186  NotCorrupted &= SafeFread( (char*) &(bmih.biPlanes) , sizeof(ebmpWORD) , 1, fp); 
00187  NotCorrupted &= SafeFread( (char*) &(bmih.biBitCount) , sizeof(ebmpWORD) , 1, fp);
00188 
00189  NotCorrupted &= SafeFread( (char*) &(bmih.biCompression) , sizeof(ebmpDWORD) , 1 , fp);
00190  NotCorrupted &= SafeFread( (char*) &(bmih.biSizeImage) , sizeof(ebmpDWORD) , 1 , fp);
00191  NotCorrupted &= SafeFread( (char*) &(bmih.biXPelsPerMeter) , sizeof(ebmpDWORD) , 1 , fp);
00192  NotCorrupted &= SafeFread( (char*) &(bmih.biYPelsPerMeter) , sizeof(ebmpDWORD) , 1 , fp);
00193  NotCorrupted &= SafeFread( (char*) &(bmih.biClrUsed) , sizeof(ebmpDWORD) , 1 , fp);
00194  NotCorrupted &= SafeFread( (char*) &(bmih.biClrImportant) , sizeof(ebmpDWORD) , 1 , fp);
00195  
00196  // a safety catch: if any of the header information didn't read properly, abort
00197  // future idea: check to see if at least most is self-consistent
00198   
00199  if( !NotCorrupted )
00200  {
00201   fclose(fp);
00202   return false;
00203  } 
00204  
00205  // if bmih.biCompression 1 or 2, then the file is RLE compressed
00206  
00207  if( bmih.biCompression == 1 || bmih.biCompression == 2 )
00208  {
00209   fclose(fp);
00210   return false; 
00211  }
00212  
00213  // if bmih.biCompression > 3, then something strange is going on 
00214  // it's probably an OS2 bitmap file.
00215  
00216  if( bmih.biCompression > 3 )
00217  {
00218   fclose(fp);
00219   return false; 
00220  }
00221  
00222  if( bmih.biCompression == 3 && bmih.biBitCount != 16 )
00223  {
00224   fclose(fp);
00225   return false; 
00226  }
00227 
00228  // set the bit depth
00229  
00230  int TempBitDepth = (int) bmih.biBitCount;
00231  if(    TempBitDepth != 1  && TempBitDepth != 4 
00232      && TempBitDepth != 8  && TempBitDepth != 16
00233      && TempBitDepth != 24 && TempBitDepth != 32 )
00234  {
00235   fclose(fp);
00236   return false;
00237  }
00238  BitDepth = (int)bmih.biBitCount;
00239  // set the size
00240 
00241  if( (int) bmih.biWidth <= 0 || (int) bmih.biHeight <= 0 ) 
00242  {
00243   fclose(fp);
00244   return false;
00245  } 
00246  Width = (int) bmih.biWidth;
00247  Height = (int) bmih.biHeight;
00248  // some preliminaries
00249  
00250  double dBytesPerPixel = ( (double) BitDepth ) / 8.0;
00251  double dBytesPerRow = dBytesPerPixel * (Width+0.0);
00252  dBytesPerRow = ceil(dBytesPerRow);
00253   
00254  int BytePaddingPerRow = 4 - ( (int) (dBytesPerRow) )% 4;
00255  if( BytePaddingPerRow == 4 )
00256  { BytePaddingPerRow = 0; }  
00257  
00258  // if < 16 bits, read the palette
00259  
00260  if( BitDepth < 16 )
00261  {
00262   // determine the number of colors specified in the 
00263   // color table
00264   
00265   int NumberOfColorsToRead = ((int) bmfh.bfOffBits - 54 )/4;  
00266   if( NumberOfColorsToRead > (1 << BitDepth) )
00267   { NumberOfColorsToRead = (1 << BitDepth); }
00268  
00269   int n;
00270   for( n=0; n < NumberOfColorsToRead ; n++ )
00271   {
00272    SafeFread( (char*) &(Colors[n]) , 4 , 1 , fp);     
00273   }
00274   for( n=NumberOfColorsToRead ; n < TellNumberOfColors(BitDepth) ; n++ )
00275   {
00276    RGBApixel WHITE; 
00277    WHITE.Red = 255;
00278    WHITE.Green = 255;
00279    WHITE.Blue = 255;
00280    WHITE.Alpha = 0;
00281    Colors[n] = WHITE;
00282   }
00283  }
00284  
00285  // skip blank data if bfOffBits so indicates
00286  
00287  int BytesToSkip = bmfh.bfOffBits - 54;;
00288  if( BitDepth < 16 )
00289  { BytesToSkip -= 4*(1 << BitDepth); }
00290  if( BitDepth == 16 && bmih.biCompression == 3 )
00291  { BytesToSkip -= 3*4; }
00292  if( BytesToSkip < 0 )
00293  { BytesToSkip = 0; }
00294  if( BytesToSkip > 0 && BitDepth != 16 )
00295  {
00296   ebmpBYTE* TempSkipBYTE;
00297   TempSkipBYTE = new ebmpBYTE [BytesToSkip];
00298   SafeFread( (char*) TempSkipBYTE , BytesToSkip , 1 , fp);   
00299   delete [] TempSkipBYTE;
00300  } 
00301   
00302  // This code reads 1, 4, 8, 24, and 32-bpp files 
00303  // with a more-efficient buffered technique.
00304 
00305  int i,j;
00306  if( BitDepth != 16 )
00307  {
00308   int BufferSize = (int) ( (Width*BitDepth) / 8.0 );
00309   while( 8*BufferSize < Width*BitDepth )
00310   { BufferSize++; }
00311   while( BufferSize % 4 )
00312   { BufferSize++; }
00313   ebmpBYTE* Buffer;
00314   Buffer = new ebmpBYTE [BufferSize];
00315   j= Height-1;
00316   while( j > -1 )
00317   {
00318    int BytesRead = (int) fread( (char*) Buffer, 1, BufferSize, fp );
00319    if( BytesRead < BufferSize )
00320    {
00321     j = -1; 
00322    }
00323    else
00324    {
00325     bool Success = false;
00326     if( BitDepth == 1  )
00327     { Success = Read1bitRow(  Buffer, BufferSize, j , lcd); }
00328     if( BitDepth == 4  )
00329     { Success = Read4bitRow(  Buffer, BufferSize, j , lcd); }
00330     if( BitDepth == 8  )
00331     { Success = Read8bitRow(  Buffer, BufferSize, j , lcd); }
00332     if( BitDepth == 24 )
00333     { Success = Read24bitRow( Buffer, BufferSize, j , lcd); }
00334     if( BitDepth == 32 )
00335     { Success = Read32bitRow( Buffer, BufferSize, j , lcd); }
00336     if( !Success )
00337     {
00338      j = -1;
00339     }
00340    }   
00341    j--;
00342   }
00343   delete [] Buffer; 
00344  }
00345 
00346  if( BitDepth == 16 )
00347  {
00348   int DataBytes = Width*2;
00349   int PaddingBytes = ( 4 - DataBytes % 4 ) % 4;
00350 
00351   // set the default mask
00352   
00353   ebmpWORD BlueMask = 31; // bits 12-16
00354   ebmpWORD GreenMask = 992; // bits 7-11
00355   ebmpWORD RedMask = 31744; // bits 2-6
00356 
00357   // read the bit fields, if necessary, to 
00358   // override the default 5-5-5 mask
00359   
00360   if( bmih.biCompression != 0 )
00361   {
00362    // read the three bit masks
00363 
00364    ebmpWORD TempMaskWORD;
00365   
00366    SafeFread( (char*) &RedMask , 2 , 1 , fp );
00367    SafeFread( (char*) &TempMaskWORD , 2, 1, fp );
00368   
00369    SafeFread( (char*) &GreenMask , 2 , 1 , fp );
00370    SafeFread( (char*) &TempMaskWORD , 2, 1, fp );
00371 
00372    SafeFread( (char*) &BlueMask , 2 , 1 , fp );
00373    SafeFread( (char*) &TempMaskWORD , 2, 1, fp );
00374   }
00375   
00376   // read and skip any meta data
00377 
00378   if( BytesToSkip > 0 )
00379   {
00380    ebmpBYTE* TempSkipBYTE;
00381    TempSkipBYTE = new ebmpBYTE [BytesToSkip];
00382    SafeFread( (char*) TempSkipBYTE , BytesToSkip , 1 , fp);
00383    delete [] TempSkipBYTE;   
00384   } 
00385   
00386   // determine the red, green and blue shifts
00387   
00388   int GreenShift = 0; 
00389   ebmpWORD TempShiftWORD = GreenMask;
00390   while( TempShiftWORD > 31 )
00391   { TempShiftWORD = TempShiftWORD>>1; GreenShift++; }  
00392   int BlueShift = 0;
00393   TempShiftWORD = BlueMask;
00394   while( TempShiftWORD > 31 )
00395   { TempShiftWORD = TempShiftWORD>>1; BlueShift++; }  
00396   int RedShift = 0;  
00397   TempShiftWORD = RedMask;
00398   while( TempShiftWORD > 31 )
00399   { TempShiftWORD = TempShiftWORD>>1; RedShift++; }  
00400   
00401   // read the actual pixels
00402   
00403   for( j=Height-1 ; j >= 0 ; j-- )
00404   {
00405    i=0;
00406    int ReadNumber = 0;
00407    while( ReadNumber < DataBytes )
00408    {
00409     ebmpWORD TempWORD;
00410     SafeFread( (char*) &TempWORD , 2 , 1 , fp );
00411     ReadNumber += 2;
00412   
00413     ebmpWORD Red = RedMask & TempWORD;
00414     ebmpWORD Green = GreenMask & TempWORD;
00415     ebmpWORD Blue = BlueMask & TempWORD;
00416                 
00417     ebmpBYTE BlueBYTE = (ebmpBYTE) 8*(Blue>>BlueShift);
00418     ebmpBYTE GreenBYTE = (ebmpBYTE) 8*(Green>>GreenShift);
00419     ebmpBYTE RedBYTE = (ebmpBYTE) 8*(Red>>RedShift);
00420         
00421     int color = 0x00000000 | (RedBYTE << 16) | (GreenBYTE << 8) | (BlueBYTE);
00422     (*lcd).pixel((130-Width)/2+i,(130-Height)/2+j,color);
00423     i++;
00424    }
00425    ReadNumber = 0;
00426    while( ReadNumber < PaddingBytes )
00427    {
00428     ebmpBYTE TempBYTE;
00429     SafeFread( (char*) &TempBYTE , 1, 1, fp);
00430     ReadNumber++;
00431    }
00432   }
00433 
00434  }
00435  
00436  fclose(fp);
00437  return true;
00438 }
00439 
00440 
00441 BMIH::BMIH()
00442 {
00443  biPlanes = 1;
00444  biCompression = 0;
00445  biXPelsPerMeter = DefaultXPelsPerMeter;  
00446  biYPelsPerMeter = DefaultYPelsPerMeter;
00447  biClrUsed = 0;
00448  biClrImportant = 0;
00449 }
00450 
00451 BMFH::BMFH()
00452 {
00453  bfType = 19778;
00454  bfReserved1 = 0;
00455  bfReserved2 = 0;
00456 }