SDL2 C++ 截图功能

20

你好,我想知道是否可以使用SDL2轻松地进行截屏。 我尝试了SDL_GetWindowSurface,但出现错误:

没有可用的硬件加速渲染器。

我从这里获取了代码。

另一个解决方案是将纹理转换为表面,但我没有成功...

您有什么解决方案吗?

2个回答

28

看起来你混淆了渲染系统。那种方法只在软件渲染的情况下有效。对于硬件渲染,你应该使用 SDL_RenderReadPixels() 方法。要保存截图,你需要像下面这样写代码:

SDL_Surface *sshot = SDL_CreateRGBSurface(0, w, h, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
SDL_RenderReadPixels(renderer, NULL, SDL_PIXELFORMAT_ARGB8888, sshot->pixels, sshot->pitch);
SDL_SaveBMP(sshot, "screenshot.bmp");
SDL_FreeSurface(sshot);

其中wh分别表示屏幕的宽度和高度(你可以使用SDL_GetRendererOutputSize()函数获得这些值)。


成功了!!! 顺便说一下,如果你想保存修改过的纹理,只需使用以下代码: SDL_SetRenderTarget() 谢谢。 - user3371807
好的回答!提问者引用的相关问题使用了SDL_RenderReadPixels来读取数据。调用SDL_GetWindowSurface似乎只是为了建立要传递给SDL_CreateRGBSurface的参数。您已经硬编码了这些值,但这可靠吗?如何使用新API查询这些值?谢谢! - Leo
经过测试并查看了文档,我想我现在可以回答自己的问题了:位深度和通道掩码是硬编码的,但由于它们是根据“SDL_RenderReadPixels”中请求的格式设置的,因此渲染器像素最初处于什么格式并不重要。 - Leo
1
surface = SDL_GetWindowSurface(window)format = SDL_GetWindowPixelFormat(window) 可以为您填充这些内容,只要您不介意使用您的 SDL_Window 已经使用的任何设置。 - RectangleEquals
@TalesM:你使用的方法不是独立于软硬件渲染的吗?为什么要在两种情况下使用该方法?能否详细说明一下?谢谢。 - mkiever
显示剩余2条评论

3
在 C 的 SDL2 版本 2.0.3 中,它可以与以下内容一起使用:
fenetre=SDL_GetWindowFromId(touche.windowID); // "touche" is a   SDL_KeyboardEvent, "fenetre" is a SDL_window pointer

r_copie=SDL_GetRenderer(fenetre);

s_SnapSource=SDL_CreateRGBSurface(0,SCREEN_WIDTH,SCREEN_HEIGHT,32,
rmask,
gmask,
bmask,
amask); // s_SnapSource is a SDL_Surface pointer

SDL_LockSurface(s_SnapSource);
SDL_RenderReadPixels(r_copie,NULL,s_SnapSource->format->format,
s_SnapSource->pixels,S_SnapSource->pitch);

SDL_SaveBMP(s_SnapSource,NomFichier); // NomFichier is a char*
SDL_UnlockSurface(s_SnapSource);
SDL_FreeSurface(s_SnapSource);

/!\ 注意 /!\

#if SDL_BYTEORDER == SDL_BIG_ENDIAN
    Uint32 rmask = 0xff000000;
    Uint32 gmask = 0x00ff0000;
    Uint32 bmask = 0x0000ff00;
    Uint32 amask = 0x000000ff;  
#else
    Uint32 rmask = 0x000000ff;
    Uint32 gmask = 0x0000ff00;
    Uint32 bmask = 0x00ff0000;
    Uint32 amask = 0xff000000;
#endif

在使用这些变量之前,必须先在某处设置它们。

如果你想将其放在头文件中,请确保添加一些“守卫”:

#ifndef ENDIANNESS #define ENDIANNESS

...将内容放在这里...

#endif

否则,如评论中所述,编译时可能会出现多个定义错误 :{ 是我的错 :{

请务必查看函数原型的返回类型和参数,此处的注释仅提供信息,不做更多解释。


你的回答可以通过提供更多上下文来改进。你关于字节序的说法是正确的,但即使你说这个或那个是一个char *,你也没有展示它是什么。当试图解释某些东西的工作原理时,这并不是很有帮助。此外,如果你使用包含保护,你应该能够将它们放在头文件中。哦,你还没有包括变量的类型,这本身就是相当关键的。 - Pryftan
通过查看每个函数返回的内容,您可以了解变量类型。在攻击SDL2库时,需要了解函数机制。我说法语,“NomFichier is char*”并不是非常必要的,因为每个“man SDL_SaveBMP”都会给出函数的原型,“NomFichier”在法语中意味着“FileName”,因此这是要保存到的文件的路径...所有这些函数都在SDL2中有文档记录。是的,我同意在RGBA定义之前放置一个“guard”,并在之后关闭它^^ - Hurukan Imperial Stepper
我从未回复,因为我甚至不确定原因。有太多事情要处理,我并不是指Covid(尽管那当然很疯狂)。无论如何,关于你对此感到难过 - 不要。有时候我们会忽略做某件事或错过某个东西,就像你所说的,你是法国人,所以自然解释可能更难。这是建设性的批评,我希望你知道。如果你不知道,希望你能看到这条消息。 - Pryftan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接