I have used SDL
to save the window image via SDL_SaveBMP
. The problem is that the saved image is upside down.
The saved image is
<
After a lot of struggles, I have found the solutions and I share it for programmers who will have the same problem in future.
The solution is here.
#include "SDL/SDL.h"
#include
#include
#include
#define SDL_LOCKIFMUST(s) (SDL_MUSTLOCK(s) ? SDL_LockSurface(s) : 0)
#define SDL_UNLOCKIFMUST(s) { if(SDL_MUSTLOCK(s)) SDL_UnlockSurface(s); }
int invert_surface_vertical(SDL_Surface *surface)
{
Uint8 *t;
register Uint8 *a, *b;
Uint8 *last;
register Uint16 pitch;
if( SDL_LOCKIFMUST(surface) < 0 )
return -2;
/* do nothing unless at least two lines */
if(surface->h < 2) {
SDL_UNLOCKIFMUST(surface);
return 0;
}
/* get a place to store a line */
pitch = surface->pitch;
t = (Uint8*)malloc(pitch);
if(t == NULL) {
SDL_UNLOCKIFMUST(surface);
return -2;
}
/* get first line; it's about to be trampled */
memcpy(t,surface->pixels,pitch);
/* now, shuffle the rest so it's almost correct */
a = (Uint8*)surface->pixels;
last = a + pitch * (surface->h - 1);
b = last;
while(a < b) {
memcpy(a,b,pitch);
a += pitch;
memcpy(b,a,pitch);
b -= pitch;
}
/* in this shuffled state, the bottom slice is too far down */
memmove( b, b+pitch, last-b );
/* now we can put back that first row--in the last place */
memcpy(last,t,pitch);
/* everything is in the right place; close up. */
free(t);
SDL_UNLOCKIFMUST(surface);
return 0;
}
void screen_shot(std::string filename)
{
int width = glutGet(GLUT_WINDOW_WIDTH);
int height = glutGet(GLUT_WINDOW_HEIGHT);
SDL_Surface * image = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0);
glReadBuffer(GL_FRONT);
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, image->pixels);
invert_surface_vertical(image);
SDL_SaveBMP(image, filename.c_str());
SDL_FreeSurface(image);
}
void cback_render()
{
if(!glutGetWindow())
return ;
static float rotations = 0;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glLoadIdentity();
glRotatef(rotations, 0, 0, 1);
glBegin(GL_TRIANGLES);
glVertex3f(0,0,0);
glVertex3f(1,0,0);
glVertex3f(0,1,0);
glEnd();
glutSwapBuffers();
}
void timer(int )
{
if(!glutGetWindow())
return ;
static bool saved=false;
if(!saved)
{
screen_shot("image.bmp");
saved=true;
}
glutPostRedisplay();
glutMainLoopEvent();
glutTimerFunc(30, timer, 1);
}
void init()
{
int argc=1;
glutInit(&argc, NULL);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowPosition(100, 100);
glutInitWindowSize(512, 512);
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
glutCreateWindow("freegluttest");
glutDisplayFunc (cback_render);
glutTimerFunc(30, timer, 1);
}
int main()
{
init();
glutMainLoop();
return 0;
}
build:
g++ main.cpp -o main -lGL -lglut -lSDL -lSDL2