mbed code for Farrari board

Dependencies:   DDRO_Farrari mbed

Fork of DDRO_Farrari by Liangzhen Lai

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers EasyBMP.cpp Source File

EasyBMP.cpp

00001 /*************************************************
00002 *                                                *
00003 *  EasyBMP Cross-Platform Windows Bitmap Library * 
00004 *                                                *
00005 *  Author: Paul Macklin                          *
00006 *   email: macklin01@users.sourceforge.net       *
00007 * support: http://easybmp.sourceforge.net        *
00008 *                                                *
00009 *          file: EasyBMP.cpp                     * 
00010 *    date added: 03-31-2006                      *
00011 * date modified: 12-01-2006                      *
00012 *       version: 1.06                            *
00013 *                                                *
00014 *   License: BSD (revised/modified)              *
00015 * Copyright: 2005-6 by the EasyBMP Project       * 
00016 *                                                *
00017 * description: Actual source file                *
00018 *                                                *
00019 *************************************************/
00020 
00021 #include "EasyBMP.h"
00022 
00023 /* These functions are defined in EasyBMP_DataStructures.h */
00024 
00025 int ceildiv(int n, int d)
00026 {
00027   return 1 + ((n - 1) / d);
00028 }
00029 
00030 int IntPow( int base, int exponent )
00031 {
00032  int i;
00033  int output = 1;
00034  for( i=0 ; i < exponent ; i++ )
00035  { output *= base; }
00036  return output;
00037 }
00038 
00039 BMFH::BMFH()
00040 {
00041  bfType = 19778;
00042  bfReserved1 = 0;
00043  bfReserved2 = 0;
00044 }
00045 
00046 BMIH::BMIH()
00047 {
00048  biPlanes = 1;
00049  biCompression = 0;
00050  biXPelsPerMeter = DefaultXPelsPerMeter;  
00051  biYPelsPerMeter = DefaultYPelsPerMeter;
00052  biClrUsed = 0;
00053  biClrImportant = 0;
00054 }
00055 
00056 
00057 /* These functions are defined in EasyBMP_BMP.h */
00058 
00059 unsigned char BMP::GetPixel( int i, int j ) const
00060 {
00061   if(PixelsBW[i / 32][j] & ( 0x1 << (31 - i % 32))){
00062     return 1; // white
00063   }else{
00064     return 0; // black
00065   }
00066 }
00067 
00068 bool BMP::SetPixel( int i, int j )
00069 {
00070   PixelsR[i / 32][j] |= ( 0x1 << (31 - i % 32));
00071   return true;
00072 }
00073 
00074 BMP::BMP()
00075 {
00076  Width = 1;
00077  Height = 1;
00078  BitDepth = 24;
00079  PixelsBW = new unsigned int* [1];
00080  PixelsBW[0] = new unsigned int [1];
00081  PixelsR = new unsigned int* [1];
00082  PixelsR[0] = new unsigned int [1];
00083 
00084  Colors = NULL;
00085  
00086  XPelsPerMeter = 0;
00087  YPelsPerMeter = 0;
00088  
00089  MetaData1 = NULL;
00090  SizeOfMetaData1 = 0;
00091  MetaData2 = NULL;
00092  SizeOfMetaData2 = 0;
00093 }
00094 
00095 
00096 BMP::~BMP()
00097 {
00098  int i;
00099  for(i=0;i<ceildiv(Width,32);i++)
00100  { delete [] PixelsBW[i]; }
00101  delete [] PixelsBW;
00102 
00103  for(i=0;i<ceildiv(Width,32);i++)
00104  { delete [] PixelsR[i]; }
00105  delete [] PixelsR;
00106 
00107  if( Colors )
00108  { delete [] Colors; }
00109  
00110  if( MetaData1 )
00111  { delete [] MetaData1; }
00112  if( MetaData2 )
00113  { delete [] MetaData2; }
00114 } 
00115 
00116 // int BMP::TellBitDepth( void ) const
00117 int BMP::TellBitDepth( void )
00118 { return BitDepth; }
00119 
00120 // int BMP::TellHeight( void ) const
00121 int BMP::TellHeight( void )
00122 { return Height; }
00123 
00124 // int BMP::TellWidth( void ) const
00125 int BMP::TellWidth( void )
00126 { return Width; }
00127 
00128 // int BMP::TellNumberOfColors( void ) const
00129 int BMP::TellNumberOfColors( void )
00130 {
00131  int output = IntPow( 2, BitDepth );
00132  return output;
00133 }
00134 
00135 bool BMP::SetBitDepth( int NewDepth )
00136 {
00137  using namespace std;
00138  if( NewDepth != 1 && NewDepth != 4)
00139  {
00140   return false;
00141  }
00142  
00143  BitDepth = NewDepth;
00144  if( Colors )
00145  { delete [] Colors; }
00146  int NumberOfColors = IntPow( 2, BitDepth );
00147 
00148  { Colors = new RGBApixel [NumberOfColors]; }
00149  { CreateStandardColorTable(); }
00150  
00151  return true;
00152 }
00153 
00154 bool BMP::SetSize(int NewWidth , int NewHeight )
00155 {
00156  using namespace std;
00157  if( NewWidth <= 0 || NewHeight <= 0 )
00158  {
00159   return false;
00160  }
00161 
00162  int i,j; 
00163 
00164  for(i=0;i<ceildiv(Width,32);i++)
00165  { delete [] PixelsBW[i]; }
00166  delete [] PixelsBW;
00167 
00168  for(i=0;i<ceildiv(Width,32);i++)
00169  { delete [] PixelsR[i]; }
00170  delete [] PixelsR;
00171 
00172  Width = NewWidth;
00173  Height = NewHeight;
00174  PixelsBW = new unsigned int* [ ceildiv(Width,32) ];
00175  PixelsR  = new unsigned int* [ ceildiv(Width,32) ];
00176 
00177  for(i=0;i<ceildiv(Width,32);i++){
00178    PixelsBW[i] = new unsigned int [ Height ];
00179    PixelsR[i] = new unsigned int [ Height ];
00180    for( j=0 ; j < Height ; j++ ){
00181      PixelsBW[i][j] = 0;
00182      PixelsR[i][j] = 0;
00183    }
00184  }
00185 
00186  return true; 
00187 }
00188 #include<iostream>
00189 
00190 bool BMP::WriteToFile( const char* FileName )
00191 {
00192     
00193  using namespace std;
00194  
00195  cout << "called" << endl;
00196  if( !EasyBMPcheckDataSize() )
00197  {
00198   return false; 
00199  }
00200  
00201  FILE* fp = fopen( FileName, "wb" );
00202  
00203 
00204  if( fp == NULL )
00205  {
00206     cout << "can't write\r\n" << endl;
00207   fclose( fp );
00208   return false;
00209  }
00210   
00211  // some preliminaries
00212  
00213  double dBytesPerPixel = ( (double) BitDepth ) / 8.0;
00214  double dBytesPerRow = dBytesPerPixel * (Width+0.0);
00215  dBytesPerRow = ceil(dBytesPerRow);
00216   
00217  int BytePaddingPerRow = 4 - ( (int) (dBytesPerRow) )% 4;
00218  if( BytePaddingPerRow == 4 )
00219  { BytePaddingPerRow = 0; } 
00220  
00221  double dActualBytesPerRow = dBytesPerRow + BytePaddingPerRow;
00222  
00223  double dTotalPixelBytes = Height * dActualBytesPerRow;
00224  
00225  double dPaletteSize = 0;
00226  if( BitDepth == 1 || BitDepth == 4)
00227  { dPaletteSize = IntPow(2,BitDepth)*4.0; }
00228 
00229  double dTotalFileSize = 14 + 40 + dPaletteSize + dTotalPixelBytes;
00230  
00231  // write the file header 
00232  
00233  BMFH bmfh;
00234  bmfh.bfSize = (ebmpDWORD) dTotalFileSize; 
00235  bmfh.bfReserved1 = 0; 
00236  bmfh.bfReserved2 = 0; 
00237  bmfh.bfOffBits = (ebmpDWORD) (14+40+dPaletteSize);  
00238  
00239  fwrite( (char*) &(bmfh.bfType) , sizeof(ebmpWORD) , 1 , fp );
00240  fwrite( (char*) &(bmfh.bfSize) , sizeof(ebmpDWORD) , 1 , fp );
00241  fwrite( (char*) &(bmfh.bfReserved1) , sizeof(ebmpWORD) , 1 , fp );
00242  fwrite( (char*) &(bmfh.bfReserved2) , sizeof(ebmpWORD) , 1 , fp );
00243  fwrite( (char*) &(bmfh.bfOffBits) , sizeof(ebmpDWORD) , 1 , fp );
00244  
00245  // write the info header 
00246  
00247  BMIH bmih;
00248  bmih.biSize = 40;
00249  bmih.biWidth = Width;
00250  bmih.biHeight = Height;
00251  bmih.biPlanes = 1;
00252  bmih.biBitCount = BitDepth;
00253  bmih.biCompression = 0;
00254  bmih.biSizeImage = (ebmpDWORD) dTotalPixelBytes;
00255  if( XPelsPerMeter )
00256  { bmih.biXPelsPerMeter = XPelsPerMeter; }
00257  else
00258  { bmih.biXPelsPerMeter = DefaultXPelsPerMeter; }
00259  if( YPelsPerMeter )
00260  { bmih.biYPelsPerMeter = YPelsPerMeter; }
00261  else
00262  { bmih.biYPelsPerMeter = DefaultYPelsPerMeter; }
00263 
00264  bmih.biClrUsed = 0;
00265  bmih.biClrImportant = 0;
00266 
00267  // indicates that we'll be using bit fields for 16-bit files
00268  if( BitDepth == 16 )
00269  { bmih.biCompression = 3; }
00270  
00271  fwrite( (char*) &(bmih.biSize) , sizeof(ebmpDWORD) , 1 , fp );
00272  fwrite( (char*) &(bmih.biWidth) , sizeof(ebmpDWORD) , 1 , fp );
00273  fwrite( (char*) &(bmih.biHeight) , sizeof(ebmpDWORD) , 1 , fp );
00274  fwrite( (char*) &(bmih.biPlanes) , sizeof(ebmpWORD) , 1 , fp );
00275  fwrite( (char*) &(bmih.biBitCount) , sizeof(ebmpWORD) , 1 , fp );
00276  fwrite( (char*) &(bmih.biCompression) , sizeof(ebmpDWORD) , 1 , fp );
00277  fwrite( (char*) &(bmih.biSizeImage) , sizeof(ebmpDWORD) , 1 , fp );
00278  fwrite( (char*) &(bmih.biXPelsPerMeter) , sizeof(ebmpDWORD) , 1 , fp );
00279  fwrite( (char*) &(bmih.biYPelsPerMeter) , sizeof(ebmpDWORD) , 1 , fp ); 
00280  fwrite( (char*) &(bmih.biClrUsed) , sizeof(ebmpDWORD) , 1 , fp);
00281  fwrite( (char*) &(bmih.biClrImportant) , sizeof(ebmpDWORD) , 1 , fp);
00282  
00283  // write the palette 
00284  if( BitDepth == 1 || BitDepth == 4 )
00285  {
00286   int NumberOfColors = IntPow(2,BitDepth);
00287   
00288   // if there is no palette, create one 
00289   if( !Colors )
00290   {
00291    if( !Colors )
00292    { Colors = new RGBApixel [NumberOfColors]; }
00293    CreateStandardColorTable(); 
00294   }
00295    
00296   int n;
00297   for( n=0 ; n < NumberOfColors ; n++ )
00298   { fwrite( (char*) &(Colors[n]) , 4 , 1 , fp ); }
00299  }
00300  
00301  // write the pixels 
00302  int j;
00303  {  
00304   ebmpBYTE* Buffer;
00305   int BufferSize = (int) ( (Width*BitDepth)/8.0 );
00306   while( 8*BufferSize < Width*BitDepth )
00307   { BufferSize++; }
00308   while( BufferSize % 4 )
00309   { BufferSize++; }
00310   
00311   Buffer = new ebmpBYTE [BufferSize];
00312   for( j=0 ; j < BufferSize; j++ )
00313   { Buffer[j] = 0; }
00314     
00315   j=Height-1;
00316   
00317   while( j > -1 )
00318   {
00319    bool Success = false;
00320    if( BitDepth == 4  )
00321    { Success = Write4bitRow( Buffer, BufferSize, j ); }
00322    if( Success )
00323    {
00324     int BytesWritten = (int) fwrite( (char*) Buffer, 1, BufferSize, fp );
00325     if( BytesWritten != BufferSize )
00326     { Success = false; }
00327    }
00328    if( !Success )
00329    {
00330     j = -1; 
00331    }
00332    j--; 
00333   }
00334   
00335   delete [] Buffer;
00336  }
00337  
00338  cout << "done " << endl;
00339  fclose(fp);
00340  return true;
00341 }
00342 
00343 bool BMP::ReadFromFile( const char* FileName )
00344 { 
00345  using namespace std;
00346  if( !EasyBMPcheckDataSize() )
00347  {
00348   return false; 
00349  }
00350 
00351  FILE* fp = fopen( FileName, "rb" );
00352  if( fp == NULL )
00353  {
00354 
00355   SetBitDepth(1);
00356   SetSize(1,1);
00357   return false;
00358  }
00359  
00360  // read the file header 
00361  
00362  BMFH bmfh;
00363  bool NotCorrupted = true;
00364  
00365  NotCorrupted &= SafeFread( (char*) &(bmfh.bfType) , sizeof(ebmpWORD), 1, fp);
00366  
00367  bool IsBitmap = false;
00368  
00369  if( bmfh.bfType == 19778 )
00370  { IsBitmap = true; }
00371  
00372  if( !IsBitmap ) 
00373  {
00374   fclose( fp ); 
00375   return false;
00376  }
00377 
00378  NotCorrupted &= SafeFread( (char*) &(bmfh.bfSize) , sizeof(ebmpDWORD) , 1, fp); 
00379  NotCorrupted &= SafeFread( (char*) &(bmfh.bfReserved1) , sizeof(ebmpWORD) , 1, fp);
00380  NotCorrupted &= SafeFread( (char*) &(bmfh.bfReserved2) , sizeof(ebmpWORD) , 1, fp);
00381  NotCorrupted &= SafeFread( (char*) &(bmfh.bfOffBits) , sizeof(ebmpDWORD) , 1 , fp);
00382  
00383  // read the info header
00384 
00385  BMIH bmih; 
00386  
00387  NotCorrupted &= SafeFread( (char*) &(bmih.biSize) , sizeof(ebmpDWORD) , 1 , fp);
00388  NotCorrupted &= SafeFread( (char*) &(bmih.biWidth) , sizeof(ebmpDWORD) , 1 , fp); 
00389  NotCorrupted &= SafeFread( (char*) &(bmih.biHeight) , sizeof(ebmpDWORD) , 1 , fp);
00390  NotCorrupted &= SafeFread( (char*) &(bmih.biPlanes) , sizeof(ebmpWORD) , 1, fp); 
00391  NotCorrupted &= SafeFread( (char*) &(bmih.biBitCount) , sizeof(ebmpWORD) , 1, fp);
00392 
00393  NotCorrupted &= SafeFread( (char*) &(bmih.biCompression) , sizeof(ebmpDWORD) , 1 , fp);
00394  NotCorrupted &= SafeFread( (char*) &(bmih.biSizeImage) , sizeof(ebmpDWORD) , 1 , fp);
00395  NotCorrupted &= SafeFread( (char*) &(bmih.biXPelsPerMeter) , sizeof(ebmpDWORD) , 1 , fp);
00396  NotCorrupted &= SafeFread( (char*) &(bmih.biYPelsPerMeter) , sizeof(ebmpDWORD) , 1 , fp);
00397  NotCorrupted &= SafeFread( (char*) &(bmih.biClrUsed) , sizeof(ebmpDWORD) , 1 , fp);
00398  NotCorrupted &= SafeFread( (char*) &(bmih.biClrImportant) , sizeof(ebmpDWORD) , 1 , fp);
00399  
00400  // a safety catch: if any of the header information didn't read properly, abort
00401  // future idea: check to see if at least most is self-consistent
00402   
00403  if( !NotCorrupted )
00404  {
00405   SetSize(1,1);
00406   SetBitDepth(1);
00407   fclose(fp);
00408   return false;
00409  } 
00410  
00411  XPelsPerMeter = bmih.biXPelsPerMeter;
00412  YPelsPerMeter = bmih.biYPelsPerMeter;
00413 
00414  // set the bit depth
00415  
00416  int TempBitDepth = (int) bmih.biBitCount;
00417  if(    TempBitDepth != 1  && TempBitDepth != 4 )
00418  {
00419   SetSize(1,1);
00420   SetBitDepth(1);
00421   fclose(fp);
00422   return false;
00423  }
00424  SetBitDepth( (int) bmih.biBitCount ); 
00425  
00426  // set the size
00427 
00428  if( (int) bmih.biWidth <= 0 || (int) bmih.biHeight <= 0 ) 
00429  {
00430   SetSize(1,1);
00431   SetBitDepth(1);
00432   fclose(fp);
00433   return false;
00434  } 
00435  SetSize( (int) bmih.biWidth , (int) bmih.biHeight );
00436   
00437  // some preliminaries
00438  
00439  double dBytesPerPixel = ( (double) BitDepth ) / 8.0;
00440  double dBytesPerRow = dBytesPerPixel * (Width+0.0);
00441  dBytesPerRow = ceil(dBytesPerRow);
00442   
00443  int BytePaddingPerRow = 4 - ( (int) (dBytesPerRow) )% 4;
00444  if( BytePaddingPerRow == 4 )
00445  { BytePaddingPerRow = 0; }  
00446 
00447  // skip blank data if bfOffBits so indicates
00448  
00449  int BytesToSkip = bmfh.bfOffBits - 54;;
00450  if( BitDepth == 16 && bmih.biCompression == 3 )
00451  { BytesToSkip -= 3*4; }
00452  if( BytesToSkip < 0 )
00453  { BytesToSkip = 0; }
00454  if( BytesToSkip > 0 && BitDepth != 16 )
00455  {
00456   ebmpBYTE* TempSkipBYTE;
00457   TempSkipBYTE = new ebmpBYTE [BytesToSkip];
00458   SafeFread( (char*) TempSkipBYTE , BytesToSkip , 1 , fp);   
00459   delete [] TempSkipBYTE;
00460  } 
00461   
00462  // This code reads 1, 4, 8, 24, and 32-bpp files 
00463  // with a more-efficient buffered technique.
00464 
00465  int j;
00466  if( BitDepth != 16 )
00467  {
00468   int BufferSize = (int) ( (Width*BitDepth) / 8.0 );
00469   while( 8*BufferSize < Width*BitDepth )
00470   { BufferSize++; }
00471   while( BufferSize % 4 )
00472   { BufferSize++; }
00473   ebmpBYTE* Buffer;
00474   Buffer = new ebmpBYTE [BufferSize];
00475   j= Height-1;
00476   while( j > -1 )
00477   {
00478    int BytesRead = (int) fread( (char*) Buffer, 1, BufferSize, fp );
00479    if( BytesRead < BufferSize )
00480    {
00481     j = -1; 
00482    }
00483    else
00484    {
00485     bool Success = false;
00486     if( BitDepth == 1  )
00487     { Success = Read1bitRow(  Buffer, BufferSize, j ); }
00488     if( !Success )
00489     {
00490      j = -1;
00491     }
00492    }   
00493    j--;
00494   }
00495   delete [] Buffer; 
00496  }
00497  fclose(fp);
00498  return true;
00499 }
00500 
00501 bool BMP::CreateStandardColorTable( void )
00502 {
00503  using namespace std;
00504  if( BitDepth != 1 && BitDepth != 4)
00505  {
00506   return false;
00507  }
00508 
00509  if( BitDepth == 1 )
00510  {
00511   int i;
00512   for( i=0 ; i < 2 ; i++ )
00513   {
00514    Colors[i].Red = i*255;
00515    Colors[i].Green = i*255;
00516    Colors[i].Blue = i*255;
00517    Colors[i].Alpha = 0;
00518   } 
00519   return true;
00520  } 
00521 
00522  for(int i=0; i<16; i++){
00523    Colors[i].Red = 0;
00524    Colors[i].Blue = 0;
00525    Colors[i].Green = 0;
00526    Colors[i].Alpha = 0;
00527  }
00528 
00529  Colors[1].Red = 255;
00530 
00531  Colors[15].Red = 255;
00532  Colors[15].Blue = 255;
00533  Colors[15].Green = 255;
00534 
00535  return true;
00536 }
00537 
00538 bool SafeFread( char* buffer, int size, int number, FILE* fp )
00539 {
00540  using namespace std;
00541  int ItemsRead;
00542  if( feof(fp) )
00543  { return false; }
00544  ItemsRead = (int) fread( buffer , size , number , fp );
00545  if( ItemsRead < number )
00546  { return false; }
00547  return true;
00548 }
00549 
00550 #include<iostream>
00551 bool BMP::Read1bitRow(  ebmpBYTE* Buffer, int BufferSize, int Row )
00552 {
00553   using namespace std;
00554  if( Width > 8*BufferSize )
00555  { return false; }
00556 
00557  int i=0;
00558  for(i=0; i < BufferSize; i++){
00559    PixelsBW[i/4][Row] |= Buffer[i] << (8 * (3 - i%4));
00560  }
00561  return true;
00562 }
00563 
00564 bool BMP::Write4bitRow(  ebmpBYTE* Buffer, int BufferSize, int Row )
00565 { 
00566  int PositionWeights[2]  = {16,1};
00567  
00568  int i=0;
00569  int j;
00570  int k=0;
00571  if( Width > 2*BufferSize )
00572  { return false; }
00573  while( i < Width )
00574  {
00575   j=0;
00576   int Index = 0;
00577   while( j < 2 && i < Width )
00578   {
00579     int closest = 0; // black
00580     if(PixelsBW[i / 32][Row] & ( 0x1 << (31 - i % 32))){
00581       closest = 15; // white
00582     }
00583     if(PixelsR[i / 32][Row] & ( 0x1 << (31 - i % 32))){
00584       closest = 1; // red
00585     }
00586     Index += ( PositionWeights[j]* closest ); 
00587     i++; j++;   
00588   }
00589   Buffer[k] = (ebmpBYTE) Index;
00590   k++;
00591  }
00592  return true;
00593 }
00594 
00595 bool EasyBMPcheckDataSize( void )
00596 {
00597  using namespace std;
00598  bool ReturnValue = true;
00599  if( sizeof( ebmpBYTE ) != 1 )
00600  {
00601   ReturnValue = false;
00602  }
00603  if( sizeof( ebmpWORD ) != 2 )
00604  {
00605   ReturnValue = false;
00606  }
00607  if( sizeof( ebmpDWORD ) != 4 )
00608  {
00609   ReturnValue = false;
00610  }
00611  return ReturnValue;
00612 }