Advertisement

Issues with loading/drawing a bitmap

Started by January 06, 2019 09:17 PM
3 comments, last by VanillaSnake21 6 years, 1 month ago

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

You didn't come into this world. You came out of it, like a wave from the ocean. You are not a stranger here. -Alan Watts

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.

You didn't come into this world. You came out of it, like a wave from the ocean. You are not a stranger here. -Alan Watts

Advertisement

Your image looks like the width is not matching, with an error of 2 (I think) each line. My guess is that your bitmap format is being padded to a multiple-of-4 width for each line when it's saved out.

See the BMP format description on wikipedia.

Yes! That was it. Using the formula to calculate the proper pitch fixed it.Thanks!

You didn't come into this world. You came out of it, like a wave from the ocean. You are not a stranger here. -Alan Watts

This topic is closed to new replies.

Advertisement