Advertisement Jump to content
VanillaSnake21

Issues with loading/drawing a bitmap

Recommended Posts

Posted (edited)

I'm trying to implement heightmaps for my engine however I'm having some troubles with bitmap loading code. The bitmap I'm trying to load is 8bit grayscale 250x250 pixels. I've attached the image of what it looks like. (Scroll all the way to the end).

The image on the left (in the debug window) is rendered using software, the image on the right is what the height map comes out to look like (I added the colors on purpose to make it clearer to see), that is rendered in hardware. The photoshop shows the original image and how it's meant to look. I'm not exactly sure where the error is, I'm thinking it's the loading function but it's so straight forward that I just can't find the mistake. 

This is some relevant code:

 

 

Loading:

 

int Bitmap::LoadBitmapFromDisk(std::string szFileName)
	{

		// Open the bitmap file
		HANDLE hFile = CreateFileA(szFileName.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
		if (hFile == INVALID_HANDLE_VALUE)
			return 0;

		// Read the bitmap file header
		DWORD dwBytesRead;
		BOOL bOK = ReadFile(hFile, &fileHeader, sizeof(BITMAPFILEHEADER), &dwBytesRead, NULL);

		//see if the correct byte number was read and that it's actually a bitmap (bfType has to match)
		if (!bOK || (dwBytesRead != sizeof(BITMAPFILEHEADER)) || (fileHeader.bfType != 0x4D42))
		{
			CloseHandle(hFile);
			return 0;
		}


		// Read the bitmap info head
		bOK = ReadFile(hFile, &infoHeader, sizeof(BITMAPINFOHEADER), &dwBytesRead, NULL);
		if (!bOK || (dwBytesRead != sizeof(BITMAPINFOHEADER)))
		{
			CloseHandle(hFile);
			return 0;
		}

		// Store the width and height of the bitmap
		int m_iWidth = (int)infoHeader.biWidth;
		int m_iHeight = (int)infoHeader.biHeight;


		unsigned int sz;
		SetFilePointer(hFile, fileHeader.bfOffBits, NULL, FILE_BEGIN);
		data = (UCHAR*) new unsigned char[infoHeader.biSizeImage];
		bOK = ReadFile(hFile, data, infoHeader.biSizeImage, &dwBytesRead, NULL);

		//flip the bytes to little endian
		if (infoHeader.biBitCount == 32)
		{
			DWORD* temp = (DWORD*)data;
			for (int i = 0; i < infoHeader.biSizeImage / 4; i++)
			{
				//photoshop saves a,r,g,b into little endian b,g,r,a
				//this engine is expecting r,g,b,a so all that's needed is to flip 1st and 3rd bytes
				//be careful with this code if the image source program is working in r,g,b,a instead of a,r,g,b
				char* byteMem = (char*)&temp[i];
				char btemp = byteMem[0];
				byteMem[0] = byteMem[2];
				byteMem[2] = btemp;

			}
		}

		if (bOK)
			return 1;



		// Something went wrong, so cleanup everything
		return 0;

	}

 

 

Software Render:

else if (byteCount == 1)
		{


			UCHAR* sourceStartMem = (UCHAR*)source->GetData();
			DWORD* destStartMem = (texture_buffer)+(x1 + y1*lpitch32);

			int numColumns = (x2 - x1);
			int numRows = (y2 - y1);

			for (int row = 0; row < numRows; row++)
			{
				for (int column = 0; column < numColumns; column++)
				{
					int r = sourceStartMem[column];
					int g = sourceStartMem[column]; 
					int b = sourceStartMem[column];
					destStartMem[column] = _RGBA32BIT(r, g, b, 255);

					//the RGBA macro is defined like this
					//_RGBA32BIT(r, g, b, a) ( (r & 255) + ((g & 255) << 8) + ((b & 255) << 16)  + ((a & 255) << 24) )

				}

				destStartMem += lpitch32;
				sourceStartMem += image_width;
			}



		}

 

The generation of floor vertex buffer using the height map

//create the vertices
	Vertex* floorMesh = new Vertex[dim.x*dim.y];

	for (int xdim = 0; xdim < dim.x; xdim++)
	{
		for (int zdim = 0; zdim < dim.y; zdim++)
		{
          	//height map is just a Bitmap class, GetData returns a UCHAR pointer to the raw pixel array
			float height = heightMap.GetData()[xdim + zdim*dim.x];
		
			float color = (height)/ 255.0f;
			floorMesh[xdim + zdim*dim.x] = { XMFLOAT3((float)xdim, height , (float)zdim), XMFLOAT2(float(xdim)/dim.x, float(zdim)/dim.y) };
		} 
	}

 

SCreen.jpg

Edited by VanillaSnake21
Positioned image

Share this post


Link to post
Share on other sites
Advertisement
Posted (edited)

I think I've narrowed down the error to the loading function. What I've done is I've used gdiplus bitmap class to load up a bitmap, I've left the drawing code and the heightmap code the same and it came out right. So I'm pretty sure at this point that I'm not loading up the 8 bit bitmap correctly. But I'm really not sure what it could be. Here is a simplified code snippet from my op:

		// Read the bitmap file header
		ReadFile(hFile, &fileHeader, sizeof(BITMAPFILEHEADER), &dwBytesRead, NULL);

		// Read the bitmap info head
		ReadFile(hFile, &infoHeader, sizeof(BITMAPINFOHEADER), &dwBytesRead, NULL);

		// Go to pixel array position within the file
		SetFilePointer(hFile, fileHeader.bfOffBits, NULL, FILE_BEGIN);
		
		// Read the pixel array
		ReadFile(hFile, data, infoHeader.biSizeImage, &dwBytesRead, NULL);

	

What am I missing? Should I be loading the pallette even though I'm not using it? Just to reiterate that this code works for 32bit bitmaps.

Edited by VanillaSnake21

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • 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!