bool Image::LoadBMP(string filename)
{
// Declare bitmap info & file headers
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
// Open the bitmap file
ifstream bmp_file(filename.c_str(), ios::binary);
// Check the filename
if(!bmp_file)
{
bmp_file.close();
MessageBox(0, "Unable to load TGA File!", "Error", MB_OK | MB_ICONERROR);
return false;
}
// Read the file header
if(!bmp_file.read( reinterpret_cast<char*>(&bfh), sizeof(BITMAPFILEHEADER)))
{
bmp_file.close();
MessageBox(0, "Unable to read BMP File Header!", "Read Error", MB_OK | MB_ICONERROR);
return false;
}
// Check the bmp format
if( memcmp(&bfh.bfType, "BM", 2 ) )
{
bmp_file.close();
MessageBox(0, "BMP type not match !", "Error", MB_OK | MB_ICONERROR);
return false;
}
// Read the info header
if( !bmp_file.read(reinterpret_cast<char*>(&bih), sizeof(BITMAPINFOHEADER) ))
{
bmp_file.close();
MessageBox(0, "Unable to read BMP info header!", "Error", MB_OK | MB_ICONERROR);
return false;
}
// Write bit per pixel, bmp width and height
this->m_iBpp = bih.biBitCount;
// Check the height value to ensure it is positive
// Since, if height < 0 , bitmap is top-down.
this->m_iHeight = bih.biHeight<0 ? -bih.biHeight<0 : bih.biHeight;
this->m_iWidth = bih.biWidth;
this->m_iStride = this->m_iWidth * this->m_iBpp/8;
// Set format and internal format
if(m_iBpp == 24)
{
SetFormat(GL_RGB);
SetInternalFormat(GL_RGB8);
}
else if(m_iBpp==32)
{
SetFormat(GL_RGBA);
SetInternalFormat(GL_RGBA8);
}
else if(m_iBpp==8)
{
SetFormat(GL_RGB);
SetInternalFormat(GL_RGB8);
}
// Calculate the padding at the end of the bitmap
int padding = (4 - ( m_iStride % 4 ))%4;
// Handle each Bmp (8, 24 & 32 channels) seperately
switch(m_iBpp)
{
case 8:
{
// Allocate enough memory for palette index data
try
{
m_pData = new BYTE[m_iStride* m_iHeight*3];
}
catch (bad_alloc &ba)
{
MessageBox(0, "Allocation failed for Bitmap Image !", "Error", MB_OK | MB_ICONERROR);
return false;
}
// Calculate palette size
int palette_size = 1 << m_iBpp;
// Create a palette for 8 bit bmp image
RGBQUAD *pPalette = new RGBQUAD[palette_size*3];
bmp_file.read ( (char*)pPalette, sizeof(RGBQUAD)*(palette_size*3));
// Set the file pointer to from the beginning of the file to the beginning of the palette indices
bmp_file.seekg( bfh.bfOffBits, ios::beg);
// Create an palette index array
BYTE *pIndices = new BYTE[m_iStride*m_iHeight];
// Start reading indices to palette index array
// Note here that we start reading from the last row since bitmaps are bottom-up
for( int j=0;j<m_iHeight;j++)
{
bmp_file.read( (char*)(pIndices+j*m_iStride), m_iStride);
bmp_file.seekg( padding, ios::cur);
}
// Close the file stream
bmp_file.close();
// Copy pixels from palette to real data buffer
for(int y=0; y<m_iHeight; y++)
{
for(int x=0; x<m_iWidth; x++)
{
m_pData[(y*m_iWidth+x)*3+0]=pPalette[pIndices[y*m_iWidth+x]].rgbRed; // R
m_pData[(y*m_iWidth+x)*3+1]=pPalette[pIndices[y*m_iWidth+x]].rgbGreen; // G
m_pData[(y*m_iWidth+x)*3+2]=pPalette[pIndices[y*m_iWidth+x]].rgbBlue; // B
}
}
// Delete index array & palette
delete []pPalette;
delete []pIndices;
//Quit
break;
}
case 24 :
{
// Allocate enough memory for pixel data
try
{
m_pData = new BYTE[m_iStride* m_iHeight];
}
catch (bad_alloc &ba)
{
MessageBox(0, "Allocation failed for Bitmap Image !", "Error", MB_OK | MB_ICONERROR);
return false;
}
// Set the file pointer to from the beginning of the file to the beginning of the pixel data
bmp_file.seekg( bfh.bfOffBits, ios::beg);
// Start Reading the the pixel data
// Note here that we start reading from the last row since bitmaps are bottom-up
/*
for( int j=m_iHeight-1; j>=0; j--)
{
bmp_file.read( (char*)(m_pData+j*m_iStride), m_iStride);
bmp_file.seekg( padding, ios::cur);
}
*/
for( int j=0;j<m_iHeight; j++)
{
bmp_file.read( (char*)(m_pData+j*m_iStride), m_iStride);
bmp_file.seekg( padding, ios::cur);
}
// Close the file
bmp_file.close();
// Correct the order of BGR to RBG
// Note : Instead of using a temp value for swapping we are using XOR'ing
// Since binary operations are faster
for (int i = 0; i < m_iStride*m_iHeight; i += 3)
{
/*
BYTE tempRGB = m_pData;
m_pData = m_pData ;
m_pData = tempRGB;
*/</span>
m_pData<span style="font-weight:bold;"> ^= m_pData[i+<span class="cpp-number">2</span>] ^= m_pData<span style="font-weight:bold;"> ^= m_pData[i+<span class="cpp-number">2</span>];
}
<span class="cpp-keyword">break</span>;
}
<span class="cpp-keyword">case</span> <span class="cpp-number">32</span>:
{
<span class="cpp-comment">// Allocate enough memory for pixel data</span>
<span class="cpp-keyword">try</span>
{
m_pData = <span class="cpp-keyword">new</span> BYTE[m_iStride* m_iHeight];
}
<span class="cpp-keyword">catch</span> (bad_alloc &ba)
{
MessageBox(<span class="cpp-number">0</span>, <span class="cpp-literal">"Allocation failed for Bitmap Image !"</span>, <span class="cpp-literal">"Error"</span>, MB_OK | MB_ICONERROR);
<span class="cpp-keyword">return</span> <span class="cpp-keyword">false</span>;
}
<span class="cpp-comment">// Set the file pointer to from the beginning of the file to the beginning of the pixel data</span>
bmp_file.seekg( bfh.bfOffBits, ios::beg);
<span class="cpp-comment">// Start Reading the the pixel data</span>
<span class="cpp-comment">// Note here that we start reading from the last row since bitmaps are bottom-up</span>
<span class="cpp-keyword">for</span>( <span class="cpp-keyword">int</span> j=<span class="cpp-number">0</span>;j<m_iHeight;j++)
{
bmp_file.read( (<span class="cpp-keyword">char</span>*)(m_pData+j*m_iStride), m_iStride);
bmp_file.seekg( padding, ios::cur);
}
<span class="cpp-comment">// Close the file</span>
bmp_file.close();
<span class="cpp-comment">// Correct the order of BGR to RBG</span>
<span class="cpp-comment">// Note : Instead of using a temp value for swapping we are using XOR'ing</span>
<span class="cpp-comment">// Since binary operations are faster</span>
<span class="cpp-keyword">for</span> (<span class="cpp-keyword">int</span> i = <span class="cpp-number">0</span>; i < m_iStride*m_iHeight; i += <span class="cpp-number">4</span>)
{
<span class="cpp-comment">/*
BYTE tempRGB = m_pData<span style="font-weight:bold;">;
m_pData = m_pData ;
m_pData = tempRGB;
*/</span>
m_pData<span style="font-weight:bold;"> ^= m_pData[i+<span class="cpp-number">2</span>] ^= m_pData<span style="font-weight:bold;"> ^= m_pData[i+<span class="cpp-number">2</span>];
}
<span class="cpp-keyword">break</span>;
}
<span class="cpp-keyword">default</span>:
{
MessageBox(<span class="cpp-number">0</span>, <span class="cpp-literal">"Unknown BMP Format"</span>, <span class="cpp-literal">"Error"</span>, MB_OK | MB_ICONERROR);
<span class="cpp-keyword">return</span> <span class="cpp-keyword">false</span>;
<span class="cpp-keyword">break</span>;
}
}
<span class="cpp-keyword">return</span> <span class="cpp-keyword">true</span>;
}
</pre></div><!–ENDSCRIPT–>
In the following block of the code I try to read the bitmap from the last row since bitmaps are bottom-up:
<!–STARTSCRIPT–><!–source lang="cpp"–><div class="source"><pre>
<span class="cpp-comment">// Start Reading the the pixel data</span>
<span class="cpp-comment">// Note here that we start reading from the last row since bitmaps are bottom-up</span>
<span class="cpp-comment">/*
for( int j=m_iHeight-1; j>=0; j–)
{
bmp_file.read( (char*)(m_pData+j*m_iStride), m_iStride);
bmp_file.seekg( padding, ios::cur);
}
*/</span>
<span class="cpp-keyword">for</span>( <span class="cpp-keyword">int</span> j=<span class="cpp-number">0</span>;j<m_iHeight; j++)
{
bmp_file.read( (<span class="cpp-keyword">char</span>*)(m_pData+j*m_iStride), m_iStride);
bmp_file.seekg( padding, ios::cur);
}
</pre></div><!–ENDSCRIPT–>
But the Texture coordinates are reversed. Any idea about this issue?
Texture Coordinates problem
Hi
I'am writing an image class for loading some graphics files. But I came across a strange problem. When reading bitmap file's pixel data (from last scan line to first) the texture coordinates are reversed. Here is my code for bimap loading:
Images in OpenGL are expected to be passed bottom up, so you don't have to flip the bitmaps cause they are already in the orientation OpenGL expects. If you flip it, texture coordinates must be flipped accordingly or the texturing will be wrong.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement