From 6d787e221c92531a7e1952fc6b2bc18cc8b82be2 Mon Sep 17 00:00:00 2001 From: Misa Date: Tue, 31 Oct 2023 22:52:42 -0700 Subject: [PATCH] Fix screenshots in Flip Mode One problem with internal screenshot capture is that we rely on SDL's render subsystem to flip the screen in Flip Mode, while leaving our actual screen untouched. Since we source the screenshot from the screen and not what SDL renders, we need to flip the screenshot ourselves when saving an internal capture. To do this, we need to support 24-bit colors in DrawPixel() and ReadPixel(). Luckily, this isn't too hard to do. A 24-bit color is just a tuple of three bytes, and we just need to do a small amount of bitwise math to pack/unpack them to a single integer for SDL_GetRGB() and SDL_MapRGB(). --- desktop_version/src/GraphicsUtil.cpp | 48 +++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/desktop_version/src/GraphicsUtil.cpp b/desktop_version/src/GraphicsUtil.cpp index 255e3f5e..b1368af6 100644 --- a/desktop_version/src/GraphicsUtil.cpp +++ b/desktop_version/src/GraphicsUtil.cpp @@ -97,18 +97,27 @@ void DrawPixel(SDL_Surface* surface, const int x, const int y, const SDL_Color c const SDL_PixelFormat* fmt = surface->format; const int bpp = fmt->BytesPerPixel; - Uint32* pixel = (Uint32*) ((Uint8*) surface->pixels + y * surface->pitch + x * bpp); + Uint8* pixel = (Uint8*) surface->pixels + y * surface->pitch + x * bpp; + Uint32* pixel32 = (Uint32*) pixel; switch (bpp) { case 1: case 2: + SDL_assert(0 && "Colors other than 24- or 32- bit unsupported!"); + break; + case 3: - SDL_assert(0 && "Non-32-bit colors not supported!"); - return; + { + const Uint32 single = SDL_MapRGB(fmt, color.r, color.g, color.b); + pixel[0] = (single & 0xFF0000) >> 16; + pixel[1] = (single & 0x00FF00) >> 8; + pixel[2] = (single & 0x0000FF) >> 0; + break; + } case 4: - *pixel = SDL_MapRGBA(fmt, color.r, color.g, color.b, color.a); + *pixel32 = SDL_MapRGBA(fmt, color.r, color.g, color.b, color.a); } } @@ -131,18 +140,26 @@ SDL_Color ReadPixel(const SDL_Surface* surface, const int x, const int y) const SDL_PixelFormat* fmt = surface->format; const int bpp = surface->format->BytesPerPixel; - const Uint32* pixel = (Uint32*) ((Uint8*) surface->pixels + y * surface->pitch + x * bpp); + const Uint8* pixel = (Uint8*) surface->pixels + y * surface->pitch + x * bpp; + const Uint32* pixel32 = (Uint32*) pixel; switch (bpp) { case 1: case 2: - case 3: - SDL_assert(0 && "Non-32-bit colors not supported!"); + SDL_assert(0 && "Colors other than 24- or 32- bit unsupported!"); break; + case 3: + { + const Uint32 single = (pixel[0] << 16) | (pixel[1] << 8) | (pixel[2] << 0); + SDL_GetRGB(single, fmt, &color.r, &color.g, &color.b); + color.a = 255; + break; + } + case 4: - SDL_GetRGBA(*pixel, fmt, &color.r, &color.g, &color.b, &color.a); + SDL_GetRGBA(*pixel32, fmt, &color.r, &color.g, &color.b, &color.a); } return color; @@ -312,5 +329,20 @@ bool TakeScreenshot(SDL_Surface** surface) return false; } + /* Need to manually vertically reverse pixels in Flip Mode. */ + if (graphics.flipmode) + { + for (int x = 0; x < (*surface)->w; x++) + { + for (int y = 0; y < (*surface)->h / 2; y++) + { + const SDL_Color upper = ReadPixel(*surface, x, y); + const SDL_Color lower = ReadPixel(*surface, x, (*surface)->h - 1 - y); + DrawPixel(*surface, x, y, lower); + DrawPixel(*surface, x, (*surface)->h - 1 - y, upper); + } + } + } + return true; }