1

I'm trying to do a screen capture in GLUT and I'm having a bit of an issue. glReadPixels() seems to crash my program with an

Access violoation writing location 0x00000000

The thing that is weird is the file is created in the root of the project, and is obviously empty. I set up some printf commands quickly and it appears that the code crashes each time during the glReadPixels() method.

I feel the issue maybe the variable 'pixels'. Im having trouble figuring out the correct way to define this so that the RGB values are written to it.

Any tips would be appreciated.

void savePPM(char ppmFileName[]){
    int width = glutGet(GLUT_WINDOW_WIDTH);
    int height = glutGet(GLUT_WINDOW_HEIGHT);
    char *pixels = NULL;

    glReadPixels(0,0, width, height, GL_RGB, GL_UNSIGNED_BYTE ,pixels);

    ppmFile = fopen(ppmFileName, "wb");

    fprintf(ppmFile, "P6\n");
    fprintf(ppmFile, "%d %d\n", width, height);
    fprintf(ppmFile, "255\n");
    fwrite(pixels, 1, width*height*3, ppmFile);

    fclose(ppmFile);
    free(pixels);
}
meriley
  • 1,831
  • 3
  • 20
  • 33

1 Answers1

4

glReadPixels doesn't allocate memory for you, it merely stores the pixel data in the buffer that you give it in the last parameter. You're giving it a NULL pointer, so it's trying to store data at address 0, which obviously results in an access violation.

You need to allocate the memory first, pass it to glReadPixels, and then deallocate it. You also need to make sure that you call glPixelStorei to ensure that the pixel data is returned packed, without any padding (alternatively, you can write each scan line individually, but that requires a little extra effort).

For example:

// Error checking omitted for expository purposes
char *pixels = malloc(width * height * 3);  // Assuming GL_RGB
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(..., pixels);
...
fwrite(pixels, ...);
...
free(pixels);
Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
  • The multiplication with `3` in the call to `malloc` depends on the pixel format. `3` is for 24-bit pixels. Also, instead of using `malloc` why not declare an array like `GLubyte pixels[PIXELSIZE];` (where `PIXELSIZE` is the number of bytes per pixel). – Some programmer dude Feb 01 '12 at 07:10
  • In this case, you have to be careful setting `glPixelStorei(GL_PACK_ALIGNMENT, 1);`, OpenGL default is to consider each row is aligned on a multiple of 4. – rotoglup Feb 01 '12 at 08:22
  • @Joachim: Yes, the multiplication by 3 depends on the pixel format, but we're explicitly asking for 24-bit here with `GL_RGB` and `GL_UNSIGNED_BYTE`. Declaring `GLubyte pixels[PIXELSIZE]` only allocates enough memory for one pixel, not for the whole image—you need to dynamically allocate the array with `malloc` (or one of its relatives) or use a large statically-allocated array and hope that it's big enough. – Adam Rosenfield Feb 02 '12 at 00:00