SDL_SaveBMP将图像上下颠倒

我已经使用SDL通过SDL_SaveBMP保存窗口图像。 问题是保存的图像是颠倒的。

保存的图像是

AAAA

虽然必须如此

BBBB

我该如何修复代码?

screen_shotfunction:

 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); SDL_SaveBMP(image, filename.c_str()); SDL_FreeSurface(image); } 


更新

我尝试翻转像素。 结果是纯黑色输出图像。 问题是什么?

 #include "SDL/SDL.h" #include "SDL/SDL_image.h" #include  #include  #include  #include  #include  // for sleep #include  Uint32 GetPixel24(SDL_Surface * surface,int x, int y) { Uint32 rgb; Uint8 * pixel = (Uint8*)surface->pixels; pixel += (y * surface->pitch) + (x * sizeof(Uint8) * 3); #if SDL_BYTEORDER == SDL_BIG_ENDIAN rgb=(pixel[2] << 8)+(pixel[1] << 16)+(pixel[0] << 24); #else rgb=(pixel[2] << 16)+(pixel[1] << 8)+(pixel[0]); std::cout<<int(pixel[0])<<","<<int(pixel[1])<<","<<int(pixel[2])<pixels; pixel += (y * surface->pitch) + (x * sizeof(Uint8) * 3); #if SDL_BYTEORDER == SDL_BIG_ENDIAN pixel[0] = (color >> 24) & 0xFF; pixel[1] = (color >> 16) & 0xFF; pixel[2] = (color >> 8) & 0xFF; #else pixel[0] = color & 0xFF; pixel[1] = (color >> 8) & 0xFF; pixel[2] = (color >> 16) & 0xFF; #endif } void PutPixel24(SDL_Surface * surface, int x, int y, Uint32 rgb) { if(SDL_MUSTLOCK(surface)) SDL_LockSurface(surface); PutPixel24_nolock(surface,x,y,rgb); if(SDL_MUSTLOCK(surface)) SDL_LockSurface(surface); } SDL_Surface *flip_vertical_surface(SDL_Surface *surface) { SDL_Surface *flipped = nullptr; flipped = SDL_CreateRGBSurface( SDL_SWSURFACE, surface->w, surface->h, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0); for(int x=0;xw;x++) for(int y=0;yh;y++) { int ry=(surface->h)-1-y; Uint32 pixel=GetPixel24(surface,x,y); PutPixel24(flipped,x,ry,pixel); } return flipped; } 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); SDL_Surface *image_fliped=flip_vertical_surface(image); if(image_fliped==nullptr) std::cout<<"image_fliped must be different than nullptr"<pixels); SDL_SaveBMP(image_fliped, filename.c_str()); SDL_FreeSurface(image); SDL_FreeSurface(image_fliped); } void cback_render() { if(!glutGetWindow()) return ; static float rotations = 0; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 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, nullptr); 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; } 

经过大量的努力,我找到了解决方案,并将其分享给将来会遇到同样问题的程序员。

解决方案就在这里 。

 #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; } 

建立:

 g++ main.cpp -o main -lGL -lglut -lSDL -lSDL2