I wish to capture an image I rendered rendered in openGL. I use glReadPixels and then save the image with CImg. Unfortunately, the result is wrong. See below. The image on the left is correct. I captured it with GadWin PrintScreen. The image on the right is incorrect. I created it with glReadPixels and CImg:


I’ve done a lot of Web research on what might be wrong, but I’m out of avenues to pursue. Here the code the captures the image:
void snapshot() {
int width = glutGet(GLUT_WINDOW_WIDTH);
int height = glutGet(GLUT_WINDOW_HEIGHT);
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
int bytes = width*height*3; //Color space is RGB
GLubyte *buffer = (GLubyte *)malloc(bytes);
glFinish();
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
glFinish();
CImg<GLubyte> img(buffer,width,height,1,3,false);
img.save("ScreenShot.ppm");
exit(0);
}
Here is where I call the snapshot method:
void display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawIndividual(0);
snapshot();
glutSwapBuffers();
}
Following up on a comment, I grabbed the bit depth and printed to the console. Here are the results:
redbits=8
greenbits=8
bluebits=8
depthbits=24
CImg does not interleave its colors. That is, 3 red, green, blue pixels would be stored linearly as:
R1, R2, R3, …, G1, G2, G3, …, B1, B2, B3, …
However, OpenGL’s glReadPixel and glDrawPixel expect interleaved color components like this:
R1, G1, B1, R2, G2, B2, …
Additionally, OpenGL puts the origin (0,0) at the lower left corner of an image. CImg uses the more approach where the origin is at the top left of the image.
Here is a routine I wrote convert the interleaved colors to CImg’s channel-oriented format.
I should have probably added the code to account for the change in origin, but I felt lazy and decided to use CImg to do that. Once this routine is run, this code creates the image object:
And as far as I can tell, I do not have to set any packing parameters. Here is the code I use to grab the pixels from the OpenGL render target: