Save a OpenGL image?

I am new to this and have a program that creates an opengl image. I would like to modify the program to allow the user to save the image as a bitmap or some sort of image file type. There has got to be a way to do this but the documentation I have does not address this issue.

Use glReadPixels()

Heres some code… (With the details on how to actually write the BMP file…)
—8<-----------------------------------
void rgDisplay::SaveView(char *szFile)
{
HDC hdc;
BITMAPINFOHEADER myBitmap;
BITMAPFILEHEADER bmpFile;
char *szBits;
char *szOutput;
FILE *myFile;
int nX;
int nY;

// Get the current DC.
hdc = wglGetCurrentDC();

// Yes this is meant to be "MB"  (Little Endian)
bmpFile.bfType = 'MB';
bmpFile.bfSize = sizeof(BITMAPFILEHEADER);
bmpFile.bfReserved1 = bmpFile.bfReserved2 = 0;
bmpFile.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

// Create the Bitmap info header.
myBitmap.biSize = sizeof(BITMAPINFOHEADER);
myBitmap.biWidth = gnScreenWidth;  // Size in pixels...
myBitmap.biHeight = gnScreenHeight; // Size in pixels...
myBitmap.biPlanes = 1;
myBitmap.biBitCount = 24;
myBitmap.biCompression = BI_RGB;
myBitmap.biSizeImage = 0;
// The following two lines are a bit dodgy.  It gets the systems "Pixels per inch", divides it by
// 2.5 (cm) and turns that into Meters...  It works though...
myBitmap.biXPelsPerMeter = (int)((float)(GetDeviceCaps(hdc, LOGPIXELSX)/2.5f) * 100.0f);
myBitmap.biYPelsPerMeter = (int)((float)(GetDeviceCaps(hdc, LOGPIXELSY)/2.5f) * 100.0f);
myBitmap.biClrUsed = 0;
myBitmap.biClrImportant = 0;

// Open the file.
if ((myFile = fopen(szFile, "wb")) == NULL)
	return;

// Write the file header to the file.
if (fwrite(&bmpFile, 1, sizeof(BITMAPFILEHEADER), myFile) &lt; sizeof(BITMAPFILEHEADER))
	{
	fclose(myFile);
	return;
	}

// Write the Bitmap INFO header to the file.
if (fwrite(&myBitmap, 1, sizeof(BITMAPINFOHEADER), myFile) &lt; sizeof(BITMAPINFOHEADER))
	{
	fclose(myFile);
	return;
	}

// Allocate the buffers.
szBits = (char *)malloc(gnScreenWidth * gnScreenHeight * 4);
szOutput = (char *)malloc(gnScreenWidth * gnScreenHeight * 3);

// Get the pixels from the OpenGL context.
glReadPixels(0, 0, gnScreenWidth, gnScreenHeight, GL_RGBA, GL_UNSIGNED_BYTE, szBits);

// Reverse the bits... (TURN RGBA INTO BGR.. Or is it BGRA into RGB?)
for (nX = 0; nX &lt; gnScreenWidth; nX++)
	{
	for (nY = 0; nY &lt; gnScreenHeight; nY++)
		{
		szOutput[((nY * gnScreenWidth) + nX) * 3] = szBits[(((nY * gnScreenWidth) + nX) * 4) + 2];
		szOutput[(((nY * gnScreenWidth) + nX) * 3) + 1] = szBits[(((nY * gnScreenWidth) + nX) * 4) + 1];
		szOutput[(((nY * gnScreenWidth) + nX) * 3) + 2] = szBits[(((nY * gnScreenWidth) + nX) * 4)];
		}
	}

// Write the bitmap to the file.
if (fwrite(szOutput, 1, gnScreenHeight * gnScreenWidth * 3, myFile) &lt; sizeof(gnScreenHeight * gnScreenWidth * 4))
	{
	free(szBits);
	fclose(myFile);
	return;
	}

free(szBits);
fclose(myFile);

} // End of rgDisplay::SaveView().

—8<-----------------------------------

Oh yeah…

I definitely recommend the following book…

OpenGL SuperBible (2nd Ed or more)
Wait Group PRESS
Richard S. Wright Jr. &
Michael Sweet.

Unlike some of the “Official” OpenGL publications (Red book being one of them) it actually shows you some REALLY useful techniques - like shadows for example. I bought it because it had code that specifically drew shadows (I now understand the process and understand it when people write “Oh you just create a shadow matrix and multiply it out…”

Thanks alot for the code! This really helps alot!!