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) < sizeof(BITMAPFILEHEADER))
{
fclose(myFile);
return;
}
// Write the Bitmap INFO header to the file.
if (fwrite(&myBitmap, 1, sizeof(BITMAPINFOHEADER), myFile) < 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 < gnScreenWidth; nX++)
{
for (nY = 0; nY < 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) < 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!!