【问题标题】:How do I take and save a BMP screenshot in SDL 2?如何在 SDL 2 中获取并保存 BMP 屏幕截图?
【发布时间】:2013-12-12 13:31:40
【问题描述】:

仅使用给定的 SDL_Window* 和 SDL_Renderer*,我如何在 SDL 2.0 中创建和保存屏幕截图?

【问题讨论】:

    标签: c++ opengl sdl sdl-2


    【解决方案1】:

    下面是一个将屏幕截图保存到 SDL 2 中的函数,该屏幕截图取自我目前正在编写的库。

    bool saveScreenshotBMP(std::string filepath, SDL_Window* SDLWindow, SDL_Renderer* SDLRenderer) {
        SDL_Surface* saveSurface = NULL;
        SDL_Surface* infoSurface = NULL;
        infoSurface = SDL_GetWindowSurface(SDLWindow);
        if (infoSurface == NULL) {
            std::cerr << "Failed to create info surface from window in saveScreenshotBMP(string), SDL_GetError() - " << SDL_GetError() << "\n";
        } else {
            unsigned char * pixels = new (std::nothrow) unsigned char[infoSurface->w * infoSurface->h * infoSurface->format->BytesPerPixel];
            if (pixels == 0) {
                std::cerr << "Unable to allocate memory for screenshot pixel data buffer!\n";
                return false;
            } else {
                if (SDL_RenderReadPixels(SDLRenderer, &infoSurface->clip_rect, infoSurface->format->format, pixels, infoSurface->w * infoSurface->format->BytesPerPixel) != 0) {
                    std::cerr << "Failed to read pixel data from SDL_Renderer object. SDL_GetError() - " << SDL_GetError() << "\n";
                    delete[] pixels;
                    return false;
                } else {
                    saveSurface = SDL_CreateRGBSurfaceFrom(pixels, infoSurface->w, infoSurface->h, infoSurface->format->BitsPerPixel, infoSurface->w * infoSurface->format->BytesPerPixel, infoSurface->format->Rmask, infoSurface->format->Gmask, infoSurface->format->Bmask, infoSurface->format->Amask);
                    if (saveSurface == NULL) {
                        std::cerr << "Couldn't create SDL_Surface from renderer pixel data. SDL_GetError() - " << SDL_GetError() << "\n";
                        delete[] pixels;
                        return false;
                    }
                    SDL_SaveBMP(saveSurface, filepath.c_str());
                    SDL_FreeSurface(saveSurface);
                    saveSurface = NULL;
                }
                delete[] pixels;
            }
            SDL_FreeSurface(infoSurface);
            infoSurface = NULL;
        }
        return true;
    }
    

    干杯! -尼尔

    【讨论】:

    • pixels = NULL; 应该是delete[] pixels;,否则数组会泄露。
    【解决方案2】:

    如果您使用带有 SDL2 的 OpenGL,您可以直接调用 glReadPixels,而不是使用信息表面和渲染器。这是一个示例(没有错误检查)。

    void Screenshot(int x, int y, int w, int h, const char * filename)
    {
        unsigned char * pixels = new unsigned char[w*h*4]; // 4 bytes for RGBA
        glReadPixels(x,y,w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
    
        SDL_Surface * surf = SDL_CreateRGBSurfaceFrom(pixels, w, h, 8*4, w*4, 0,0,0,0);
        SDL_SaveBMP(surf, filename);
    
        SDL_FreeSurface(surf);
        delete [] pixels;
    }
    

    这里是 SDL wiki page,其中包含设置窗口和 OpenGL 上下文的示例。

    编辑:如果您想复制/粘贴此 sn-p,请记住添加一些错误检查

    【讨论】:

    【解决方案3】:
    void Screenshot(int x, int y, int w, int h, const char * filename)
    {
    Uint32 rmask, gmask, bmask, amask;
    
    rmask = 0x000000ff;
    gmask = 0x0000ff00;
    bmask = 0x00ff0000;
    amask = 0xff000000;
    
    unsigned char * pixels = new unsigned char[w*h*4]; // 4 bytes for RGBA
    glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
    
    SDL_Surface * surf = SDL_CreateRGBSurfaceFrom(pixels, w, h, 8*4, w*4, rmask, gmask, bmask, amask);
    SDL_SaveBMP(surf, filename);
    
    SDL_FreeSurface(surf);
    delete [] pixels;
    }
    

    【讨论】:

    猜你喜欢
    • 2018-09-16
    • 1970-01-01
    • 2015-12-18
    • 1970-01-01
    • 1970-01-01
    • 2010-11-03
    • 2018-02-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多