我正在尝试将纹理保存到png中,这是我唯一能得到的 是屏幕一部分的屏幕截图。
我的代码示例:
src_texture = SDL_CreateTextureFromSurface( renderer, some_surface );
/*.........*/
/*create target texture */
SDL_Texture *tmp_texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_TARGET , w, h);
SDL_SetTextureBlendMode(tmp_texture, SDL_BLENDMODE_NONE);
SDL_SetRenderTarget(renderer, tmp_texture);
SDL_RenderCopy(renderer, src_texture, NULL, NULL);
/*create surface and get pixels from texture*/
PixelFormat mask = GetMask(format);
s = SDL_CreateRGBSurface(0, w, h, 32, mask.Rmask, mask.Gmask, mask.Bmask, mask.Amask);
if (s) {
SDL_SetRenderTarget(renderer, tmp_texture);
SDL_RenderReadPixels(renderer, NULL, s->format->format, s->pixels, s->pitch);
IMG_SavePNG(s, "image.png");
}
SDL_DestroyTexture(tmp_texture);
知道如何实现这个目标吗?
答案 0 :(得分:3)
这是我的解决方法:
void save_texture(const char* file_name, SDL_Renderer* renderer, SDL_Texture* texture) {
SDL_Texture* target = SDL_GetRenderTarget(renderer);
SDL_SetRenderTarget(renderer, texture);
int width, height;
SDL_QueryTexture(texture, NULL, NULL, &width, &height);
SDL_Surface* surface = SDL_CreateRGBSurface(0, width, height, 32, 0, 0, 0, 0);
SDL_RenderReadPixels(renderer, NULL, surface->format->format, surface->pixels, surface->pitch);
IMG_SavePNG(surface, file_name);
SDL_FreeSurface(surface);
SDL_SetRenderTarget(renderer, target);
}
此功能在文件写入之外没有任何副作用。这使插入变得容易,因为您不必担心渲染目标会被破坏。随意添加您认为合适的错误处理。
答案 1 :(得分:2)
我一直在寻找相同的东西,当我找不到一个执行此操作的片段时,我感到很失望"简单"任务。
所以,我继续为下一个想要它的人做了一个。我不会在生产代码中使用它,它只是用于调试。在SDL 2.0.7中测试。
将所有SDL_Texture
保存到.bmp
文件。
从技术上讲,它会将SDL_Texture
转换为SDL_Surface
,并将其保存为.bmp
。
特别适合:
非常简单,只需将SDL_Renderer
与您要保存的SDL_Texture
一起传递,并filename
保存到。
此外,这将破坏任何文件,所以要小心。
代码将所有内容强制为RGBA32格式,尽管它很简单,可以调整为您想要的任何格式。如果您愿意,可以通过将其作为参数传递给format
来加载SDL_QueryTexture
,以自动检测输入纹理的格式并将其用于输出文件。
如果您想要增强此代码,请考虑以下几点。
png
,jpg
或其他压缩格式的垫脚石。/* Usage example */
save_texture(sdlttyDisplay->ren, sdlttyDisplay->font_tex, "image.bmp");
void save_texture(SDL_Renderer *ren, SDL_Texture *tex, const char *filename)
{
SDL_Texture *ren_tex;
SDL_Surface *surf;
int st;
int w;
int h;
int format;
void *pixels;
pixels = NULL;
surf = NULL;
ren_tex = NULL;
format = SDL_PIXELFORMAT_RGBA32;
/* Get information about texture we want to save */
st = SDL_QueryTexture(tex, NULL, NULL, &w, &h);
if (st != 0) {
SDL_Log("Failed querying texture: %s\n", SDL_GetError());
goto cleanup;
}
ren_tex = SDL_CreateTexture(ren, format, SDL_TEXTUREACCESS_TARGET, w, h);
if (!ren_tex) {
SDL_Log("Failed creating render texture: %s\n", SDL_GetError());
goto cleanup;
}
/*
* Initialize our canvas, then copy texture to a target whose pixel data we
* can access
*/
st = SDL_SetRenderTarget(ren, ren_tex);
if (st != 0) {
SDL_Log("Failed setting render target: %s\n", SDL_GetError());
goto cleanup;
}
SDL_SetRenderDrawColor(ren, 0x00, 0x00, 0x00, 0x00);
SDL_RenderClear(ren);
st = SDL_RenderCopy(ren, tex, NULL, NULL);
if (st != 0) {
SDL_Log("Failed copying texture data: %s\n", SDL_GetError());
goto cleanup;
}
/* Create buffer to hold texture data and load it */
pixels = malloc(w * h * SDL_BYTESPERPIXEL(format));
if (!pixels) {
SDL_Log("Failed allocating memory\n");
goto cleanup;
}
st = SDL_RenderReadPixels(ren, NULL, format, pixels, w * SDL_BYTESPERPIXEL(format));
if (st != 0) {
SDL_Log("Failed reading pixel data: %s\n", SDL_GetError());
goto cleanup;
}
/* Copy pixel data over to surface */
surf = SDL_CreateRGBSurfaceWithFormatFrom(pixels, w, h, SDL_BITSPERPIXEL(format), w * SDL_BYTESPERPIXEL(format), format);
if (!surf) {
SDL_Log("Failed creating new surface: %s\n", SDL_GetError());
goto cleanup;
}
/* Save result to an image */
st = SDL_SaveBMP(surf, filename);
if (st != 0) {
SDL_Log("Failed saving image: %s\n", SDL_GetError());
goto cleanup;
}
SDL_Log("Saved texture as BMP to \"%s\"\n", filename);
cleanup:
SDL_FreeSurface(surf);
free(pixels);
SDL_DestroyTexture(ren_tex);
}
答案 2 :(得分:0)
为了将部分屏幕保存到文件中,最好创建RGBSurface:
SDL_Surface *ss = SDL_CreateRGBSurface(0, w, h, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
Here is SDL_CreateRGBSurface documentation
下一步与您的代码相同 - 使用正确颜色格式的SDL_RenderReadPixels
。
获得此功能后,您只需使用SDL_SaveBMP
或其他功能进行保存即可。
答案 3 :(得分:0)
你设法解决了这个问题吗?使用您的代码,我的程序在SDL_RenderReadPixels()调用时崩溃。
如果将纹理更改为SDL_TEXTUREACCESS_STREAMING,则可以使用上述方法正确捕获它,但请注意仅在实际渲染器的分辨率中。如果纹理较大,它将被切断。