Sign in to follow this  
Avenyr

Problems loading a bitmap file into self-created structure

Recommended Posts

Hello! I've had a problem for the past few days trying on my own to load a bitmap in a C++ class i've made up from the informations gathered on MSDN. I had also read a bit of the Windows Games Programming Gurus and I have some code from that book that can get me to load a bitmap without any problems but I don't want to just copy&paste and then move on because I want to understand the "How and Why" of doing it so that I can get a better understanding of what i'm doing wrong etc... At the moment I am able to load all the proper info in BITFILEHEADER and BITMAPV5HEADER structures but it starts to bug on me with the color palettes and the actual bitmap data matrix. Also the whole procedures are made in order to load up uncompressed 16-bits BMP only at the moment. Once this will be done and I understand what's wrong then I will adapt it for 8,24 and 32 bits loading.
//paddles.h
#include <windows.h>
#include <stdio.h>
#include <io.h>
#include <ddraw.h>

#define WIN32_LEAN_AND_MEAN  // just say no to MFC

/////////////////////////Classes Definitions/////////////

class BitmapFile
{
public:
	BITMAPFILEHEADER BmpFileHeader;
	BITMAPV5HEADER   BmpV5Header;
	RGBQUAD*         pRGBQuad;
	USHORT*			 pBmpData;
};

//////////////////////////Window Objects/////////////////
HWND hwndWindow             = NULL;
HDC  hdc					= NULL;
//////////////////////////DDRAW Objects//////////////////
LPDIRECTDRAW7 lpdd7         = NULL;

LPDIRECTDRAWSURFACE7 lpdds7_OffScreen = NULL;
LPDIRECTDRAWSURFACE7 lpdds7 = NULL;
DDSURFACEDESC2 ddsd2;

HRESULT ddrval              = NULL;

//////////////////////////Misc Variables/////////////////
char buffer[80];
bool window_closed= 0;
BitmapFile image;
RECT ImageRect;
//////////////////////////Function Definitions///////////

void Error(LPCTSTR message);
bool LoadBitmapFile(char* FileName, BitmapFile* Bmp);
USHORT _RGB16(BYTE R,BYTE G,BYTE B);
UINT _RGB32(BYTE A, BYTE R, BYTE G, BYTE B);
#define KeyDown() (GetAsyncKeyState(VK_ESCAPE) & 0x8000 ? 1:0)
bool SendImageToSurface(BitmapFile* Bmp);
//End paddles.h

//paddles.cpp
#include "Paddles.h"

LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMSG,WPARAM wParam,LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	RECT rect;

	switch(uMSG)
	{
		case WM_CREATE:
		{

			return 0;	
		}break;

		case WM_PAINT:
		{
			hdc = BeginPaint(hwnd,&ps);
			
			EndPaint(hwnd,&ps);
			return 0;
		}break;

		case WM_DESTROY:
		{
			PostQuitMessage(NULL);
			return 0;
		}break;

	}
	return DefWindowProc(hwnd,uMSG,wParam,lParam);
}

int GameInit()
{
	SetRect(&ImageRect,0,0,320,200);
	if(!(DirectDrawCreateEx(NULL,(LPVOID*)&lpdd7,IID_IDirectDraw7,NULL))==DD_OK)
		return(0);

	if(!(lpdd7->SetDisplayMode(320,200,16,NULL,NULL)) == DD_OK)
		return(0);

	if(!(lpdd7->SetCooperativeLevel(hwndWindow,DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN))==DD_OK)
		return(0);

	ZeroMemory(&ddsd2,sizeof(ddsd2));

	ddsd2.dwSize = sizeof(ddsd2);

	ddsd2.dwFlags = DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
	ddsd2.ddsCaps.dwCaps = DDSCAPS_FLIP|DDSCAPS_COMPLEX|DDSCAPS_PRIMARYSURFACE;
	ddsd2.dwBackBufferCount = 1;

	if(!(ddrval = lpdd7->CreateSurface(&ddsd2,&lpdds7,NULL)) == DD_OK)
		return(0);
	
	ZeroMemory(&ddsd2,sizeof(ddsd2));

	ddsd2.dwSize = sizeof(ddsd2);
	ddsd2.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH;
	ddsd2.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN|DDSCAPS_VIDEOMEMORY;
	ddsd2.dwHeight = 200;
	ddsd2.dwWidth  = 320;

	if(!(ddrval = lpdd7->CreateSurface(&ddsd2,&lpdds7_OffScreen,NULL))== DD_OK)
		return(0);

	if(!(LoadBitmapFile("test.bmp",&image)))
	{
		Error("Error Loading Bitmap");
		return(0);
	}

	if(!(SendImageToSurface(&image)))
	{	
		Error("Cannot Send Image to Surface");
		return(0);
	}

	return(1);
} 

int GameMain()
{
	if(KeyDown())
	{
		window_closed = 1;
		SendMessage(hwndWindow,WM_CLOSE,NULL,NULL);
	}

	if(window_closed)
		return(0);

	lpdds7->Blt(NULL,lpdds7_OffScreen,NULL,NULL,NULL);
	/*lpdds7->Lock(NULL,&ddsd2,DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT,NULL);
	USHORT* vid_mem = (USHORT*)ddsd2.lpSurface;

	for(int x = 0 ;x < 640;x++)
	{
		for(int y = 0; y<480; y++)
		{
			vid_mem[(x + y * (ddsd2.lPitch >> 1))] = _RGB16(255,0,0);
		}
	}
	lpdds7->Unlock(NULL);*/
	lpdds7->Flip(NULL,DDFLIP_WAIT);
	return(1);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow)
{
	HWND hwnd;
	MSG msg;
	WNDCLASSEX wndclass;

	wndclass.cbSize        = sizeof(WNDCLASSEX);
	wndclass.style         = CS_VREDRAW|CS_HREDRAW;
	wndclass.lpfnWndProc   = WindowProc;
	wndclass.cbClsExtra    = NULL;
	wndclass.cbWndExtra    = NULL;
	wndclass.hInstance     = hInstance;
	wndclass.hIcon         = NULL;
	wndclass.hCursor       = NULL;
	wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wndclass.lpszMenuName  = NULL;
	wndclass.lpszClassName = "RPG";
	wndclass.hIconSm       = NULL;
	
	if(!(RegisterClassEx(&wndclass)))
	{
		MessageBox(NULL,"Error Registering class", "Error", MB_OK);
		return 0;
	}
	
	hwnd = CreateWindow("RPG","TEST",WS_OVERLAPPEDWINDOW|WS_VISIBLE,0,0,640,480,NULL,NULL,hInstance,NULL);
	
	hwndWindow = hwnd;

	if(!(GameInit()))
		return(0);

	while(true)
	{
		if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
		{
			if(msg.message == WM_QUIT)
				break;

			TranslateMessage(&msg);

			DispatchMessage(&msg);
		}

		GameMain();		
	}

	return msg.wParam;
}

void Error(LPCTSTR message)
{
	MessageBox(NULL,message,ERROR,MB_OK);
}

USHORT _RGB16(BYTE R, BYTE G, BYTE B)
{
	return ((B & 31) + ((G & 63)<<5) + ((R & 31)<<11));
}

bool LoadBitmapFile(char* FileName, BitmapFile* Bmp)
{
    HANDLE hFile      = NULL;
	DWORD BytesRead = NULL;

	if((hFile = CreateFile(FileName,GENERIC_READ,0,NULL,OPEN_EXISTING,NULL,NULL)) == INVALID_HANDLE_VALUE)
	{	
		Error("INVALID_HANDLE_VALUE");
		return(0);
	}
	

	if(!(ReadFile((HANDLE)hFile,&Bmp->BmpFileHeader,sizeof(BITMAPFILEHEADER),&BytesRead,NULL)))
	{	
		Error("Cannot Read BmpFileHeader");
		return(0);
	}

	if(!(Bmp->BmpFileHeader.bfType == 0x4D42))
	{	
		Error("Not a Bitmap");
		return(0);

	}

	if(!(ReadFile(hFile,&Bmp->BmpV5Header,sizeof(BITMAPV5HEADER),&BytesRead,NULL)))
	{	
		Error("Cannot Read BmpV5Header");
		return(0);
	}

	if(Bmp->BmpV5Header.bV5BitCount != 16)
	{
		Error("BitCount is not 16bits");
		return(0);
	}
	
	// Read File with number of bytes equal to the size of RGBQUAD multiplied by the number of ColorUsed in the bitmap

	/*if(!(ReadFile(hFile,Bmp->pRGBQuad,sizeof(RGBQUAD)*Bmp->BmpV5Header.bV5ClrUsed,&BytesRead,NULL)))
	{
		Error("Cannot Load RGBQUAD array");
		return(0);
	}*/
	
	if(Bmp->BmpV5Header.bV5SizeImage == 0)
	{
		Bmp->BmpV5Header.bV5SizeImage = Bmp->BmpV5Header.bV5Width*Bmp->BmpV5Header.bV5Height;
	}


//	_lseek((int)hFile,-(int)(Bmp->BmpV5Header.bV5SizeImage),SEEK_END);
	
	if(!(Bmp->pBmpData))
		free(Bmp->pBmpData);

	if(!(Bmp->pBmpData = new USHORT[Bmp->BmpV5Header.bV5SizeImage]))
	{
		Error("Cannot allocate memory");
		return(0);
	}		

	if(!(ReadFile(hFile,Bmp->pBmpData,Bmp->BmpV5Header.bV5SizeImage,&BytesRead,NULL)))
	{
		Error("Cannot Load Data");
		return(0);
	}

	//sprintf(buffer,"%C",Bmp->BmpV5Header.bV5Compression);
	//Error(buffer);
	
	CloseHandle(hFile);

	return(1);
}

bool SendImageToSurface(BitmapFile* Bmp)
{
	lpdds7_OffScreen->Lock(NULL,&ddsd2,DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT,NULL);
	
	USHORT* vid_mem = NULL;
	vid_mem = (USHORT*)ddsd2.lpSurface;

	for(int x = 0; x < Bmp->BmpV5Header.bV5Width;x++)
	{
		for(int y = 0; y < Bmp->BmpV5Header.bV5Height; y++)
		{
			vid_mem[x+y*(ddsd2.lPitch>>1)] = Bmp->pBmpData[x+(y*Bmp->BmpV5Header.bV5Width)];
		}
	}

	lpdds7_OffScreen->Unlock(NULL);

	return(1);
}
//End paddles.cpp

So the problem with my application is that when I blit from the offscreen surface to the current display I get a black RECT from the size of the image and I assume the problem is with the BMP loading or the other function since I can lay pixels on the surface manually and blit without problems. Thank you for your help ! ; ) [Edited by - Avenyr on July 7, 2004 12:16:22 PM]

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

Sign in to follow this