2013-11-27 12 views

risposta

11

Di seguito è una funzione per il salvataggio di uno screenshot in SDL 2 preso da una libreria che sto attualmente scrivendo.

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"; 
       pixels = NULL; 
       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"; 
        return false; 
       } 
       SDL_SaveBMP(saveSurface, filepath.c_str()); 
       SDL_FreeSurface(saveSurface); 
       saveSurface = NULL; 
      } 
      delete[] pixels; 
     } 
     SDL_FreeSurface(infoSurface); 
     infoSurface = NULL; 
    } 
    return true; 
} 

Cheers! -Neil

+2

'pixels = NULL;' deve essere 'delete [] pixels;', altrimenti la matrice viene persa. – emlai

6

Se si utilizza OpenGL con SDL2, è possibile chiamare glReadPixels direttamente anziché utilizzare la superficie informativa e il renderer. Ecco un esempio (senza controllo degli errori).

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

Ecco il SDL wiki page con un esempio di impostazione della finestra e un contesto OpenGL.