Advertisement

delete problem after using glReadPixels

Started by August 07, 2004 02:23 AM
1 comment, last by omega_sword 20 years, 4 months ago
Hi! Newbie alert! I'm just starting to learn OpenGL programming and ran into something I've been banging my head on for almost a week now. My code below simply renders a rotating triangle. I wanted to try and capture some of the frames and save it on bmp files but I'm having trouble with delete [] (at the end of the code, inside the main loop). If I simply create a pointer to an array of unsigned char and just delete it every iteration, no problem. But if I place the glReadPixels call in between I get a problem saying Debug Error! Program: ...\HomeTest.exe DAMAGE: after Normal block (#39) at 0x028551C0 I'm stumped. Can anybody help me please? I included the whole code so you might see any mistakes I made in setting up OpenGL.

#define WIND32_LEAN_AND_MEAN				// trim the excess fat from Windows

////// Includes
#include <windows.h>						// standard Windows app include
#include <gl/gl.h>							// standard OpenGL include
#include <gl/glu.h>							// OpenGL utilities
#include <gl/glaux.h>						// OpenGL auxiliary functions

////// Global Variables
float angle = 0.0f;							// current angle of the rotating triangle
HDC g_HDC;									// global device context
bool fullScreen = false;					// start off in full-screen mode
unsigned char *imageData;

// function to set the pixel format for the device context
void SetupPixelFormat(HDC hDC)
{
	int nPixelFormat;						// your pixel format index

	static PIXELFORMATDESCRIPTOR pfd = {
		sizeof(PIXELFORMATDESCRIPTOR),		//size of the structure
		1,									// version, always set to 1
		PFD_DRAW_TO_WINDOW |				// support window
		PFD_SUPPORT_OPENGL |				// support OpenGL
		PFD_DOUBLEBUFFER,					// support double buffering
		PFD_TYPE_RGBA,						// RGBA color mode
		32,									// go for 32 bit color mode
		0, 0, 0, 0, 0, 0,					// ignore color bits, not used
		0,									// no alpha buffer
		0,									// ignore shift bit
		0,									// no accumulation buffer
		0, 0, 0, 0,							// ignore accumulation bits
		16,									// 16-bit z-buffer size
		0,									// no stencil buffer
		0,									// no auxiliary buffer
		PFD_MAIN_PLANE,						// main drawing plane
		0,									// reserved
		0, 0, 0};							// layer masks ignored

	// choose best matching pixel format, return index
	nPixelFormat = ChoosePixelFormat(hDC, &pfd);

	// set pixel format to device context
	SetPixelFormat(hDC, nPixelFormat, &pfd);
}

// the Windows Procedure event handler
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static HGLRC hRC;						// rendering context
	static HDC hDC;							// device context
	char string[] = "Hello, world!";		// text to be displayed
	int width, height;

	switch(message)
	{
		case WM_CREATE:						// window is being created

			hDC = GetDC(hwnd);				// get current window's device context
			g_HDC = hDC;
			SetupPixelFormat(hDC);			// call your pixel format setup function

			// create rendering context and make it current
			hRC = wglCreateContext(hDC);
			wglMakeCurrent(hDC, hRC);

			return 0;
			break;

		case WM_CLOSE:						// windows is closing
			
			// deselect rendering context and delete it
			wglMakeCurrent(hDC, NULL);
			wglDeleteContext(hRC);

			// send WM_QUIT to message queue
			PostQuitMessage(0);

			return 0;
			break;

		case WM_SIZE:
			height = HIWORD(lParam);		// retrieve width and height
			width = LOWORD(lParam);

			if (height==0)					// don't wnat a divide by zero
			{
				height = 1;
			}

			// reset the viewport to new dimensions
			glViewport(0, 0, width, height);
			glMatrixMode(GL_PROJECTION);	// set projection matrix
			glLoadIdentity();				// reset projection matrix

			//calculate aspect ratio of window
			gluPerspective(45.0f, (GLfloat)width/(GLfloat)height, 1.0f, 1000.0f);

			glMatrixMode(GL_MODELVIEW);		// set modelview matrix
			glLoadIdentity();				// reset modelview matrix

			return 0;
			break;

		default:
			break;
	}

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

// the main Windows entry point
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	WNDCLASSEX	windowClass;			// window class
	HWND		hwnd;					// window handle
	MSG			msg;					// message
	bool		done;					// flag saying when you app is complete
	DEVMODE		devModeScreen;
	DWORD		extendedWindowStyle;	
	DWORD		windowStyle;
	RECT		windowRect;				// client area coordinates of the window

	// fill out the window class structure
	windowClass.cbSize				= sizeof(WNDCLASSEX);
	windowClass.style				= CS_HREDRAW | CS_VREDRAW;
	windowClass.lpfnWndProc			= WndProc;
	windowClass.cbClsExtra			= 0;
	windowClass.cbWndExtra			= 0;
	windowClass.hInstance			= hInstance;
	windowClass.hIcon				= LoadIcon(NULL, IDI_APPLICATION);	// default icon
	windowClass.hCursor				= LoadCursor(NULL, IDC_ARROW);		// default arrow
	windowClass.hbrBackground		= NULL;								// don't need background
	windowClass.lpszMenuName		= NULL;								// no menu
	windowClass.lpszClassName		= "MyClass";
	windowClass.hIconSm				= LoadIcon(NULL, IDI_WINLOGO);		// small icon

	// register the window class
	if (!RegisterClassEx(&windowClass))
		return 0;

	if (fullScreen==true)
	{
		//set display to full-screen
		memset(&devModeScreen, 0, sizeof(devModeScreen));	// clear the DEVMODE structure
		devModeScreen.dmSize = sizeof(devModeScreen);		// size of the structure
		devModeScreen.dmPelsWidth = 800;			// set the width 1152
		devModeScreen.dmPelsHeight = 600;			// set the height 864
		devModeScreen.dmBitsPerPel = 32;				// set the bits per pixel
		devModeScreen.dmFields = DM_PELSWIDTH |DM_PELSHEIGHT | DM_BITSPERPEL;

		if (ChangeDisplaySettings(&devModeScreen, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
			// change has failed, you'll run in windowed mode
			fullScreen = false;
	}

	if (fullScreen)
	{
		extendedWindowStyle = WS_EX_APPWINDOW;		// hide top level windows
		windowStyle = WS_POPUP;						// no border on your window
		ShowCursor(false);
	}
	else
	{
		extendedWindowStyle = NULL;					// same as earlier example
		windowStyle =	WS_OVERLAPPEDWINDOW | WS_VISIBLE |
						WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
	}

	// readjust window
	windowRect.top = 0;				// top left
	windowRect.left = 0;
	windowRect.bottom = 600;
	windowRect.right = 800;
	AdjustWindowRectEx(&windowRect, windowStyle, false, extendedWindowStyle);

	// class registered, so now create your window
	hwnd = CreateWindowEx(	extendedWindowStyle,						// extended style
							"MyClass",									// class name
							"The OpenGL Window Applicaion",				// app name
							windowStyle,								// style
							0, 0,										// x,y coordinate
							windowRect.right - windowRect.left,			// width
							windowRect.bottom - windowRect.top,			// height
							NULL,										// handle to parent
							NULL,										// handle to menu
							hInstance,									// application instance
							NULL);										// no extra params

	// check if window creation failed (hwnd would equal NULL)
	if (!hwnd)
		return 0;

	ShowWindow(hwnd, SW_SHOW);		// display the window
	UpdateWindow(hwnd);				// update the window

	done = false;					// initialize the loop condition variable
	imageData = NULL;

	// main message loop
	while (!done)
	{
		PeekMessage(&msg, hwnd, NULL, NULL, PM_REMOVE);

		if (msg.message == WM_QUIT)		// do you receive a WM_QUIT message?
		{
			done = true;				// if so, time to quit the application
		}
		else
		{
			// do rendering here
			// clear screen and depth buffer
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
			glLoadIdentity();		// reset modelview matrix

			angle = angle + 5.0f;	// increase your rotation angle counter
			if (angle >= 360.0f)	// reset angle counter
				angle = 0.0f;
			glTranslatef(0.0f, 0.0f, -5.0f);		//move back 5 units
			glRotatef(angle, 0.0f, 1.0f, 0.0f);		//rotate along z-axis

			glColor3f(1.0f, 0.0f, 0.0f);			// set color to red
			glBegin(GL_TRIANGLES);					// draw the triangle
				glVertex3f(0.0f, 0.0f, 0.0f);
				glVertex3f(1.0f, 0.0f, 0.0f);
				glVertex3f(1.0f, 1.0f, 1.0f);
			glEnd();

			//glRasterPos3i(intX, intY, -50);		
			//glReadPixels(intX, intY, intWidth, intHeight, GL_RGB, GL_UNSIGNED_BYTE, uchrImageData);
			//glDrawPixels(intWidth, intHeight, GL_RGB, GL_UNSIGNED_BYTE, uchrImageData);

			imageData = new unsigned char [42*42*3];
			memset(imageData, 0, 42 * 42 * 3);		// clear the allocated memory
			glReadPixels(400, 300, 42, 42, GL_RGB, GL_UNSIGNED_BYTE, imageData);
			delete [] imageData;

			SwapBuffers(g_HDC);						// bring back buffer to foreground

			TranslateMessage(&msg);					// translate/dispatch to event queue
			DispatchMessage(&msg);
		}
	}

	return msg.wParam;
}

You did not take the data-alignment into account. Read up about glPixelStore for more information.

In short what happens is, that the rows are aligned to 4 bytes. So, if i.e. your row is 3 pixel wide, it only has 3 * 3 = 9 bytes. Than it is aligned to the next multiple of 4, in this case to 12 bytes. Instead of your expected 9 bytes every row of your pixeldata takes up 12 bytes with 3 bytes padded.

Solutions:

1. Change the Alignment with glPixelStore

2. Change your buffer to take the padding into account.

Advertisement
Bullseye! It finally worked!!! Both solutions worked like a charm. I used GL_PACK_ALIGNMENT = 1 and GL_UNPACK_ALIGNMENT = 1 (for glDrawPixels). What I still don't get is why using =3 (since I have a pixelwidth of 3) doesn't work. Hmm... You're right that I don't know much about glPixelStorei and to tell you the truth I'm still trying to digest your explanation but I think I get the gist of it. I'll take your advice and read up on it.

Hope you can help me next time I'm in a rut. Thanks!!!

This topic is closed to new replies.

Advertisement