Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions include/SDL3/SDL_surface.h
Original file line number Diff line number Diff line change
Expand Up @@ -594,10 +594,10 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadBMP(const char *file);
/**
* Save a surface to a seekable SDL data stream in BMP format.
*
* Surfaces with a 24-bit, 32-bit and paletted 8-bit format get saved in the
* Surfaces with a 24-bit, 32-bit and paletted format get saved in the
* BMP directly. Other RGB formats with 8-bit or higher get converted to a
* 24-bit surface or, if they have an alpha mask or a colorkey, to a 32-bit
* surface before they are saved. YUV and paletted 1-bit and 4-bit formats are
* surface before they are saved. YUV and LSB paletted 1-bit and 4-bit formats are
* not supported.
*
* \param surface the SDL_Surface structure containing the image to be saved.
Expand All @@ -620,10 +620,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SaveBMP_IO(SDL_Surface *surface, SDL_IOStre
/**
* Save a surface to a file in BMP format.
*
* Surfaces with a 24-bit, 32-bit and paletted 8-bit format get saved in the
* Surfaces with a 24-bit, 32-bit, paletted formats get saved in the
* BMP directly. Other RGB formats with 8-bit or higher get converted to a
* 24-bit surface or, if they have an alpha mask or a colorkey, to a 32-bit
* surface before they are saved. YUV and paletted 1-bit and 4-bit formats are
* surface before they are saved. YUV and LSB paletted 1-bit and 4-bit formats are
* not supported.
*
* \param surface the SDL_Surface structure containing the image to be saved.
Expand Down
8 changes: 7 additions & 1 deletion src/video/SDL_bmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -638,11 +638,17 @@ static bool InitBMPSaveState(BMPSaveState *state, SDL_Surface *surface)
if (surface->palette && !state->save32bit) {
if (SDL_BITSPERPIXEL(surface->format) == 8) {
state->intermediate_surface = surface;
} else if (surface->format == SDL_PIXELFORMAT_INDEX1MSB || surface->format == SDL_PIXELFORMAT_INDEX4MSB) {
state->intermediate_surface = surface;
} else {
SDL_SetError("%u bpp BMP files not supported",
SDL_BITSPERPIXEL(surface->format));
goto error;
}
} else if (surface->format == SDL_PIXELFORMAT_INDEX1MSB || surface->format == SDL_PIXELFORMAT_INDEX4MSB) {
SDL_SetError("%u bpp BMP files require a palette",
SDL_BITSPERPIXEL(surface->format));
goto error;
} else if ((surface->format == SDL_PIXELFORMAT_BGR24 && !state->save32bit) ||
(surface->format == SDL_PIXELFORMAT_BGRA32 && state->save32bit)) {
state->intermediate_surface = surface;
Expand Down Expand Up @@ -726,7 +732,7 @@ static bool SDL_SaveBMP_IO_Internal(BMPSaveState *state, SDL_IOStream *dst, bool
Uint32 bV5Reserved = 0;

if (SDL_LockSurface(state->intermediate_surface)) {
const size_t bw = state->intermediate_surface->w * state->intermediate_surface->fmt->bytes_per_pixel;
const size_t bw = (state->intermediate_surface->w * SDL_BITSPERPIXEL(state->intermediate_surface->format) + 7) / 8;

// Set the BMP file header values
bfSize = 0; // We'll write this when we're done
Expand Down
53 changes: 51 additions & 2 deletions src/video/SDL_surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -2781,9 +2781,11 @@ Uint32 SDL_MapSurfaceRGBA(SDL_Surface *surface, Uint8 r, Uint8 g, Uint8 b, Uint8
bool SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
{
Uint32 pixel = 0;
Uint32 mask = 0xffffffff;
Uint32 shift = 0;
size_t bytes_per_pixel;
Uint8 unused;
Uint8 *p;
const Uint8 *p;
bool result = false;

if (r) {
Expand Down Expand Up @@ -2830,7 +2832,53 @@ bool SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g
}
}

p = (Uint8 *)surface->pixels + y * surface->pitch + x * bytes_per_pixel;
if (bytes_per_pixel == 0) {
switch (surface->format) {
case SDL_PIXELFORMAT_INDEX4MSB:
p = (Uint8 *)surface->pixels + y * surface->pitch + x / 2;
shift = 4 * (1 - (x & 0x1));
mask = 0xf << shift;
bytes_per_pixel = 1;
break;
case SDL_PIXELFORMAT_INDEX4LSB:
p = (Uint8 *)surface->pixels + y * surface->pitch + x / 2;
shift = 4 * (x & 0x1);
mask = 0xf << shift;
bytes_per_pixel = 1;
break;
case SDL_PIXELFORMAT_INDEX2MSB:
p = (Uint8 *)surface->pixels + y * surface->pitch + x / 4;
shift = 2 * (3 - (x & 0x3));
mask = 0x3 << shift;
bytes_per_pixel = 1;
break;
case SDL_PIXELFORMAT_INDEX2LSB:
p = (Uint8 *)surface->pixels + y * surface->pitch + x / 4;
shift = 2 * (x & 0x3);
mask = 0x3 << shift;
bytes_per_pixel = 1;
break;
case SDL_PIXELFORMAT_INDEX1MSB:
p = (Uint8 *)surface->pixels + y * surface->pitch + x / 8;
shift = 7 - (x & 0x7);
mask = 0x1 << shift;
bytes_per_pixel = 1;
break;
case SDL_PIXELFORMAT_INDEX1LSB:
p = (Uint8 *)surface->pixels + y * surface->pitch + x / 8;
shift = x & 0x7;
mask = 0x1 << shift;
bytes_per_pixel = 1;
break;
default:
if (SDL_MUSTLOCK(surface)) {
SDL_UnlockSurface(surface);
}
return SDL_SetError("Unsupported format with 0 bpp");
}
} else {
p = (Uint8 *)surface->pixels + y * surface->pitch + x * bytes_per_pixel;
}

if (bytes_per_pixel <= sizeof(pixel) &&
!SDL_ISPIXELFORMAT_FOURCC(surface->format) &&
Expand All @@ -2842,6 +2890,7 @@ bool SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g
#else
SDL_memcpy(&pixel, p, bytes_per_pixel);
#endif
pixel = (pixel & mask) >> shift;
SDL_GetRGBA(pixel, surface->fmt, surface->palette, r, g, b, a);
result = true;
} else if (SDL_ISPIXELFORMAT_FOURCC(surface->format)) {
Expand Down
Loading