mElite  1.0
An Elite clone based on TextElite by Jan-Philipp Kappmeier and Melanie Schmidt.
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
TextureLoaderBMP.cpp
Go to the documentation of this file.
1 
6 #include "TextureLoaderBMP.h"
7 #include <Windows.h>
8 #include <fstream>
9 
10 using namespace std; // for iostream
11 
16 }
17 
22 }
23 
25 
29 AUX_RGBImageRec * TextureLoaderBMP::loadAux( const char *filename ) {
30  FILE *file = NULL;
31 
32  if (!filename) // file could not be opened
33  return NULL;
34 
35  fopen_s( &file, filename, "r" ); // try opening file for read access
36  if( file ) {// if opening was successful send file to glaux function and let it do all the stuff
37  fclose( file );
38  return auxDIBImageLoad( filename );
39  }
40 
41  return NULL;
42 }
43 
45 
51 bool TextureLoaderBMP::load( const string& filename ) {
52  std::ifstream file( filename.c_str(), ios::binary );
53  if(!file)
54  return 0;
55 
56  BYTE begin[20];
57  file.read( (char *)begin, sizeof(begin) );
58  if(!file) {
59  return 0;
60  }
61 
62  file.seekg(0); // rewind to beginning to read file again
63 
64  if( begin[0] == 'B' && begin[1] == 'M' ) { // windows bitmap file
65  bool ret = ReadDIBFile( file );
66  if( ret == false)
67  return false;
68  } else { // unsupported file type
69  return false;
70  }
71  return false;
72 }
73 
74 #define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B')
75 const int PADSIZE = 4;
76 
78 
89 bool TextureLoaderBMP::ReadDIBFile( istream &file ) {
90  BITMAPFILEHEADER bmfHeader;
91  int nBMISize;
92  BITMAPINFOHEADER * pBMI;
93 
94  // try reading file header
95  file.read( (char *)&bmfHeader, sizeof(bmfHeader) );
96  if( !file )
97  return false;
98 
99  // check if header is valid
100  if ( bmfHeader.bfType != DIB_HEADER_MARKER )
101  return false;
102 
103  // A llocate memory for bitmap info header. The actual size of the header varies in the different
104  // file versions. we suppose it starts at current position and stops where the image data begins.
105  nBMISize = bmfHeader.bfOffBits - sizeof(bmfHeader);
106  pBMI = (BITMAPINFOHEADER *)(new BYTE[nBMISize]);
107  file.read( (char *)pBMI, nBMISize );
108  if( !file ) { // file error. free again.
109  delete (BYTE *)pBMI;
110  return false;
111  }
112 
113  // check for unsupported file type
114  if( pBMI->biHeight < 0 || pBMI->biWidth < 0 || pBMI->biCompression != BI_RGB ) {
115  delete (BYTE *)pBMI;
116  return false;
117  }
118 
119  // save size information in class
120  setHeight( pBMI->biHeight );
121  setWidth( pBMI->biWidth );
122 
123  // if a colormap is present, we create a pointer to it
124  RGBQUAD *bmiColors = (RGBQUAD *)(((BYTE *)pBMI) + pBMI->biSize);
125 
126  // create some width. this is needed for some different file versions and colordephts
127  int usewidth1 = (getWidth() + (PADSIZE - 1)) / PADSIZE;usewidth1 *= PADSIZE;
128  int usewidth3 = (getWidth() * 3 + (PADSIZE - 1)) / PADSIZE;usewidth3 *= PADSIZE;
129  int usewidth4 = (getWidth() * 4 + (PADSIZE - 1)) / PADSIZE;usewidth4 *= PADSIZE;
130 
131  // allocate memory for one row in the file. this row has to be aligned on DWORD (4 bytes)
132  BYTE *rowbuf = new BYTE[usewidth4];
133  bool err = false;
134 
135  //allocate memory for the whole image. we use the aligned size!
136  int usewidth = (getWidth() * 3 + (PADSIZE - 1)) / PADSIZE;
137  usewidth *= PADSIZE;
138 
139  // we create an one dimensional array but it can be accessed as two dimensional array
140  BYTE *image = new BYTE[usewidth * getHeight()];
141  BYTE **pimage;
142  pimage = new BYTE *[getHeight()];
143  for( unsigned int i=0;i<getHeight();i++, image += usewidth )
144  pimage[i] = image;
145 
146  switch( pBMI->biBitCount ) {
147 default:
148  err = true;
149  break;
150 
151 case 8:
152  for( unsigned int r=0;r < getHeight();r++ ) {
153  file.read((char *)rowbuf, usewidth1);
154  if(!file) {
155  err = true;
156  break;
157  }
158 
159  BYTE *img = rowbuf;
160  BYTE *row = pimage[r];
161  for( unsigned int c=0;c < getWidth();c++ ) {// note BGR order of colors!
162  *row++ = bmiColors[*img].rgbBlue;
163  *row++ = bmiColors[*img].rgbGreen;
164  *row++ = bmiColors[*img++].rgbRed;
165  }
166  }
167  break;
168 
169 case 24:
170  for( unsigned int r=0; r < getHeight(); r++ ) {
171  file.read( (char *)rowbuf, usewidth3 );
172  if(!file) {
173  err = true;
174  break;
175  }
176 
177  BYTE *img = rowbuf;
178  BYTE *row = pimage[r];
179  for( unsigned int c=0;c < getWidth()*3;c++ ) {
180  *row++ = *img++;
181  }
182  }
183  break;
184 
185 case 32:
186  for( unsigned int r=0; r < getHeight(); r++ ) {
187  file.read( (char *)rowbuf, usewidth4 );
188  if(!file) {
189  err = true;
190  break;
191  }
192 
193  BYTE *img = rowbuf;
194  BYTE *row = pimage[r];
195  for( unsigned int c=0;c<getWidth();c++ ) {
196  *row++ = *img++;
197  *row++ = *img++;
198  *row++ = *img++;
199  img++;
200  }
201  }
202  break;
203  }
204 
205  // free temp memory, image data is freed in base class destructor
206  delete (BYTE *)pBMI;
207  delete [] rowbuf;
208  if(err) {
209  delete pimage[0];
210  delete pimage;
211  pimage = NULL;
212  setWidth(0);
213  setHeight(0);
214  return false;
215  setFormat(0);
216  }
217 
218  // set format to windows BGR format if possible, elsewise switch to rgb
219  // this ensures compilability, however it does not check if the opengl at runtime can use bgr colors
220  if( pimage == NULL )
221  return false;
222  setImage( pimage );
223 #ifdef GL_BGR_EXT
224  if( useBGR() )
225  setFormat( GL_BGR_EXT );
226  else {
227  bgr2rgb( 3 );
228  setFormat( GL_RGB );
229  }
230 #else
231  bgr2rgb( 3 );
232  setFormat( GL_RGB );
233 #endif
234  return true;
235 }
236 
238 
241 bool TextureLoaderBMP::write( const std::string& filename ) {
242  return false;
243 }