Jump to content
  • Advertisement
Sign in to follow this  
Thevenin

Playing with Pixels (Warning: Lots of source code) [Solved]

This topic is 4726 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

Before implementing DIBs into my game (BitBlt just had to go), I wanted to test it out to make sure I could get the structural math right for blitting and such. My first objective was to get rid of bitmaps entirely, and switch to a very simple file format (Just a linear array of RGB quads in Row-Major form, no image dimensions are stored within the file itself). My BMP -> FSF converter (FSF being merly a term I coined. xD)
#include <stdio.h>
#include "windows.h"

#pragma pack(1)

struct strRGB
{
	unsigned char bytBlue, bytGreen,bytRed;
};

void main()
{
	struct strRGB chrRGB;
	char chrFileName[100];
	HDC hdcBitmap;
	HBITMAP lngBitmap;
	HDC hTempImage;
	int intWidth, intHeight;
	FILE *f;
	int x,y;

	int intRGB;

	/* Get the path. */
	printf("This tool will convert a 24bit bitmap file into a FSF.\n"
		   "To begin, enter the name of the file.\n->");
	scanf("%s", chrFileName);

	/* What is the width and height of this image? */
	printf("What is the width and height of this image?\nWidth ->");
	scanf("%d", &intWidth);
	printf("Height ->");
	scanf("%d", &intHeight);

	/* Create the surface. */
    hdcBitmap = CreateCompatibleDC(GetDC(0));
	lngBitmap = CreateCompatibleBitmap(GetDC(0), intWidth, intHeight);
	SelectObject(hdcBitmap, lngBitmap);

	/* Load the image. */
    hTempImage = LoadImage(0, chrFileName, 0, 0, 0, 16);
    SelectObject(hdcBitmap, hTempImage);
    DeleteObject(hTempImage);

	/* Prepare the output file. */
	printf("Writing to 'Output.fsf'.\n");
	f = fopen("Output.fsf", "wb");

	/* Now write! */
	for(x=0;x<intWidth;x++)
		for(y=(intHeight-1); y>0; y--)
		{
			chrRGB.bytRed = (unsigned char)GetPixel(hdcBitmap,x,y);
			chrRGB.bytGreen = ((unsigned char)(((unsigned short)(GetPixel(hdcBitmap,x,y))) >> 8));
			chrRGB.bytBlue = ((unsigned char)((GetPixel(hdcBitmap,x,y)) >> 16));	
			fwrite(&chrRGB,sizeof(struct strRGB),1,f);
		}

	/* Unload the resources. */
	fclose(f);
	DeleteObject(lngBitmap);
	DeleteObject(hdcBitmap);
}





Than I wrote up an application to draw this onto a screen (With some color changing background).
#pragma pack(1)

#include <stdio.h>
#include "string.h"
#include "windows.h"
//#include "resource.h"

extern LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
extern void sCalculateFPS();
extern struct strRGB* sLoadFSF(char *chrFileName, int intWidth, int intHeight);
extern void sDrawFSF(int intPX, int intPY, int intPWidth, int intPHeight, int intWidth, int intHeight, struct strRGB *chrDest,struct strRGB *chrSrc);

/*  Windows Information */
HWND hwnd; /* Our Window Handle */
HDC WindowDC;
HCURSOR hCursor;
HFONT hSmallFont;
HFONT hBigFont;
HBRUSH hBrush;
BITMAPINFO bmi;
HINSTANCE hInstance;
RECT r;


struct strRGB
{
	unsigned char bytBlue, bytGreen,bytRed;
};

struct strRGB *rgbBear;


HINSTANCE hDib;

HBITMAP hBackBuffer;

/* Mouse Globals. */
short int intMouseClickX,intMouseClickY,
		  intMouseReleaseX,intMouseReleaseY,
	      intMouseX,intMouseY;

int bytSelectedSlot, bytDestinationSlot;
char bytMouse, bytDragging = 0;
struct strRGB *arrBits;

/* Global Loop Variables. */
POINT p;
unsigned char color=0;

/* For capturing keyboard text. */
char chrString[80];
char chrSending[80];
char chrDebug[100];
char bytChar;

/* Stupid Win32 */
PAINTSTRUCT ps;    
char bytFullscreen=1;
unsigned short intOldResWidth;
unsigned short intOldResHeight;

LARGE_INTEGER intCurrentTick;
LARGE_INTEGER intLastTick;
LARGE_INTEGER intFreq;
double dblFPS;

/* Used to determine which keys are being held by the user's  keyboard. */
char bytLoop=1;


/* Main Window Information */
int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil)
{
	int x,y;
    /* Create the absurdly abstract 'Window' (I hate Windows!) */
	MSG messages; WNDCLASSEX wincl;
	hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.hInstance = hThisInstance; wincl.lpszClassName = "WindowsApp"; wincl.lpfnWndProc = WindowProcedure;
    wincl.style = CS_DBLCLKS; wincl.cbSize = sizeof (WNDCLASSEX); wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION); wincl.hCursor = hCursor;
    wincl.lpszMenuName = NULL; wincl.cbClsExtra = 0; wincl.cbWndExtra = 0; wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
    if (!RegisterClassEx (&wincl)) return 0;
    hwnd = CreateWindowEx (0, "WindowsApp","DIB Testing", WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX,
           CW_USEDEFAULT,CW_USEDEFAULT, (800+6), (600+32), HWND_DESKTOP, NULL, hThisInstance, NULL);
	WindowDC = GetDC(hwnd);
	hSmallFont = CreateFont(-MulDiv(5, GetDeviceCaps(WindowDC, LOGPIXELSY), 72), 0, 0, 0, 0, FALSE, 0, 0, 0, 0, 0, 0, 0, "Small Fonts");
	hBigFont = CreateFont(-MulDiv(7, GetDeviceCaps(WindowDC, LOGPIXELSY), 72), 0, 0, 0, 0, FALSE, 0, 0, 0, 0, 0, 0, 0, "Small Fonts");
    ShowWindow (hwnd, nFunsterStil);
	SetCursor(hCursor);
	hInstance = hThisInstance;

	// Initialize the fields in the BITMAPINFO structure. 
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
	bmi.bmiHeader.biHeight = 600;
	bmi.bmiHeader.biWidth = 800;
    bmi.bmiHeader.biPlanes = 1; 
    bmi.bmiHeader.biBitCount = 24; 
    bmi.bmiHeader.biCompression = BI_RGB; 
    bmi.bmiHeader.biSizeImage = ((600 * 24 +31) & ~31)/8 * 800; 
	bmi.bmiHeader.biClrImportant = 0; 

	   QueryPerformanceFrequency(&intFreq);
    QueryPerformanceCounter(&intCurrentTick);

	hDib = CreateDIBSection(WindowDC,&bmi,DIB_RGB_COLORS,&arrBits,NULL,NULL);
	if(hDib == NULL)
	{
		MessageBox(hwnd,"Error creating DIB","AWW NUTTS",0);
	}

	r.left = 0;
	r.right = 300;
	r.top = 0;
	r.bottom = 300;

	/* Create the bear.*/
	rgbBear = sLoadFSF("Bear.fsf", 384,32);



	while(bytLoop)
	{
		while(PeekMessage(&messages, NULL, 0, 0, PM_REMOVE))
		{
			if(messages.message == WM_QUIT)bytLoop=0;
			TranslateMessage(&messages);
			DispatchMessage(&messages);
		}

	/* Main game loop. */
		for(y=0;y<600;y++)
			for(x=0;x<800;x++)
			{
				arrBits[x+(800*y)].bytRed++;
				arrBits[x+(800*y)].bytBlue-=2;
				arrBits[x+(800*y)].bytGreen = arrBits[x+(800*y)].bytRed - arrBits[x+(800*y)].bytBlue;
			}

		sDrawFSF(0, 0, 800, 600, 384,32, arrBits, rgbBear);
		sCalculateFPS();
		sprintf(chrDebug,"FPS = %f1.1",dblFPS); 
		/* Deals with game content. */
		RedrawWindow(hwnd, 0, 0, 1);
	}
	return 0;
}


/*  This function is called by the Windows function DispatchMessage()  */
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static int x,y;
	switch(message)
	{
		case WM_PAINT:
			WindowDC = BeginPaint(hwnd, &ps);
			if(SetDIBitsToDevice(WindowDC,0,0,800,600,0,0,0,600,arrBits,&bmi,DIB_RGB_COLORS) == 0) PostQuitMessage(0);
			DrawText(WindowDC, chrDebug,strlen(chrDebug),&r,DT_LEFT);
			EndPaint(hwnd, &ps);
		break;



		case WM_DESTROY:
			PostQuitMessage (0);
			free(arrBits);
			free(rgbBear);
		break;

		default:
			return DefWindowProc (hwnd, message, wParam, lParam);
		break;
	}
}

/* This procedure calculates the game's frame-rate. */
void sCalculateFPS()
{
	static int dblRun = 4;
	static double dblTotal = 4*30;

	intLastTick = intCurrentTick;
	QueryPerformanceCounter(&intCurrentTick);
	dblTotal += ((intCurrentTick.QuadPart-intLastTick.QuadPart)/(intFreq.QuadPart/1.0));
	dblRun++;

	if(dblRun==5)
	{
		dblFPS = 1.0/(dblTotal/dblRun);
		dblRun=0;
		dblTotal=0;
	}
	if(dblFPS > 500 || dblFPS < 1) dblFPS = 1;
}


/* This procedure loads the sprite file into the game. */
struct strRGB* sLoadFSF(char *chrFileName, int intWidth, int intHeight)
{
	int x,y;
	struct strRGB *rgbBuf;
	FILE *tempf;
	tempf = fopen(chrFileName, "rb");

	/* Allocate enough memory. */
	rgbBuf = malloc(3*intWidth*intHeight);

	/* Now read!1 */
	for(x=0;x<intWidth;x++)
		for(y=0;y<intHeight;y++)
			fread(&rgbBuf[(x*intHeight) + y],sizeof(char),3,tempf);

	fclose(tempf);
	return rgbBuf;
}

/* This function draws the sprite into a buffer . */
void sDrawFSF(int intPX, int intPY, int intPWidth, int intPHeight, int intWidth, int intHeight, struct strRGB *chrDest,struct strRGB *chrSrc)
{
	int x,y;

	/* For all pixels in the FSF. */
	for(x=0;x<intWidth;x++)
		for(y=0;y<intHeight;y++)
			memcpy(&chrDest[intPY + y + (intPX*intPHeight) + (x*intPHeight)]
				  ,&chrSrc[(x*intHeight) + y], 3);

	/* All done. xD */
}




The results I get are quite ackward. The program compiles and runs just fine, but the blt of the bear isn't right. On the plus side though, if you combine a view of those vertical (Yes, its not even suppose to be vertical) bltz, you can see it sorta resembles the bear. :( Below are screenshots.... Program Output Image Hosted by ImageShack.us Original Bear.bmp Image Hosted by ImageShack.us What have I done wrong? [depressed] Edit: The placement of my comments seems to have gotten scrambled.... [rolleyes] [Edited by - Thevenin on June 17, 2005 12:46:22 AM]

Share this post


Link to post
Share on other sites
Advertisement
lol, perhaps I'm in the wrong field.

Just now, I thought "Wait, I got it, I got it", made a slight change in the code, ran it, and blam!

Image Hosted by ImageShack.us

Now thats something to hang on my wall.

Share this post


Link to post
Share on other sites
Ok, one last one, just because this one had some significance...

Image Hosted by ImageShack.us

The bear is perfectly drawn (Though, slight color loss and rotated).

Share this post


Link to post
Share on other sites
Got it working (BMP->FSF && Draw functions were out of wack).

Can't argue with the frame-rate either...
Image Hosted by ImageShack.us

I'm gonna have alot of happy players after my next release! [smile]

Edit: Oh wow, transparency costs sooo little! [smile]
Image Hosted by ImageShack.us

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.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!