【问题标题】:SDL2 C++ Taking a screenshotSDL2 C++ 截图
【发布时间】:2014-04-14 11:45:06
【问题描述】:

您好,我想知道是否可以使用 SDL2 简单地截取屏幕截图。 我尝试了SDL_GetWindowSurface,但我收到一条错误消息:

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

我从here获取代码。

我想到的另一个解决方案是将纹理转换为表面,但我没能做到...

你有什么解决办法吗?

【问题讨论】:

    标签: c++ screenshot sdl-2


    【解决方案1】:

    您似乎在混合渲染系统。该方法仅适用于软件渲染的上下文。对于硬件渲染,您应该使用方法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() 谢谢
    • 很好的答案!提问者提到的linked question使用SDL_RenderReadPixels读取数据。对SDL_GetWindowSurface 的调用似乎只是为了建立要输入SDL_CreateRGBSurface 的参数。您已经对这些值进行了硬编码,但可以依赖这些值吗?您将如何使用新 API 查询这些值?谢谢!
    • 玩过这个并查看了文档,我想我现在可以回答我自己的问题:位深度和通道掩码是硬编码的,但是它们是根据请求的格式设置的在SDL_RenderReadPixels 中,渲染器的像素最初采用什么格式并不重要。
    • surface = SDL_GetWindowSurface(window)format = SDL_GetWindowPixelFormat(window) 实际上可以为您填写这些内容,前提是您不介意使用 SDL_Window 已经使用的任何设置。
    • @TalesM:您使用的方法不是独立于 sw/hw 渲染并且在这两种情况下都应该有效吗?为什么以及何时在链接答案中使用该方法?请您详细说明一下好吗?谢谢。
    【解决方案2】:

    在 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 字节序 #定义字节序

    ...把东西放在这里...

    #endif

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

    不要犹豫,检查函数原型的返回类型和参数,这里的 cmets 只是提供信息,而不是更多。

    【讨论】:

    • 您的答案可以通过提供更多上下文来改进。你对字节序是正确的,但即使你说这个或那个是char *,你也不会显示它是什么。当试图解释某事是如何工作的时,这并没有那么有用。此外,如果您使用包含防护,您应该能够避免将 t 软管放在头文件中。哦,你没有包括变量的类型,这本身就很关键。
    • 查看每个函数的返回值,您可以知道变量类型是什么。攻击 SDL2 库时需要了解函数机制。我是法语,“NomFichier is char*”不是很需要,因为每个“man SDL_SaveBMP”都会给你函数的原型,法语中的“NomFichier”给你“FileName”所以这是你文件的路径想要保存到... 所有这些功能都记录在 SDL2 中。是的,我同意你必须在 RGBA 定义之前放置一个“守卫”......并在 ^^ 之后关闭它
    猜你喜欢
    • 1970-01-01
    • 2018-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多