Jump to content
  • Advertisement
Sign in to follow this  
Great_White

Texture Coordinates problem

This topic is 4407 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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:
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 [i + 0] = m_pData [i + 2];
				m_pData [i + 2] = tempRGB;
				*/

				m_pData ^= m_pData[i+2] ^= m_pData ^= m_pData[i+2];
			}

			break;
		}

		case 32:
		{
			
			// 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=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 += 4)
			{
				/*
				BYTE tempRGB = m_pData;
				m_pData [i + 0] = m_pData [i + 2];
				m_pData [i + 2] = tempRGB;
				*/
				m_pData ^= m_pData[i+2] ^= m_pData ^= m_pData[i+2];
			}

			break;
								
		}

		default:
		{	
			MessageBox(0, "Unknown BMP Format", "Error", MB_OK | MB_ICONERROR);
			return false;
			break;
		}
	 }


	return true;


}


In the following block of the code I try to read the bitmap from the last row since bitmaps are bottom-up:
// 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);
			}


But the Texture coordinates are reversed. Any idea about this issue?

Share this post


Link to post
Share on other sites
Advertisement
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!