gpt4 book ai didi

c++ - SDL_SaveBMP 倒置保存图片

转载 作者:太空宇宙 更新时间:2023-11-04 06:58:24 25 4
gpt4 key购买 nike

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

保存的图片是

aaaa

必须如此

bbbb

我应该如何修复代码?

screen_shot 函数:

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 <stdio.h>
#include <assert.h>
#include <iostream>
#include <GL/freeglut.h>
#include <boost/thread/thread.hpp> // for sleep
#include <SDL2/SDL.h>


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])<<std::endl;

#endif

return rgb;
}

void PutPixel24_nolock(SDL_Surface * surface, int x, int y, Uint32 color)
{
Uint8 * pixel = (Uint8*)surface->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;x<surface->w;x++)
for(int y=0;y<surface->h;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"<<std::endl;

glReadBuffer(GL_FRONT);
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, image->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;
}

最佳答案

经过一番折腾,我找到了解决办法,分享给以后遇到同样问题的程序员。

解决方案是here .

#include "SDL/SDL.h"
#include <iostream>
#include <GL/freeglut.h>
#include <SDL2/SDL.h>

#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

关于c++ - SDL_SaveBMP 倒置保存图片,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41443911/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com