SDL_bmp.c File Reference
`#include "../SDL_internal.h"`
`#include "SDL_hints.h"`
`#include "SDL_video.h"`
`#include "SDL_assert.h"`
`#include "SDL_endian.h"`
`#include "SDL_pixels_c.h"`
Include dependency graph for SDL_bmp.c:

Go to the source code of this file.

## Macros

#define | SAVE_32BIT_BMP
#define | BI_RGB 0
#define | BI_RLE8 1
#define | BI_RLE4 2
#define | BI_BITFIELDS 3
#define | LCS_WINDOWS_COLOR_SPACE 0x57696E20

## Functions

static void | CorrectAlphaChannel (SDL_Surface *surface)
SDL_Surface * | SDL_LoadBMP_RW (SDL_RWops *src, int freesrc)
int | SDL_SaveBMP_RW (SDL_Surface *saveme, SDL_RWops *dst, int freedst)

## Macro Definition Documentation

## BI_BITFIELDS

#define BI_BITFIELDS 3

Definition at line 48 of file SDL_bmp.c.

Referenced by SDL_LoadBMP_RW(), and SDL_SaveBMP_RW().

## BI_RGB

#define BI_RGB 0

Definition at line 45 of file SDL_bmp.c.

Referenced by SDL_LoadBMP_RW(), and SDL_SaveBMP_RW().

## BI_RLE4

#define BI_RLE4 2

Definition at line 47 of file SDL_bmp.c.

## BI_RLE8

#define BI_RLE8 1

Definition at line 46 of file SDL_bmp.c.

## LCS_WINDOWS_COLOR_SPACE

#define LCS_WINDOWS_COLOR_SPACE 0x57696E20

Definition at line 54 of file SDL_bmp.c.

Referenced by SDL_SaveBMP_RW().

## SAVE_32BIT_BMP

#define SAVE_32BIT_BMP

Definition at line 41 of file SDL_bmp.c.

## Function Documentation

## CorrectAlphaChannel()

static void CorrectAlphaChannel | ( | SDL_Surface * | surface | ) |

static

Definition at line 57 of file SDL_bmp.c.

References SDL_Surface::h, SDL_Surface::pitch, SDL_Surface::pixels, SDL_ALPHA_OPAQUE, SDL_FALSE, and SDL_TRUE.

Referenced by SDL_LoadBMP_RW().

{
/* Check to see if there is any alpha channel data */
SDL_bool hasAlpha = SDL_FALSE;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
int alphaChannelOffset = 0;
#else
int alphaChannelOffset = 3;
#endif
Uint8 *alpha = ((Uint8*)surface->pixels) + alphaChannelOffset;
Uint8 *end = alpha + surface->h * surface->pitch;
while (alpha < end) {
if (*alpha != 0) {
hasAlpha = SDL_TRUE;
break;
}
alpha += 4;
}
if (!hasAlpha) {
alpha = ((Uint8*)surface->pixels) + alphaChannelOffset;
while (alpha < end) {
*alpha = SDL_ALPHA_OPAQUE;
alpha += 4;
}
}
}
SDL_TRUE
Definition: SDL_stdinc.h:142
SDL_Surface::h
int h
Definition: SDL_surface.h:73
SDL_FALSE
Definition: SDL_stdinc.h:141
end
GLuint GLuint end
Definition: SDL_opengl.h:1571
alpha
GLfloat GLfloat GLfloat alpha
Definition: SDL_opengl_glext.h:412
SDL_Surface::pixels
void * pixels
Definition: SDL_surface.h:75
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:157
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:139
SDL_Surface::pitch
int pitch
Definition: SDL_surface.h:74
SDL_ALPHA_OPAQUE
#define SDL_ALPHA_OPAQUE
Definition: SDL_pixels.h:46

## SDL_LoadBMP_RW()

SDL_Surface* SDL_LoadBMP_RW | ( | SDL_RWops * | src,
|  | int | freesrc
| ) |  |

Load a surface from a seekable SDL data stream (memory or file).

If `freesrc` is non-zero, the stream will be closed after being read.

The new surface should be freed with SDL_FreeSurface().

Returns
  the new surface, or NULL if there was an error.

Definition at line 87 of file SDL_bmp.c.

References SDL_Color::a, SDL_Color::b, BI_BITFIELDS, BI_RGB, colors, SDL_Palette::colors, CorrectAlphaChannel(), done, SDL_Surface::format, SDL_Color::g, SDL_Surface::h, i, SDL_Palette::ncolors, NULL, SDL_Surface::pitch, SDL_Surface::pixels, SDL_Color::r, RW_SEEK_CUR, RW_SEEK_SET, SDL_ALPHA_OPAQUE, SDL_assert, SDL_ClearError, SDL_CreateRGBSurface, SDL_EFREAD, SDL_EFSEEK, SDL_Error, SDL_FALSE, SDL_FreeSurface, SDL_GetError, SDL_OutOfMemory, SDL_ReadLE16, SDL_ReadLE32, SDL_realloc, SDL_RWclose, SDL_RWread, SDL_RWseek, SDL_RWtell, SDL_SetError, SDL_strcmp, SDL_strncmp, SDL_Swap16(), SDL_Swap32(), SDL_TRUE, void, and SDL_Surface::w.

{
SDL_bool was_error;
Sint64 fp_offset = 0;
int bmpPitch;
int i, pad;
SDL_Surface *surface;
Uint32 Rmask = 0;
Uint32 Gmask = 0;
Uint32 Bmask = 0;
Uint32 Amask = 0;
SDL_Palette *palette;
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;
/* The Win32 BMP file header (14 bytes) */
char magic[2];
/* Uint32 bfSize = 0; */
/* Uint16 bfReserved1 = 0; */
/* Uint16 bfReserved2 = 0; */
Uint32 bfOffBits = 0;
/* The Win32 BITMAPINFOHEADER struct (40 bytes) */
Uint32 biSize = 0;
Sint32 biWidth = 0;
Sint32 biHeight = 0;
/* Uint16 biPlanes = 0; */
Uint16 biBitCount = 0;
Uint32 biCompression = 0;
/* Uint32 biSizeImage = 0; */
/* Sint32 biXPelsPerMeter = 0; */
/* Sint32 biYPelsPerMeter = 0; */
Uint32 biClrUsed = 0;
/* Uint32 biClrImportant = 0; */
(void) haveRGBMasks;
(void) haveAlphaMask;
/* Make sure we are passed a valid data source */
surface = NULL;
was_error = SDL_FALSE;
if (src == NULL) {
was_error = SDL_TRUE;
goto done;
}
/* Read in the BMP file header */
fp_offset = SDL_RWtell(src);
SDL_ClearError();
if (SDL_RWread(src, magic, 1, 2) != 2) {
SDL_Error(SDL_EFREAD);
was_error = SDL_TRUE;
goto done;
}
if (SDL_strncmp(magic, "BM", 2) != 0) {
SDL_SetError("File is not a Windows BMP file");
was_error = SDL_TRUE;
goto done;
}
/* bfSize = */ SDL_ReadLE32(src);
/* bfReserved1 = */ SDL_ReadLE16(src);
/* bfReserved2 = */ SDL_ReadLE16(src);
bfOffBits = SDL_ReadLE32(src);
/* Read the Win32 BITMAPINFOHEADER */
biSize = SDL_ReadLE32(src);
if (biSize == 12) { /* really old BITMAPCOREHEADER */
biWidth = (Uint32) SDL_ReadLE16(src);
biHeight = (Uint32) SDL_ReadLE16(src);
/* biPlanes = */ SDL_ReadLE16(src);
biBitCount = SDL_ReadLE16(src);
biCompression = BI_RGB;
} else if (biSize >= 40) { /* some version of BITMAPINFOHEADER */
Uint32 headerSize;
biWidth = SDL_ReadLE32(src);
biHeight = SDL_ReadLE32(src);
/* biPlanes = */ SDL_ReadLE16(src);
biBitCount = SDL_ReadLE16(src);
biCompression = SDL_ReadLE32(src);
/* biSizeImage = */ SDL_ReadLE32(src);
/* biXPelsPerMeter = */ SDL_ReadLE32(src);
/* biYPelsPerMeter = */ SDL_ReadLE32(src);
biClrUsed = SDL_ReadLE32(src);
/* biClrImportant = */ SDL_ReadLE32(src);
/* 64 == BITMAPCOREHEADER2, an incompatible OS/2 2.x extension. Skip this stuff for now. */
if (biSize == 64) {
/* ignore these extra fields. */
if (biCompression == BI_BITFIELDS) {
/* this value is actually huffman compression in this variant. */
SDL_SetError("Compressed BMP files not supported");
was_error = SDL_TRUE;
goto done;
}
} else {
/* This is complicated. If compression is BI_BITFIELDS, then
we have 3 DWORDS that specify the RGB masks. This is either
stored here in an BITMAPV2INFOHEADER (which only differs in
that it adds these RGB masks) and biSize >= 52, or we've got
these masks stored in the exact same place, but strictly
speaking, this is the bmiColors field in BITMAPINFO immediately
following the legacy v1 info header, just past biSize. */
if (biCompression == BI_BITFIELDS) {
haveRGBMasks = SDL_TRUE;
Rmask = SDL_ReadLE32(src);
Gmask = SDL_ReadLE32(src);
Bmask = SDL_ReadLE32(src);
/* ...v3 adds an alpha mask. */
if (biSize >= 56) { /* BITMAPV3INFOHEADER; adds alpha mask */
haveAlphaMask = SDL_TRUE;
Amask = SDL_ReadLE32(src);
}
} else {
/* the mask fields are ignored for v2+ headers if not BI_BITFIELD. */
if (biSize >= 52) { /* BITMAPV2INFOHEADER; adds RGB masks */
/*Rmask = */ SDL_ReadLE32(src);
/*Gmask = */ SDL_ReadLE32(src);
/*Bmask = */ SDL_ReadLE32(src);
}
if (biSize >= 56) { /* BITMAPV3INFOHEADER; adds alpha mask */
/*Amask = */ SDL_ReadLE32(src);
}
}
/* Insert other fields here; Wikipedia and MSDN say we're up to
v5 of this header, but we ignore those for now (they add gamma,
color spaces, etc). Ignoring the weird OS/2 2.x format, we
currently parse up to v3 correctly (hopefully!). */
}
/* skip any header bytes we didn't handle... */
headerSize = (Uint32) (SDL_RWtell(src) - (fp_offset + 14));
if (biSize > headerSize) {
SDL_RWseek(src, (biSize - headerSize), RW_SEEK_CUR);
}
}
if (biHeight < 0) {
topDown = SDL_TRUE;
biHeight = -biHeight;
} else {
topDown = SDL_FALSE;
}
/* Check for read error */
if (SDL_strcmp(SDL_GetError(), "") != 0) {
was_error = SDL_TRUE;
goto done;
}
/* Expand 1 and 4 bit bitmaps to 8 bits per pixel */
switch (biBitCount) {
case 1:
case 4:
ExpandBMP = biBitCount;
biBitCount = 8;
break;
default:
ExpandBMP = 0;
break;
}
/* We don't support any BMP compression right now */
switch (biCompression) {
case BI_RGB:
/* If there are no masks, use the defaults */
SDL_assert(!haveRGBMasks);
SDL_assert(!haveAlphaMask);
/* Default values for the BMP format */
switch (biBitCount) {
case 15:
case 16:
Rmask = 0x7C00;
Gmask = 0x03E0;
Bmask = 0x001F;
break;
case 24:
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
Rmask = 0x000000FF;
Gmask = 0x0000FF00;
Bmask = 0x00FF0000;
#else
Rmask = 0x00FF0000;
Gmask = 0x0000FF00;
Bmask = 0x000000FF;
#endif
break;
case 32:
/* We don't know if this has alpha channel or not */
correctAlpha = SDL_TRUE;
Amask = 0xFF000000;
Rmask = 0x00FF0000;
Gmask = 0x0000FF00;
Bmask = 0x000000FF;
break;
default:
break;
}
break;
case BI_BITFIELDS:
break; /* we handled this in the info header. */
default:
SDL_SetError("Compressed BMP files not supported");
was_error = SDL_TRUE;
goto done;
}
/* Create a compatible surface, note that the colors are RGB ordered */
surface =
SDL_CreateRGBSurface(0, biWidth, biHeight, biBitCount, Rmask, Gmask,
Bmask, Amask);
if (surface == NULL) {
was_error = SDL_TRUE;
goto done;
}
/* Load the palette, if any */
palette = (surface->format)->palette;
if (palette) {
SDL_assert(biBitCount <= 8);
if (biClrUsed == 0) {
biClrUsed = 1 << biBitCount;
}
if ((int) biClrUsed > palette->ncolors) {
SDL_Color *colors;
int ncolors = biClrUsed;
colors =
(SDL_Color *) SDL_realloc(palette->colors,
ncolors *
sizeof(*palette->colors));
if (!colors) {
SDL_OutOfMemory();
was_error = SDL_TRUE;
goto done;
}
palette->ncolors = ncolors;
palette->colors = colors;
} else if ((int) biClrUsed < palette->ncolors) {
palette->ncolors = biClrUsed;
}
if (biSize == 12) {
for (i = 0; i < (int) biClrUsed; ++i) {
SDL_RWread(src, &palette->colors[i].b, 1, 1);
SDL_RWread(src, &palette->colors[i].g, 1, 1);
SDL_RWread(src, &palette->colors[i].r, 1, 1);
palette->colors[i].a = SDL_ALPHA_OPAQUE;
}
} else {
for (i = 0; i < (int) biClrUsed; ++i) {
SDL_RWread(src, &palette->colors[i].b, 1, 1);
SDL_RWread(src, &palette->colors[i].g, 1, 1);
SDL_RWread(src, &palette->colors[i].r, 1, 1);
SDL_RWread(src, &palette->colors[i].a, 1, 1);
/* According to Microsoft documentation, the fourth element
is reserved and must be zero, so we shouldn't treat it as
alpha.
*/
palette->colors[i].a = SDL_ALPHA_OPAQUE;
}
}
}
/* Read the surface pixels. Note that the bmp image is upside down */
if (SDL_RWseek(src, fp_offset + bfOffBits, RW_SEEK_SET) < 0) {
SDL_Error(SDL_EFSEEK);
was_error = SDL_TRUE;
goto done;
}
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 4:
bmpPitch = (biWidth + 1) >> 1;
pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0);
break;
default:
pad = ((surface->pitch % 4) ? (4 - (surface->pitch % 4)) : 0);
break;
}
if (topDown) {
bits = top;
} else {
bits = end - surface->pitch;
}
while (bits >= top && bits < end) {
switch (ExpandBMP) {
case 1:
case 4:{
Uint8 pixel = 0;
int shift = (8 - ExpandBMP);
for (i = 0; i < surface->w; ++i) {
if (i % (8 / ExpandBMP) == 0) {
if (!SDL_RWread(src, &pixel, 1, 1)) {
SDL_SetError("Error reading from BMP");
was_error = SDL_TRUE;
goto done;
}
}
*(bits + i) = (pixel >> shift);
pixel <<= ExpandBMP;
}
}
break;
default:
if (SDL_RWread(src, bits, 1, surface->pitch)
!= surface->pitch) {
SDL_Error(SDL_EFREAD);
was_error = SDL_TRUE;
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;
}
case 32:{
Uint32 *pix = (Uint32 *) bits;
for (i = 0; i < surface->w; i++)
pix[i] = SDL_Swap32(pix[i]);
break;
}
}
#endif
break;
}
/* Skip padding bytes, ugh */
if (pad) {
Uint8 padbyte;
for (i = 0; i < pad; ++i) {
SDL_RWread(src, &padbyte, 1, 1);
}
}
if (topDown) {
bits += surface->pitch;
} else {
bits -= surface->pitch;
}
}
if (correctAlpha) {
CorrectAlphaChannel(surface);
}
done:
if (was_error) {
if (src) {
SDL_RWseek(src, fp_offset, RW_SEEK_SET);
}
SDL_FreeSurface(surface);
surface = NULL;
}
if (freesrc && src) {
SDL_RWclose(src);
}
return (surface);
}
BI_RGB
#define BI_RGB
Definition: SDL_bmp.c:45
SDL_ClearError
#define SDL_ClearError
Definition: SDL_dynapi_overrides.h:114
SDL_GetError
#define SDL_GetError
Definition: SDL_dynapi_overrides.h:113
SDL_Color
Definition: SDL_pixels.h:295
SDL_TRUE
Definition: SDL_stdinc.h:142
SDL_Color::g
Uint8 g
Definition: SDL_pixels.h:298
SDL_Surface::h
int h
Definition: SDL_surface.h:73
SDL_EFSEEK
Definition: SDL_error.h:60
SDL_FALSE
Definition: SDL_stdinc.h:141
end
GLuint GLuint end
Definition: SDL_opengl.h:1571
surface
EGLSurface surface
Definition: eglext.h:248
SDL_Surface
A collection of pixels used in software blitting.
Definition: SDL_surface.h:69
SDL_ReadLE32
#define SDL_ReadLE32
Definition: SDL_dynapi_overrides.h:359
SDL_RWread
#define SDL_RWread(ctx, ptr, size, n)
Definition: SDL_rwops.h:187
SDL_Color::b
Uint8 b
Definition: SDL_pixels.h:299
bits
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
Definition: SDL_opengl_glext.h:6176
Uint32
uint32_t Uint32
Definition: SDL_stdinc.h:181
SDL_realloc
#define SDL_realloc
Definition: SDL_dynapi_overrides.h:376
CorrectAlphaChannel
static void CorrectAlphaChannel(SDL_Surface *surface)
Definition: SDL_bmp.c:57
SDL_Surface::w
int w
Definition: SDL_surface.h:73
top
GLdouble GLdouble GLdouble GLdouble top
Definition: SDL_opengl_glext.h:6103
SDL_strncmp
#define SDL_strncmp
Definition: SDL_dynapi_overrides.h:418
SDL_Error
#define SDL_Error
Definition: SDL_dynapi_overrides.h:115
SDL_RWseek
#define SDL_RWseek(ctx, offset, whence)
Definition: SDL_rwops.h:185
SDL_ReadLE16
#define SDL_ReadLE16
Definition: SDL_dynapi_overrides.h:357
SDL_Swap32
SDL_FORCE_INLINE Uint32 SDL_Swap32(Uint32 x)
Definition: SDL_endian.h:162
SDL_Palette
Definition: SDL_pixels.h:304
SDL_Color::r
Uint8 r
Definition: SDL_pixels.h:297
SDL_Surface::pixels
void * pixels
Definition: SDL_surface.h:75
SDL_FreeSurface
#define SDL_FreeSurface
Definition: SDL_dynapi_overrides.h:446
SDL_Color::a
Uint8 a
Definition: SDL_pixels.h:300
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:157
done
int done
Definition: checkkeys.c:28
SDL_EFREAD
Definition: SDL_error.h:58
SDL_Palette::ncolors
int ncolors
Definition: SDL_pixels.h:306
SDL_Swap16
SDL_FORCE_INLINE Uint16 SDL_Swap16(Uint16 x)
Definition: SDL_endian.h:107
Sint32
int32_t Sint32
Definition: SDL_stdinc.h:175
BI_BITFIELDS
#define BI_BITFIELDS
Definition: SDL_bmp.c:48
i
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
SDL_assert
#define SDL_assert(condition)
Definition: SDL_assert.h:169
NULL
#define NULL
Definition: begin_code.h:164
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:139
SDL_Palette::colors
SDL_Color * colors
Definition: SDL_pixels.h:307
SDL_Surface::format
SDL_PixelFormat * format
Definition: SDL_surface.h:72
SDL_RWclose
#define SDL_RWclose(ctx)
Definition: SDL_rwops.h:189
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
SDL_CreateRGBSurface
#define SDL_CreateRGBSurface
Definition: SDL_dynapi_overrides.h:444
void
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 void
Definition: SDL_dynapi_procs.h:89
SDL_Surface::pitch
int pitch
Definition: SDL_surface.h:74
RW_SEEK_SET
#define RW_SEEK_SET
Definition: SDL_rwops.h:174
Uint16
uint16_t Uint16
Definition: SDL_stdinc.h:169
SDL_strcmp
#define SDL_strcmp
Definition: SDL_dynapi_overrides.h:417
RW_SEEK_CUR
#define RW_SEEK_CUR
Definition: SDL_rwops.h:175
Sint64
int64_t Sint64
Definition: SDL_stdinc.h:188
colors
static int colors[7]
Definition: testgesture.c:39
SDL_ALPHA_OPAQUE
#define SDL_ALPHA_OPAQUE
Definition: SDL_pixels.h:46
SDL_RWtell
#define SDL_RWtell(ctx)
Definition: SDL_rwops.h:186

## SDL_SaveBMP_RW()

int SDL_SaveBMP_RW | ( | SDL_Surface * | surface,
|  | SDL_RWops * | dst,
|  | int | freedst
| ) |  |

Save a surface to a seekable SDL data stream (memory or file).

Surfaces with a 24-bit, 32-bit and paletted 8-bit 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 not supported.

If `freedst` is non-zero, the stream will be closed after being written.

Returns
  0 if successful or -1 if there was an error.

Definition at line 463 of file SDL_bmp.c.

References SDL_PixelFormat::Amask, BI_BITFIELDS, BI_RGB, SDL_PixelFormat::BitsPerPixel, SDL_PixelFormat::Bmask, SDL_PixelFormat::BytesPerPixel, colors, SDL_Palette::colors, SDL_BlitInfo::flags, SDL_Surface::format, SDL_PixelFormat::Gmask, SDL_Surface::h, i, SDL_BlitMap::info, LCS_WINDOWS_COLOR_SPACE, SDL_Surface::map, SDL_Palette::ncolors, NULL, SDL_PixelFormat::palette, SDL_Surface::pitch, SDL_Surface::pixels, SDL_PixelFormat::Rmask, RW_SEEK_SET, SDL_BYTEORDER, SDL_ClearError, SDL_ConvertSurface, SDL_COPY_COLORKEY, SDL_EFSEEK, SDL_EFWRITE, SDL_Error, SDL_FALSE, SDL_FreeSurface, SDL_GetError, SDL_GetHintBoolean, SDL_HINT_BMP_SAVE_LEGACY_FORMAT, SDL_InitFormat(), SDL_LIL_ENDIAN, SDL_LockSurface, SDL_PIXELFORMAT_BGR24, SDL_PIXELFORMAT_BGRA32, SDL_RWclose, SDL_RWseek, SDL_RWtell, SDL_RWwrite, SDL_SetError, SDL_strcmp, SDL_TRUE, SDL_UnlockSurface, SDL_WriteLE16, SDL_WriteLE32, and SDL_Surface::w.

{
Sint64 fp_offset;
int i, pad;
SDL_Surface *surface;
Uint8 *bits;
SDL_bool save32bit = SDL_FALSE;
SDL_bool saveLegacyBMP = SDL_FALSE;
/* The Win32 BMP file header (14 bytes) */
char magic[2] = { 'B', 'M' };
Uint32 bfSize;
Uint16 bfReserved1;
Uint16 bfReserved2;
Uint32 bfOffBits;
/* The Win32 BITMAPINFOHEADER struct (40 bytes) */
Uint32 biSize;
Sint32 biWidth;
Sint32 biHeight;
Uint16 biPlanes;
Uint16 biBitCount;
Uint32 biCompression;
Uint32 biSizeImage;
Sint32 biXPelsPerMeter;
Sint32 biYPelsPerMeter;
Uint32 biClrUsed;
Uint32 biClrImportant;
/* The additional header members from the Win32 BITMAPV4HEADER struct (108 bytes in total) */
Uint32 bV4RedMask = 0;
Uint32 bV4GreenMask = 0;
Uint32 bV4BlueMask = 0;
Uint32 bV4AlphaMask = 0;
Uint32 bV4CSType = 0;
Sint32 bV4Endpoints[3 * 3] = {0};
Uint32 bV4GammaRed = 0;
Uint32 bV4GammaGreen = 0;
Uint32 bV4GammaBlue = 0;
/* Make sure we have somewhere to save */
surface = NULL;
if (dst) {
#ifdef SAVE_32BIT_BMP
/* We can save alpha information in a 32-bit BMP */
if (saveme->format->BitsPerPixel >= 8 && (saveme->format->Amask ||
saveme->map->info.flags & SDL_COPY_COLORKEY)) {
save32bit = SDL_TRUE;
}
#endif /* SAVE_32BIT_BMP */
if (saveme->format->palette && !save32bit) {
if (saveme->format->BitsPerPixel == 8) {
surface = saveme;
} else {
SDL_SetError("%d bpp BMP files not supported",
saveme->format->BitsPerPixel);
}
} else if ((saveme->format->BitsPerPixel == 24) && !save32bit &&
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
(saveme->format->Rmask == 0x00FF0000) &&
(saveme->format->Gmask == 0x0000FF00) &&
(saveme->format->Bmask == 0x000000FF)
#else
(saveme->format->Rmask == 0x000000FF) &&
(saveme->format->Gmask == 0x0000FF00) &&
(saveme->format->Bmask == 0x00FF0000)
#endif
) {
surface = saveme;
} else {
SDL_PixelFormat format;
/* If the surface has a colorkey or alpha channel we'll save a
32-bit BMP with alpha channel, otherwise save a 24-bit BMP. */
if (save32bit) {
SDL_InitFormat(&format, SDL_PIXELFORMAT_BGRA32);
} else {
SDL_InitFormat(&format, SDL_PIXELFORMAT_BGR24);
}
surface = SDL_ConvertSurface(saveme, &format, 0);
if (!surface) {
SDL_SetError("Couldn't convert image to %d bpp",
format.BitsPerPixel);
}
}
} else {
/* Set no error here because it may overwrite a more useful message from
SDL_RWFromFile() if SDL_SaveBMP_RW() is called from SDL_SaveBMP(). */
return -1;
}
if (save32bit) {
saveLegacyBMP = SDL_GetHintBoolean(SDL_HINT_BMP_SAVE_LEGACY_FORMAT, SDL_FALSE);
}
if (surface && (SDL_LockSurface(surface) == 0)) {
const int bw = surface->w * surface->format->BytesPerPixel;
/* Set the BMP file header values */
bfSize = 0; /* We'll write this when we're done */
bfReserved1 = 0;
bfReserved2 = 0;
bfOffBits = 0; /* We'll write this when we're done */
/* Write the BMP file header values */
fp_offset = SDL_RWtell(dst);
SDL_ClearError();
SDL_RWwrite(dst, magic, 2, 1);
SDL_WriteLE32(dst, bfSize);
SDL_WriteLE16(dst, bfReserved1);
SDL_WriteLE16(dst, bfReserved2);
SDL_WriteLE32(dst, bfOffBits);
/* Set the BMP info values */
biSize = 40;
biWidth = surface->w;
biHeight = surface->h;
biPlanes = 1;
biBitCount = surface->format->BitsPerPixel;
biCompression = BI_RGB;
biSizeImage = surface->h * surface->pitch;
biXPelsPerMeter = 0;
biYPelsPerMeter = 0;
if (surface->format->palette) {
biClrUsed = surface->format->palette->ncolors;
} else {
biClrUsed = 0;
}
biClrImportant = 0;
/* Set the BMP info values for the version 4 header */
if (save32bit && !saveLegacyBMP) {
biSize = 108;
biCompression = BI_BITFIELDS;
/* The BMP format is always little endian, these masks stay the same */
bV4RedMask = 0x00ff0000;
bV4GreenMask = 0x0000ff00;
bV4BlueMask = 0x000000ff;
bV4AlphaMask = 0xff000000;
bV4CSType = LCS_WINDOWS_COLOR_SPACE;
bV4GammaRed = 0;
bV4GammaGreen = 0;
bV4GammaBlue = 0;
}
/* Write the BMP info values */
SDL_WriteLE32(dst, biSize);
SDL_WriteLE32(dst, biWidth);
SDL_WriteLE32(dst, biHeight);
SDL_WriteLE16(dst, biPlanes);
SDL_WriteLE16(dst, biBitCount);
SDL_WriteLE32(dst, biCompression);
SDL_WriteLE32(dst, biSizeImage);
SDL_WriteLE32(dst, biXPelsPerMeter);
SDL_WriteLE32(dst, biYPelsPerMeter);
SDL_WriteLE32(dst, biClrUsed);
SDL_WriteLE32(dst, biClrImportant);
/* Write the BMP info values for the version 4 header */
if (save32bit && !saveLegacyBMP) {
SDL_WriteLE32(dst, bV4RedMask);
SDL_WriteLE32(dst, bV4GreenMask);
SDL_WriteLE32(dst, bV4BlueMask);
SDL_WriteLE32(dst, bV4AlphaMask);
SDL_WriteLE32(dst, bV4CSType);
for (i = 0; i < 3 * 3; i++) {
SDL_WriteLE32(dst, bV4Endpoints[i]);
}
SDL_WriteLE32(dst, bV4GammaRed);
SDL_WriteLE32(dst, bV4GammaGreen);
SDL_WriteLE32(dst, bV4GammaBlue);
}
/* Write the palette (in BGR color order) */
if (surface->format->palette) {
SDL_Color *colors;
int ncolors;
colors = surface->format->palette->colors;
ncolors = surface->format->palette->ncolors;
for (i = 0; i < ncolors; ++i) {
SDL_RWwrite(dst, &colors[i].b, 1, 1);
SDL_RWwrite(dst, &colors[i].g, 1, 1);
SDL_RWwrite(dst, &colors[i].r, 1, 1);
SDL_RWwrite(dst, &colors[i].a, 1, 1);
}
}
/* Write the bitmap offset */
bfOffBits = (Uint32)(SDL_RWtell(dst) - fp_offset);
if (SDL_RWseek(dst, fp_offset + 10, RW_SEEK_SET) < 0) {
SDL_Error(SDL_EFSEEK);
}
SDL_WriteLE32(dst, bfOffBits);
if (SDL_RWseek(dst, fp_offset + bfOffBits, RW_SEEK_SET) < 0) {
SDL_Error(SDL_EFSEEK);
}
/* Write the bitmap image upside down */
bits = (Uint8 *) surface->pixels + (surface->h * surface->pitch);
pad = ((bw % 4) ? (4 - (bw % 4)) : 0);
while (bits > (Uint8 *) surface->pixels) {
bits -= surface->pitch;
if (SDL_RWwrite(dst, bits, 1, bw) != bw) {
SDL_Error(SDL_EFWRITE);
break;
}
if (pad) {
const Uint8 padbyte = 0;
for (i = 0; i < pad; ++i) {
SDL_RWwrite(dst, &padbyte, 1, 1);
}
}
}
/* Write the BMP file size */
bfSize = (Uint32)(SDL_RWtell(dst) - fp_offset);
if (SDL_RWseek(dst, fp_offset + 2, RW_SEEK_SET) < 0) {
SDL_Error(SDL_EFSEEK);
}
SDL_WriteLE32(dst, bfSize);
if (SDL_RWseek(dst, fp_offset + bfSize, RW_SEEK_SET) < 0) {
SDL_Error(SDL_EFSEEK);
}
/* Close it up.. */
SDL_UnlockSurface(surface);
if (surface != saveme) {
SDL_FreeSurface(surface);
}
}
if (freedst && dst) {
SDL_RWclose(dst);
}
return ((SDL_strcmp(SDL_GetError(), "") == 0) ? 0 : -1);
}
BI_RGB
#define BI_RGB
Definition: SDL_bmp.c:45
SDL_ClearError
#define SDL_ClearError
Definition: SDL_dynapi_overrides.h:114
r
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2079
SDL_GetError
#define SDL_GetError
Definition: SDL_dynapi_overrides.h:113
SDL_Color
Definition: SDL_pixels.h:295
SDL_UnlockSurface
#define SDL_UnlockSurface
Definition: SDL_dynapi_overrides.h:449
SDL_TRUE
Definition: SDL_stdinc.h:142
SDL_COPY_COLORKEY
#define SDL_COPY_COLORKEY
Definition: SDL_blit.h:39
LCS_WINDOWS_COLOR_SPACE
#define LCS_WINDOWS_COLOR_SPACE
Definition: SDL_bmp.c:54
SDL_PixelFormat::Gmask
Uint32 Gmask
Definition: SDL_pixels.h:323
SDL_Surface::h
int h
Definition: SDL_surface.h:73
SDL_PIXELFORMAT_BGR24
Definition: SDL_pixels.h:233
SDL_RWwrite
#define SDL_RWwrite(ctx, ptr, size, n)
Definition: SDL_rwops.h:188
SDL_PixelFormat::BytesPerPixel
Uint8 BytesPerPixel
Definition: SDL_pixels.h:320
SDL_ConvertSurface
#define SDL_ConvertSurface
Definition: SDL_dynapi_overrides.h:463
SDL_BlitInfo::flags
int flags
Definition: SDL_blit.h:68
SDL_EFSEEK
Definition: SDL_error.h:60
SDL_FALSE
Definition: SDL_stdinc.h:141
surface
EGLSurface surface
Definition: eglext.h:248
SDL_Surface
A collection of pixels used in software blitting.
Definition: SDL_surface.h:69
SDL_PixelFormat::Bmask
Uint32 Bmask
Definition: SDL_pixels.h:324
SDL_WriteLE16
#define SDL_WriteLE16
Definition: SDL_dynapi_overrides.h:364
SDL_LIL_ENDIAN
#define SDL_LIL_ENDIAN
Definition: SDL_endian.h:37
bits
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
Definition: SDL_opengl_glext.h:6176
Uint32
uint32_t Uint32
Definition: SDL_stdinc.h:181
SDL_Surface::w
int w
Definition: SDL_surface.h:73
SDL_Error
#define SDL_Error
Definition: SDL_dynapi_overrides.h:115
SDL_GetHintBoolean
#define SDL_GetHintBoolean
Definition: SDL_dynapi_overrides.h:608
SDL_RWseek
#define SDL_RWseek(ctx, offset, whence)
Definition: SDL_rwops.h:185
format
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
SDL_Surface::map
struct SDL_BlitMap * map
Definition: SDL_surface.h:88
SDL_Surface::pixels
void * pixels
Definition: SDL_surface.h:75
SDL_FreeSurface
#define SDL_FreeSurface
Definition: SDL_dynapi_overrides.h:446
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:157
SDL_PixelFormat::BitsPerPixel
Uint8 BitsPerPixel
Definition: SDL_pixels.h:319
SDL_HINT_BMP_SAVE_LEGACY_FORMAT
#define SDL_HINT_BMP_SAVE_LEGACY_FORMAT
Prevent SDL from using version 4 of the bitmap header when saving BMPs.
Definition: SDL_hints.h:819
SDL_Palette::ncolors
int ncolors
Definition: SDL_pixels.h:306
Sint32
int32_t Sint32
Definition: SDL_stdinc.h:175
SDL_InitFormat
int SDL_InitFormat(SDL_PixelFormat *format, Uint32 pixel_format)
Definition: SDL_pixels.c:537
BI_BITFIELDS
#define BI_BITFIELDS
Definition: SDL_bmp.c:48
i
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
NULL
#define NULL
Definition: begin_code.h:164
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:139
SDL_Palette::colors
SDL_Color * colors
Definition: SDL_pixels.h:307
SDL_Surface::format
SDL_PixelFormat * format
Definition: SDL_surface.h:72
SDL_RWclose
#define SDL_RWclose(ctx)
Definition: SDL_rwops.h:189
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
SDL_LockSurface
#define SDL_LockSurface
Definition: SDL_dynapi_overrides.h:448
SDL_PixelFormat::Rmask
Uint32 Rmask
Definition: SDL_pixels.h:322
SDL_PixelFormat
Definition: SDL_pixels.h:315
SDL_Surface::pitch
int pitch
Definition: SDL_surface.h:74
SDL_WriteLE32
#define SDL_WriteLE32
Definition: SDL_dynapi_overrides.h:366
RW_SEEK_SET
#define RW_SEEK_SET
Definition: SDL_rwops.h:174
Uint16
uint16_t Uint16
Definition: SDL_stdinc.h:169
SDL_PixelFormat::Amask
Uint32 Amask
Definition: SDL_pixels.h:325
SDL_PixelFormat::palette
SDL_Palette * palette
Definition: SDL_pixels.h:318
SDL_strcmp
#define SDL_strcmp
Definition: SDL_dynapi_overrides.h:417
Sint64
int64_t Sint64
Definition: SDL_stdinc.h:188
SDL_EFWRITE
Definition: SDL_error.h:59
colors
static int colors[7]
Definition: testgesture.c:39
a
GLboolean GLboolean GLboolean GLboolean a
Definition: SDL_opengl_glext.h:1109
g
GLboolean GLboolean g
Definition: SDL_opengl_glext.h:1109
b
GLboolean GLboolean GLboolean b
Definition: SDL_opengl_glext.h:1109
SDL_RWtell
#define SDL_RWtell(ctx)
Definition: SDL_rwops.h:186
SDL_BYTEORDER
#define SDL_BYTEORDER
Definition: SDL_config_pandora.h:37
SDL_BlitMap::info
SDL_BlitInfo info
Definition: SDL_blit.h:92
SDL_PIXELFORMAT_BGRA32
Definition: SDL_pixels.h:273