简体   繁体   English

如何在 SDL 2 中拍摄和保存 BMP 屏幕截图?

[英]How do I take and save a BMP screenshot in SDL 2?

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

Below is a function for saving a screenshot in SDL 2 taken from a library I'm currently writing.下面是一个函数,用于在 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;
}

Cheers!干杯! -Neil -尼尔

If you are using OpenGL with SDL2 you can call glReadPixels directly instead of using the info surface and renderer.如果您将 OpenGL 与 SDL2 一起使用,您可以直接调用glReadPixels而不是使用信息表面和渲染器。 Here is an example (without error checking).这是一个示例(没有错误检查)。

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;
}

Here's the SDL wiki page with an example of setting up the window and an OpenGL context.这是SDL wiki 页面,其中包含设置窗口和 OpenGL 上下文的示例。

Edit: If you are tempted to copy/paste this snippet, remember to add some error checking编辑:如果您想复制/粘贴此代码段,请记住添加一些错误检查

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM