Copy screen to array

I’ve just drawn a simple square with a texture on it in the window, then all I need to do is basically take a screen shot of the window after a few rotations/translations, then output this to a .bmp file. I’ve done the .bmp file writing function which simply requires a 1D array of pixel data. (its in RGB format so 1 pixel takes up 3 spaces in the arrays). So how would I go about copying a window’s contents into an array exactly how it appears on screen?

Will glReadPixels() do this? I’ve had a play with it but I dont quite understand the parameters and I think I’ve got it setup incorrectly:

glReadPixels(100,100,256,256,GL_RGB, GL_UNSIGNED_BYTE, printData);

This just gives me an array which is almost entirely filled with 0’s and the few numbers that are there are very large (~40000-50000).

Have I just made a silly mistake or would I be better off using another function that is more suitable?


glReadPixels will do it. The first four parameters control what part of the window you want to get; the above will get you [100,356]x[100,356]. Is that what you want? It certainly isn’t the entire window, which normally starts at 0,0.

GL_RGB says that the array you’ve providing contains room for 3widthheight values (3256256 in this case), and where those values should come from (R, G, and B). GL_UNSIGNED_BYTE says that each of the values put into the array should be of type unsigned char, in other words the total size of “printData” needs to be 3256256sizeof(unsigned char) and it’s type needs to be unsigned char.

If all of this sounds right, then the other thing to look at is whether you’ve properly called glReadBuffer(GL_FRONT). That tells glReadPixels where to take data from.

Personally, I suspect that the type of printData is not unsigned char*, because an unsigned char could not possibly have value 40,000.

Thanks for the quick reply Lindley.

With regard to the first 4 parameters - the window is only 256 x 256 and the top left of the window is at pixel 100, 100. The documentation says that the first two parameters x,y specify the lower left of the window so personally I would have thought I should be using (100, 356, 256, 256…) as the first 4 parameters but this gives me all 0’s in the array so I thought that must be wrong, at least (100, 100, 256, 256…) gives me some values! :o

As for the definition of my array and the GLenum type i’ve tried numerous combinations, none of which seem to work. It is currently:

GLushort printData[imageWidth * imageHeight * 3];

glReadPixels(100,100,256,256,GL_RGB, GL_UNSIGNED_SHORT, printData);

And as for calling glReadBuffer(GL_FRONT)…I didn’t even know what it was. :o I have included it just before my call to glReadPixels but it still gives me the same results.

Incidently my general program structure is as follows: (If it makes any difference)
-load texture
-bind texture
-display the window and draw vertices
-call my function with glReadPixels and glReadBuffer in when a certain key is pressed

Any ideas?

Firstly try this:

GLubyte printData[256 * 256 * 4];
glReadPixels(0,0,256,256,GL_RGBA, GL_UNSIGNED_BYTE, printData);

And view the output data to ensure you are getting the right values.

Then change the width/height to what you need

GLubyte printData[imageWidth * imageHeight * 4];
glReadPixels(0,0,imageWidth,imageHeight,GL_RGBA, GL_UNSIGNED_BYTE, printData);

Note that glReadPixels width/height indicates the width and height of the destination buffer.

Next move the buffrer to the position you want. Note that in OpenGL all coordinates are measured from the lower left hand corner. so pixel 0,0 is the pixel in the bottom left hand corner of the screen.

A quick sanity check to see if you’re getting anything reasonable is to change the glClearColor to something like (.1,.2,.3,.4), do a glClear (and swapbuffers if necessary), and then see if the values you’re reading back match the clearcolor.

Thanks for all your help sqrt[-1] and Lindley. Turns out the first two parameters should have been to 0,0. I just didn’t understand the documentation properly. :o

Thanks again!