PDA

View Full Version : Screenshot of opengl window



EthanHunt
05-02-2011, 11:52 AM
Need to take simple screenshot of the opengl window and save it to file.
Please, post example code in c++.

McLeary
05-02-2011, 11:54 AM
just use glReadPixels to retrieve raw data.
http://www.opengl.org/sdk/docs/man/xhtml/glReadPixels.xml

EthanHunt
05-02-2011, 12:23 PM
Ok, i get the data. Now how to save it to file? I'm sorry, i'm absolutely zero in c++.

McLeary
05-02-2011, 12:34 PM
I use this method to write a PPM file, maybe it can help you



void Image::writePPM( std::ostream& out ) {
// Escreve o cabeçalho do arquivo
out << "P6" << endl;
out << width << ' ' << height << endl;
out << "255" << endl;

// Escreve os valores ajustados para o intervalo [0,255]
// O valor do canal aplha é ignorado
for ( unsigned int idx = 0; idx < this->getNumberOfPixels(); idx++ ) {

unsigned int iRed = (unsigned int) ( 256 * raster[idx].r );
unsigned int iGreen = (unsigned int) ( 256 * raster[idx].g );
unsigned int iBlue = (unsigned int) ( 256 * raster[idx].b );

if ( iRed > 255 )
iRed = 255;
if ( iGreen > 255 )
iGreen = 255;
if ( iBlue > 255 )
iBlue = 255;

unsigned char red = (unsigned char) iRed;
unsigned char green = (unsigned char) iGreen;
unsigned char blue = (unsigned char) iBlue;

out.put( red );
out.put( green );
out.put( blue );
}
}


Comments are in portuguese, but you can take the idea

EthanHunt
05-02-2011, 01:21 PM
I succeeded make a screenshot with SDL library:


SDL_Surface * image = SDL_CreateRGBSurface(SDL_SWSURFACE, current_w, current_h, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0);

glReadBuffer(GL_FRONT);
glReadPixels(0, 0, current_w, current_h, GL_RGB, GL_UNSIGNED_BYTE, image->pixels);

SDL_SaveBMP(image, "pic.bmp");
SDL_FreeSurface(image);

But it was all black))) My size but all black. Why and how to fix it?

UPD: I found - need to remove glReadBuffer(GL_FRONT). But now screenshot is upside down... How to fix IT?)

McLeary
05-02-2011, 01:51 PM
The system's origin of an OpenGL window is in the bottom left corner, while a bitmap has its origin in the upper left corner.

All you need to do is to invert the y coords of your pixels.
How this can be done with SDL? I have no idea.

EthanHunt
05-02-2011, 01:59 PM
I found:


int index;
void* temp_row;
int height_div_2;

temp_row = (void *)malloc(image->pitch);
if(NULL == temp_row)
{
SDL_SetError("Not enough memory for image inversion");
}
height_div_2 = (int) (image->h * .5);
for(index = 0; index < height_div_2; index++)
{
memcpy((Uint8 *)temp_row,(Uint8 *)(image->pixels) + image->pitch * index, image->pitch);
memcpy((Uint8 *)(image->pixels) + image->pitch * index, (Uint8 *)(image->pixels) + image->pitch * (image->h - index-1), image->pitch);
memcpy((Uint8 *)(image->pixels) + image->pitch * (image->h - index-1), temp_row, image->pitch);
}
free(temp_row);

Now all works fine. Thanks for help, McLeary.

McLeary
05-02-2011, 02:53 PM
No problem