From 05e7dcf8f80724c46d44e736c9b7d3714529c761 Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Fri, 17 Nov 2023 14:10:32 +0000 Subject: [PATCH] Support returning <8bpp surfaces in SDL_LoadBMP_RW --- src/video/SDL_bmp.c | 105 +++++++++++----------------------------- test/testcustomcursor.c | 7 ++- test/testutils.c | 7 ++- 3 files changed, 40 insertions(+), 79 deletions(-) diff --git a/src/video/SDL_bmp.c b/src/video/SDL_bmp.c index c9fdcdbaf..c5fe6c7de 100644 --- a/src/video/SDL_bmp.c +++ b/src/video/SDL_bmp.c @@ -197,7 +197,6 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc) { SDL_bool was_error = SDL_TRUE; Sint64 fp_offset = 0; - int bmpPitch; int i, pad; SDL_Surface *surface; Uint32 Rmask = 0; @@ -208,7 +207,6 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc) Uint8 *bits; Uint8 *top, *end; SDL_bool topDown; - int ExpandBMP; SDL_bool haveRGBMasks = SDL_FALSE; SDL_bool haveAlphaMask = SDL_FALSE; SDL_bool correctAlpha = SDL_FALSE; @@ -365,14 +363,8 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc) goto done; } - /* Expand 1, 2 and 4 bit bitmaps to 8 bits per pixel */ + /* Reject invalid bit depths */ switch (biBitCount) { - case 1: - case 2: - case 4: - ExpandBMP = biBitCount; - biBitCount = 8; - break; case 0: case 3: case 5: @@ -381,7 +373,6 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc) SDL_SetError("%d-bpp BMP images are not supported", biBitCount); goto done; default: - ExpandBMP = 0; break; } @@ -514,89 +505,49 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc) } top = (Uint8 *)surface->pixels; end = (Uint8 *)surface->pixels + (surface->h * surface->pitch); - switch (ExpandBMP) { - case 1: - bmpPitch = (biWidth + 7) >> 3; - pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0); - break; - case 2: - bmpPitch = (biWidth + 3) >> 2; - pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0); - break; - case 4: - bmpPitch = (biWidth + 1) >> 1; - pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0); - break; - default: - pad = ((surface->pitch % 4) ? (4 - (surface->pitch % 4)) : 0); - break; - } + pad = ((surface->pitch % 4) ? (4 - (surface->pitch % 4)) : 0); if (topDown) { bits = top; } else { bits = end - surface->pitch; } while (bits >= top && bits < end) { - switch (ExpandBMP) { - case 1: - case 2: - case 4: - { - Uint8 pixel = 0; - int shift = (8 - ExpandBMP); + if (SDL_RWread(src, bits, surface->pitch) != (size_t)surface->pitch) { + goto done; + } + if (biBitCount == 8 && palette && biClrUsed < (1u << biBitCount)) { for (i = 0; i < surface->w; ++i) { - if (i % (8 / ExpandBMP) == 0) { - if (!SDL_ReadU8(src, &pixel)) { - goto done; - } - } - bits[i] = (pixel >> shift); if (bits[i] >= biClrUsed) { SDL_SetError("A BMP image contains a pixel with a color out of the palette"); goto done; } - pixel <<= ExpandBMP; - } - } break; - - default: - if (SDL_RWread(src, bits, surface->pitch) != (size_t)surface->pitch) { - goto done; - } - if (biBitCount == 8 && palette && biClrUsed < (1u << biBitCount)) { - for (i = 0; i < surface->w; ++i) { - if (bits[i] >= biClrUsed) { - SDL_SetError("A BMP image contains a pixel with a color out of the palette"); - goto done; - } - } } + } #if SDL_BYTEORDER == SDL_BIG_ENDIAN - /* Byte-swap the pixels if needed. Note that the 24bpp - case has already been taken care of above. */ - switch (biBitCount) { - case 15: - case 16: - { - Uint16 *pix = (Uint16 *)bits; - for (i = 0; i < surface->w; i++) { - pix[i] = SDL_Swap16(pix[i]); - } - break; + /* Byte-swap the pixels if needed. Note that the 24bpp + case has already been taken care of above. */ + switch (biBitCount) { + case 15: + case 16: + { + Uint16 *pix = (Uint16 *)bits; + for (i = 0; i < surface->w; i++) { + pix[i] = SDL_Swap16(pix[i]); } - - case 32: - { - Uint32 *pix = (Uint32 *)bits; - for (i = 0; i < surface->w; i++) { - pix[i] = SDL_Swap32(pix[i]); - } - break; - } - } -#endif break; } + + case 32: + { + Uint32 *pix = (Uint32 *)bits; + for (i = 0; i < surface->w; i++) { + pix[i] = SDL_Swap32(pix[i]); + } + break; + } + } +#endif + /* Skip padding bytes, ugh */ if (pad) { Uint8 padbyte; diff --git a/test/testcustomcursor.c b/test/testcustomcursor.c index ee90c782d..afd74b121 100644 --- a/test/testcustomcursor.c +++ b/test/testcustomcursor.c @@ -72,7 +72,12 @@ init_color_cursor(const char *file) SDL_Surface *surface = SDL_LoadBMP(file); if (surface) { if (surface->format->palette) { - SDL_SetSurfaceColorKey(surface, 1, *(Uint8 *)surface->pixels); + const Uint8 bpp = surface->format->BitsPerPixel; + const Uint8 mask = (1 << bpp) - 1; + if (SDL_PIXELORDER(surface->format->format) == SDL_BITMAPORDER_4321) + SDL_SetSurfaceColorKey(surface, 1, (*(Uint8 *)surface->pixels) & mask); + else + SDL_SetSurfaceColorKey(surface, 1, ((*(Uint8 *)surface->pixels) >> (8 - bpp)) & mask); } else { switch (surface->format->BitsPerPixel) { case 15: diff --git a/test/testutils.c b/test/testutils.c index f6eb3780e..e9d505297 100644 --- a/test/testutils.c +++ b/test/testutils.c @@ -116,7 +116,12 @@ LoadTexture(SDL_Renderer *renderer, const char *file, SDL_bool transparent, /* Set transparent pixel as the pixel at (0,0) */ if (transparent) { if (temp->format->palette) { - SDL_SetSurfaceColorKey(temp, SDL_TRUE, *(Uint8 *)temp->pixels); + const Uint8 bpp = temp->format->BitsPerPixel; + const Uint8 mask = (1 << bpp) - 1; + if (SDL_PIXELORDER(temp->format->format) == SDL_BITMAPORDER_4321) + SDL_SetSurfaceColorKey(temp, SDL_TRUE, (*(Uint8 *)temp->pixels) & mask); + else + SDL_SetSurfaceColorKey(temp, SDL_TRUE, ((*(Uint8 *)temp->pixels) >> (8 - bpp)) & mask); } else { switch (temp->format->BitsPerPixel) { case 15: