SDL  2.0
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_SurfaceSDL_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().

58 {
59  /* Check to see if there is any alpha channel data */
60  SDL_bool hasAlpha = SDL_FALSE;
61 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
62  int alphaChannelOffset = 0;
63 #else
64  int alphaChannelOffset = 3;
65 #endif
66  Uint8 *alpha = ((Uint8*)surface->pixels) + alphaChannelOffset;
67  Uint8 *end = alpha + surface->h * surface->pitch;
68 
69  while (alpha < end) {
70  if (*alpha != 0) {
71  hasAlpha = SDL_TRUE;
72  break;
73  }
74  alpha += 4;
75  }
76 
77  if (!hasAlpha) {
78  alpha = ((Uint8*)surface->pixels) + alphaChannelOffset;
79  while (alpha < end) {
80  *alpha = SDL_ALPHA_OPAQUE;
81  alpha += 4;
82  }
83  }
84 }
GLuint GLuint end
Definition: SDL_opengl.h:1564
GLfloat GLfloat GLfloat alpha
void * pixels
Definition: SDL_surface.h:75
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:143
SDL_bool
Definition: SDL_stdinc.h:130
#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, and SDL_Surface::w.

88 {
89  SDL_bool was_error;
90  Sint64 fp_offset = 0;
91  int bmpPitch;
92  int i, pad;
93  SDL_Surface *surface;
94  Uint32 Rmask = 0;
95  Uint32 Gmask = 0;
96  Uint32 Bmask = 0;
97  Uint32 Amask = 0;
98  SDL_Palette *palette;
99  Uint8 *bits;
100  Uint8 *top, *end;
101  SDL_bool topDown;
102  int ExpandBMP;
103  SDL_bool haveRGBMasks = SDL_FALSE;
104  SDL_bool haveAlphaMask = SDL_FALSE;
105  SDL_bool correctAlpha = SDL_FALSE;
106 
107  /* The Win32 BMP file header (14 bytes) */
108  char magic[2];
109  /* Uint32 bfSize = 0; */
110  /* Uint16 bfReserved1 = 0; */
111  /* Uint16 bfReserved2 = 0; */
112  Uint32 bfOffBits = 0;
113 
114  /* The Win32 BITMAPINFOHEADER struct (40 bytes) */
115  Uint32 biSize = 0;
116  Sint32 biWidth = 0;
117  Sint32 biHeight = 0;
118  /* Uint16 biPlanes = 0; */
119  Uint16 biBitCount = 0;
120  Uint32 biCompression = 0;
121  /* Uint32 biSizeImage = 0; */
122  /* Sint32 biXPelsPerMeter = 0; */
123  /* Sint32 biYPelsPerMeter = 0; */
124  Uint32 biClrUsed = 0;
125  /* Uint32 biClrImportant = 0; */
126 
127  /* Make sure we are passed a valid data source */
128  surface = NULL;
129  was_error = SDL_FALSE;
130  if (src == NULL) {
131  was_error = SDL_TRUE;
132  goto done;
133  }
134 
135  /* Read in the BMP file header */
136  fp_offset = SDL_RWtell(src);
137  SDL_ClearError();
138  if (SDL_RWread(src, magic, 1, 2) != 2) {
140  was_error = SDL_TRUE;
141  goto done;
142  }
143  if (SDL_strncmp(magic, "BM", 2) != 0) {
144  SDL_SetError("File is not a Windows BMP file");
145  was_error = SDL_TRUE;
146  goto done;
147  }
148  /* bfSize = */ SDL_ReadLE32(src);
149  /* bfReserved1 = */ SDL_ReadLE16(src);
150  /* bfReserved2 = */ SDL_ReadLE16(src);
151  bfOffBits = SDL_ReadLE32(src);
152 
153  /* Read the Win32 BITMAPINFOHEADER */
154  biSize = SDL_ReadLE32(src);
155  if (biSize == 12) { /* really old BITMAPCOREHEADER */
156  biWidth = (Uint32) SDL_ReadLE16(src);
157  biHeight = (Uint32) SDL_ReadLE16(src);
158  /* biPlanes = */ SDL_ReadLE16(src);
159  biBitCount = SDL_ReadLE16(src);
160  biCompression = BI_RGB;
161  } else if (biSize >= 40) { /* some version of BITMAPINFOHEADER */
162  Uint32 headerSize;
163  biWidth = SDL_ReadLE32(src);
164  biHeight = SDL_ReadLE32(src);
165  /* biPlanes = */ SDL_ReadLE16(src);
166  biBitCount = SDL_ReadLE16(src);
167  biCompression = SDL_ReadLE32(src);
168  /* biSizeImage = */ SDL_ReadLE32(src);
169  /* biXPelsPerMeter = */ SDL_ReadLE32(src);
170  /* biYPelsPerMeter = */ SDL_ReadLE32(src);
171  biClrUsed = SDL_ReadLE32(src);
172  /* biClrImportant = */ SDL_ReadLE32(src);
173 
174  /* 64 == BITMAPCOREHEADER2, an incompatible OS/2 2.x extension. Skip this stuff for now. */
175  if (biSize == 64) {
176  /* ignore these extra fields. */
177  if (biCompression == BI_BITFIELDS) {
178  /* this value is actually huffman compression in this variant. */
179  SDL_SetError("Compressed BMP files not supported");
180  was_error = SDL_TRUE;
181  goto done;
182  }
183  } else {
184  /* This is complicated. If compression is BI_BITFIELDS, then
185  we have 3 DWORDS that specify the RGB masks. This is either
186  stored here in an BITMAPV2INFOHEADER (which only differs in
187  that it adds these RGB masks) and biSize >= 52, or we've got
188  these masks stored in the exact same place, but strictly
189  speaking, this is the bmiColors field in BITMAPINFO immediately
190  following the legacy v1 info header, just past biSize. */
191  if (biCompression == BI_BITFIELDS) {
192  haveRGBMasks = SDL_TRUE;
193  Rmask = SDL_ReadLE32(src);
194  Gmask = SDL_ReadLE32(src);
195  Bmask = SDL_ReadLE32(src);
196 
197  /* ...v3 adds an alpha mask. */
198  if (biSize >= 56) { /* BITMAPV3INFOHEADER; adds alpha mask */
199  haveAlphaMask = SDL_TRUE;
200  Amask = SDL_ReadLE32(src);
201  }
202  } else {
203  /* the mask fields are ignored for v2+ headers if not BI_BITFIELD. */
204  if (biSize >= 52) { /* BITMAPV2INFOHEADER; adds RGB masks */
205  /*Rmask = */ SDL_ReadLE32(src);
206  /*Gmask = */ SDL_ReadLE32(src);
207  /*Bmask = */ SDL_ReadLE32(src);
208  }
209  if (biSize >= 56) { /* BITMAPV3INFOHEADER; adds alpha mask */
210  /*Amask = */ SDL_ReadLE32(src);
211  }
212  }
213 
214  /* Insert other fields here; Wikipedia and MSDN say we're up to
215  v5 of this header, but we ignore those for now (they add gamma,
216  color spaces, etc). Ignoring the weird OS/2 2.x format, we
217  currently parse up to v3 correctly (hopefully!). */
218  }
219 
220  /* skip any header bytes we didn't handle... */
221  headerSize = (Uint32) (SDL_RWtell(src) - (fp_offset + 14));
222  if (biSize > headerSize) {
223  SDL_RWseek(src, (biSize - headerSize), RW_SEEK_CUR);
224  }
225  }
226  if (biHeight < 0) {
227  topDown = SDL_TRUE;
228  biHeight = -biHeight;
229  } else {
230  topDown = SDL_FALSE;
231  }
232 
233  /* Check for read error */
234  if (SDL_strcmp(SDL_GetError(), "") != 0) {
235  was_error = SDL_TRUE;
236  goto done;
237  }
238 
239  /* Expand 1 and 4 bit bitmaps to 8 bits per pixel */
240  switch (biBitCount) {
241  case 1:
242  case 4:
243  ExpandBMP = biBitCount;
244  biBitCount = 8;
245  break;
246  default:
247  ExpandBMP = 0;
248  break;
249  }
250 
251  /* We don't support any BMP compression right now */
252  switch (biCompression) {
253  case BI_RGB:
254  /* If there are no masks, use the defaults */
255  SDL_assert(!haveRGBMasks);
256  SDL_assert(!haveAlphaMask);
257  /* Default values for the BMP format */
258  switch (biBitCount) {
259  case 15:
260  case 16:
261  Rmask = 0x7C00;
262  Gmask = 0x03E0;
263  Bmask = 0x001F;
264  break;
265  case 24:
266 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
267  Rmask = 0x000000FF;
268  Gmask = 0x0000FF00;
269  Bmask = 0x00FF0000;
270 #else
271  Rmask = 0x00FF0000;
272  Gmask = 0x0000FF00;
273  Bmask = 0x000000FF;
274 #endif
275  break;
276  case 32:
277  /* We don't know if this has alpha channel or not */
278  correctAlpha = SDL_TRUE;
279  Amask = 0xFF000000;
280  Rmask = 0x00FF0000;
281  Gmask = 0x0000FF00;
282  Bmask = 0x000000FF;
283  break;
284  default:
285  break;
286  }
287  break;
288 
289  case BI_BITFIELDS:
290  break; /* we handled this in the info header. */
291 
292  default:
293  SDL_SetError("Compressed BMP files not supported");
294  was_error = SDL_TRUE;
295  goto done;
296  }
297 
298  /* Create a compatible surface, note that the colors are RGB ordered */
299  surface =
300  SDL_CreateRGBSurface(0, biWidth, biHeight, biBitCount, Rmask, Gmask,
301  Bmask, Amask);
302  if (surface == NULL) {
303  was_error = SDL_TRUE;
304  goto done;
305  }
306 
307  /* Load the palette, if any */
308  palette = (surface->format)->palette;
309  if (palette) {
310  SDL_assert(biBitCount <= 8);
311  if (biClrUsed == 0) {
312  biClrUsed = 1 << biBitCount;
313  }
314  if ((int) biClrUsed > palette->ncolors) {
315  SDL_Color *colors;
316  int ncolors = biClrUsed;
317  colors =
318  (SDL_Color *) SDL_realloc(palette->colors,
319  ncolors *
320  sizeof(*palette->colors));
321  if (!colors) {
322  SDL_OutOfMemory();
323  was_error = SDL_TRUE;
324  goto done;
325  }
326  palette->ncolors = ncolors;
327  palette->colors = colors;
328  } else if ((int) biClrUsed < palette->ncolors) {
329  palette->ncolors = biClrUsed;
330  }
331  if (biSize == 12) {
332  for (i = 0; i < (int) biClrUsed; ++i) {
333  SDL_RWread(src, &palette->colors[i].b, 1, 1);
334  SDL_RWread(src, &palette->colors[i].g, 1, 1);
335  SDL_RWread(src, &palette->colors[i].r, 1, 1);
336  palette->colors[i].a = SDL_ALPHA_OPAQUE;
337  }
338  } else {
339  for (i = 0; i < (int) biClrUsed; ++i) {
340  SDL_RWread(src, &palette->colors[i].b, 1, 1);
341  SDL_RWread(src, &palette->colors[i].g, 1, 1);
342  SDL_RWread(src, &palette->colors[i].r, 1, 1);
343  SDL_RWread(src, &palette->colors[i].a, 1, 1);
344 
345  /* According to Microsoft documentation, the fourth element
346  is reserved and must be zero, so we shouldn't treat it as
347  alpha.
348  */
349  palette->colors[i].a = SDL_ALPHA_OPAQUE;
350  }
351  }
352  }
353 
354  /* Read the surface pixels. Note that the bmp image is upside down */
355  if (SDL_RWseek(src, fp_offset + bfOffBits, RW_SEEK_SET) < 0) {
357  was_error = SDL_TRUE;
358  goto done;
359  }
360  top = (Uint8 *)surface->pixels;
361  end = (Uint8 *)surface->pixels+(surface->h*surface->pitch);
362  switch (ExpandBMP) {
363  case 1:
364  bmpPitch = (biWidth + 7) >> 3;
365  pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0);
366  break;
367  case 4:
368  bmpPitch = (biWidth + 1) >> 1;
369  pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0);
370  break;
371  default:
372  pad = ((surface->pitch % 4) ? (4 - (surface->pitch % 4)) : 0);
373  break;
374  }
375  if (topDown) {
376  bits = top;
377  } else {
378  bits = end - surface->pitch;
379  }
380  while (bits >= top && bits < end) {
381  switch (ExpandBMP) {
382  case 1:
383  case 4:{
384  Uint8 pixel = 0;
385  int shift = (8 - ExpandBMP);
386  for (i = 0; i < surface->w; ++i) {
387  if (i % (8 / ExpandBMP) == 0) {
388  if (!SDL_RWread(src, &pixel, 1, 1)) {
389  SDL_SetError("Error reading from BMP");
390  was_error = SDL_TRUE;
391  goto done;
392  }
393  }
394  *(bits + i) = (pixel >> shift);
395  pixel <<= ExpandBMP;
396  }
397  }
398  break;
399 
400  default:
401  if (SDL_RWread(src, bits, 1, surface->pitch)
402  != surface->pitch) {
404  was_error = SDL_TRUE;
405  goto done;
406  }
407 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
408  /* Byte-swap the pixels if needed. Note that the 24bpp
409  case has already been taken care of above. */
410  switch (biBitCount) {
411  case 15:
412  case 16:{
413  Uint16 *pix = (Uint16 *) bits;
414  for (i = 0; i < surface->w; i++)
415  pix[i] = SDL_Swap16(pix[i]);
416  break;
417  }
418 
419  case 32:{
420  Uint32 *pix = (Uint32 *) bits;
421  for (i = 0; i < surface->w; i++)
422  pix[i] = SDL_Swap32(pix[i]);
423  break;
424  }
425  }
426 #endif
427  break;
428  }
429  /* Skip padding bytes, ugh */
430  if (pad) {
431  Uint8 padbyte;
432  for (i = 0; i < pad; ++i) {
433  SDL_RWread(src, &padbyte, 1, 1);
434  }
435  }
436  if (topDown) {
437  bits += surface->pitch;
438  } else {
439  bits -= surface->pitch;
440  }
441  }
442  if (correctAlpha) {
443  CorrectAlphaChannel(surface);
444  }
445  done:
446  if (was_error) {
447  if (src) {
448  SDL_RWseek(src, fp_offset, RW_SEEK_SET);
449  }
450  SDL_FreeSurface(surface);
451  surface = NULL;
452  }
453  if (freesrc && src) {
454  SDL_RWclose(src);
455  }
456  return (surface);
457 }
#define BI_RGB
Definition: SDL_bmp.c:45
#define SDL_ClearError
#define SDL_GetError
Uint8 g
Definition: SDL_pixels.h:296
GLuint GLuint end
Definition: SDL_opengl.h:1564
A collection of pixels used in software blitting.
Definition: SDL_surface.h:69
#define SDL_ReadLE32
#define SDL_RWread(ctx, ptr, size, n)
Definition: SDL_rwops.h:187
Uint8 b
Definition: SDL_pixels.h:297
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:159
#define SDL_realloc
static void CorrectAlphaChannel(SDL_Surface *surface)
Definition: SDL_bmp.c:57
GLdouble GLdouble GLdouble GLdouble top
#define SDL_strncmp
#define SDL_Error
#define SDL_RWseek(ctx, offset, whence)
Definition: SDL_rwops.h:185
#define SDL_ReadLE16
SDL_FORCE_INLINE Uint32 SDL_Swap32(Uint32 x)
Definition: SDL_endian.h:141
Uint8 r
Definition: SDL_pixels.h:295
void * pixels
Definition: SDL_surface.h:75
#define SDL_FreeSurface
Uint8 a
Definition: SDL_pixels.h:298
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:143
int done
Definition: checkkeys.c:28
SDL_FORCE_INLINE Uint16 SDL_Swap16(Uint16 x)
Definition: SDL_endian.h:101
int32_t Sint32
A signed 32-bit integer type.
Definition: SDL_stdinc.h:155
#define BI_BITFIELDS
Definition: SDL_bmp.c:48
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
#define SDL_assert(condition)
Definition: SDL_assert.h:167
#define NULL
Definition: begin_code.h:143
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:130
SDL_Color * colors
Definition: SDL_pixels.h:305
SDL_PixelFormat * format
Definition: SDL_surface.h:72
#define SDL_RWclose(ctx)
Definition: SDL_rwops.h:189
#define SDL_SetError
#define SDL_CreateRGBSurface
#define RW_SEEK_SET
Definition: SDL_rwops.h:174
uint16_t Uint16
An unsigned 16-bit integer type.
Definition: SDL_stdinc.h:151
#define SDL_strcmp
#define RW_SEEK_CUR
Definition: SDL_rwops.h:175
int64_t Sint64
A signed 64-bit integer type.
Definition: SDL_stdinc.h:164
static int colors[7]
Definition: testgesture.c:40
#define SDL_ALPHA_OPAQUE
Definition: SDL_pixels.h:46
#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 460 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.

461 {
462  Sint64 fp_offset;
463  int i, pad;
464  SDL_Surface *surface;
465  Uint8 *bits;
466  SDL_bool save32bit = SDL_FALSE;
467  SDL_bool saveLegacyBMP = SDL_FALSE;
468 
469  /* The Win32 BMP file header (14 bytes) */
470  char magic[2] = { 'B', 'M' };
471  Uint32 bfSize;
472  Uint16 bfReserved1;
473  Uint16 bfReserved2;
474  Uint32 bfOffBits;
475 
476  /* The Win32 BITMAPINFOHEADER struct (40 bytes) */
477  Uint32 biSize;
478  Sint32 biWidth;
479  Sint32 biHeight;
480  Uint16 biPlanes;
481  Uint16 biBitCount;
482  Uint32 biCompression;
483  Uint32 biSizeImage;
484  Sint32 biXPelsPerMeter;
485  Sint32 biYPelsPerMeter;
486  Uint32 biClrUsed;
487  Uint32 biClrImportant;
488 
489  /* The additional header members from the Win32 BITMAPV4HEADER struct (108 bytes in total) */
490  Uint32 bV4RedMask = 0;
491  Uint32 bV4GreenMask = 0;
492  Uint32 bV4BlueMask = 0;
493  Uint32 bV4AlphaMask = 0;
494  Uint32 bV4CSType = 0;
495  Sint32 bV4Endpoints[3 * 3] = {0};
496  Uint32 bV4GammaRed = 0;
497  Uint32 bV4GammaGreen = 0;
498  Uint32 bV4GammaBlue = 0;
499 
500  /* Make sure we have somewhere to save */
501  surface = NULL;
502  if (dst) {
503 #ifdef SAVE_32BIT_BMP
504  /* We can save alpha information in a 32-bit BMP */
505  if (saveme->format->BitsPerPixel >= 8 && (saveme->format->Amask ||
506  saveme->map->info.flags & SDL_COPY_COLORKEY)) {
507  save32bit = SDL_TRUE;
508  }
509 #endif /* SAVE_32BIT_BMP */
510 
511  if (saveme->format->palette && !save32bit) {
512  if (saveme->format->BitsPerPixel == 8) {
513  surface = saveme;
514  } else {
515  SDL_SetError("%d bpp BMP files not supported",
516  saveme->format->BitsPerPixel);
517  }
518  } else if ((saveme->format->BitsPerPixel == 24) && !save32bit &&
520  (saveme->format->Rmask == 0x00FF0000) &&
521  (saveme->format->Gmask == 0x0000FF00) &&
522  (saveme->format->Bmask == 0x000000FF)
523 #else
524  (saveme->format->Rmask == 0x000000FF) &&
525  (saveme->format->Gmask == 0x0000FF00) &&
526  (saveme->format->Bmask == 0x00FF0000)
527 #endif
528  ) {
529  surface = saveme;
530  } else {
532 
533  /* If the surface has a colorkey or alpha channel we'll save a
534  32-bit BMP with alpha channel, otherwise save a 24-bit BMP. */
535  if (save32bit) {
537  } else {
539  }
540  surface = SDL_ConvertSurface(saveme, &format, 0);
541  if (!surface) {
542  SDL_SetError("Couldn't convert image to %d bpp",
543  format.BitsPerPixel);
544  }
545  }
546  } else {
547  /* Set no error here because it may overwrite a more useful message from
548  SDL_RWFromFile() if SDL_SaveBMP_RW() is called from SDL_SaveBMP(). */
549  return -1;
550  }
551 
552  if (save32bit) {
554  }
555 
556  if (surface && (SDL_LockSurface(surface) == 0)) {
557  const int bw = surface->w * surface->format->BytesPerPixel;
558 
559  /* Set the BMP file header values */
560  bfSize = 0; /* We'll write this when we're done */
561  bfReserved1 = 0;
562  bfReserved2 = 0;
563  bfOffBits = 0; /* We'll write this when we're done */
564 
565  /* Write the BMP file header values */
566  fp_offset = SDL_RWtell(dst);
567  SDL_ClearError();
568  SDL_RWwrite(dst, magic, 2, 1);
569  SDL_WriteLE32(dst, bfSize);
570  SDL_WriteLE16(dst, bfReserved1);
571  SDL_WriteLE16(dst, bfReserved2);
572  SDL_WriteLE32(dst, bfOffBits);
573 
574  /* Set the BMP info values */
575  biSize = 40;
576  biWidth = surface->w;
577  biHeight = surface->h;
578  biPlanes = 1;
579  biBitCount = surface->format->BitsPerPixel;
580  biCompression = BI_RGB;
581  biSizeImage = surface->h * surface->pitch;
582  biXPelsPerMeter = 0;
583  biYPelsPerMeter = 0;
584  if (surface->format->palette) {
585  biClrUsed = surface->format->palette->ncolors;
586  } else {
587  biClrUsed = 0;
588  }
589  biClrImportant = 0;
590 
591  /* Set the BMP info values for the version 4 header */
592  if (save32bit && !saveLegacyBMP) {
593  biSize = 108;
594  biCompression = BI_BITFIELDS;
595  /* The BMP format is always little endian, these masks stay the same */
596  bV4RedMask = 0x00ff0000;
597  bV4GreenMask = 0x0000ff00;
598  bV4BlueMask = 0x000000ff;
599  bV4AlphaMask = 0xff000000;
600  bV4CSType = LCS_WINDOWS_COLOR_SPACE;
601  bV4GammaRed = 0;
602  bV4GammaGreen = 0;
603  bV4GammaBlue = 0;
604  }
605 
606  /* Write the BMP info values */
607  SDL_WriteLE32(dst, biSize);
608  SDL_WriteLE32(dst, biWidth);
609  SDL_WriteLE32(dst, biHeight);
610  SDL_WriteLE16(dst, biPlanes);
611  SDL_WriteLE16(dst, biBitCount);
612  SDL_WriteLE32(dst, biCompression);
613  SDL_WriteLE32(dst, biSizeImage);
614  SDL_WriteLE32(dst, biXPelsPerMeter);
615  SDL_WriteLE32(dst, biYPelsPerMeter);
616  SDL_WriteLE32(dst, biClrUsed);
617  SDL_WriteLE32(dst, biClrImportant);
618 
619  /* Write the BMP info values for the version 4 header */
620  if (save32bit && !saveLegacyBMP) {
621  SDL_WriteLE32(dst, bV4RedMask);
622  SDL_WriteLE32(dst, bV4GreenMask);
623  SDL_WriteLE32(dst, bV4BlueMask);
624  SDL_WriteLE32(dst, bV4AlphaMask);
625  SDL_WriteLE32(dst, bV4CSType);
626  for (i = 0; i < 3 * 3; i++) {
627  SDL_WriteLE32(dst, bV4Endpoints[i]);
628  }
629  SDL_WriteLE32(dst, bV4GammaRed);
630  SDL_WriteLE32(dst, bV4GammaGreen);
631  SDL_WriteLE32(dst, bV4GammaBlue);
632  }
633 
634  /* Write the palette (in BGR color order) */
635  if (surface->format->palette) {
636  SDL_Color *colors;
637  int ncolors;
638 
639  colors = surface->format->palette->colors;
640  ncolors = surface->format->palette->ncolors;
641  for (i = 0; i < ncolors; ++i) {
642  SDL_RWwrite(dst, &colors[i].b, 1, 1);
643  SDL_RWwrite(dst, &colors[i].g, 1, 1);
644  SDL_RWwrite(dst, &colors[i].r, 1, 1);
645  SDL_RWwrite(dst, &colors[i].a, 1, 1);
646  }
647  }
648 
649  /* Write the bitmap offset */
650  bfOffBits = (Uint32)(SDL_RWtell(dst) - fp_offset);
651  if (SDL_RWseek(dst, fp_offset + 10, RW_SEEK_SET) < 0) {
653  }
654  SDL_WriteLE32(dst, bfOffBits);
655  if (SDL_RWseek(dst, fp_offset + bfOffBits, RW_SEEK_SET) < 0) {
657  }
658 
659  /* Write the bitmap image upside down */
660  bits = (Uint8 *) surface->pixels + (surface->h * surface->pitch);
661  pad = ((bw % 4) ? (4 - (bw % 4)) : 0);
662  while (bits > (Uint8 *) surface->pixels) {
663  bits -= surface->pitch;
664  if (SDL_RWwrite(dst, bits, 1, bw) != bw) {
666  break;
667  }
668  if (pad) {
669  const Uint8 padbyte = 0;
670  for (i = 0; i < pad; ++i) {
671  SDL_RWwrite(dst, &padbyte, 1, 1);
672  }
673  }
674  }
675 
676  /* Write the BMP file size */
677  bfSize = (Uint32)(SDL_RWtell(dst) - fp_offset);
678  if (SDL_RWseek(dst, fp_offset + 2, RW_SEEK_SET) < 0) {
680  }
681  SDL_WriteLE32(dst, bfSize);
682  if (SDL_RWseek(dst, fp_offset + bfSize, RW_SEEK_SET) < 0) {
684  }
685 
686  /* Close it up.. */
687  SDL_UnlockSurface(surface);
688  if (surface != saveme) {
689  SDL_FreeSurface(surface);
690  }
691  }
692 
693  if (freedst && dst) {
694  SDL_RWclose(dst);
695  }
696  return ((SDL_strcmp(SDL_GetError(), "") == 0) ? 0 : -1);
697 }
#define BI_RGB
Definition: SDL_bmp.c:45
#define SDL_ClearError
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1565
#define SDL_GetError
#define SDL_UnlockSurface
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2072
#define SDL_COPY_COLORKEY
Definition: SDL_blit.h:39
#define LCS_WINDOWS_COLOR_SPACE
Definition: SDL_bmp.c:54
#define SDL_RWwrite(ctx, ptr, size, n)
Definition: SDL_rwops.h:188
Uint8 BytesPerPixel
Definition: SDL_pixels.h:318
#define SDL_ConvertSurface
A collection of pixels used in software blitting.
Definition: SDL_surface.h:69
#define SDL_WriteLE16
#define SDL_LIL_ENDIAN
Definition: SDL_endian.h:37
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:159
#define SDL_Error
#define SDL_GetHintBoolean
#define SDL_RWseek(ctx, offset, whence)
Definition: SDL_rwops.h:185
GLboolean GLboolean g
struct SDL_BlitMap * map
Definition: SDL_surface.h:88
void * pixels
Definition: SDL_surface.h:75
#define SDL_FreeSurface
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:143
Uint8 BitsPerPixel
Definition: SDL_pixels.h:317
#define SDL_HINT_BMP_SAVE_LEGACY_FORMAT
Prevent SDL from using version 4 of the bitmap header when saving BMPs.
Definition: SDL_hints.h:689
int32_t Sint32
A signed 32-bit integer type.
Definition: SDL_stdinc.h:155
int SDL_InitFormat(SDL_PixelFormat *format, Uint32 pixel_format)
Definition: SDL_pixels.c:521
#define BI_BITFIELDS
Definition: SDL_bmp.c:48
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
#define NULL
Definition: begin_code.h:143
SDL_bool
Definition: SDL_stdinc.h:130
SDL_Color * colors
Definition: SDL_pixels.h:305
SDL_PixelFormat * format
Definition: SDL_surface.h:72
#define SDL_RWclose(ctx)
Definition: SDL_rwops.h:189
#define SDL_SetError
#define SDL_LockSurface
#define SDL_WriteLE32
#define RW_SEEK_SET
Definition: SDL_rwops.h:174
uint16_t Uint16
An unsigned 16-bit integer type.
Definition: SDL_stdinc.h:151
SDL_Palette * palette
Definition: SDL_pixels.h:316
#define SDL_strcmp
int64_t Sint64
A signed 64-bit integer type.
Definition: SDL_stdinc.h:164
static int colors[7]
Definition: testgesture.c:40
GLboolean GLboolean GLboolean GLboolean a
GLboolean GLboolean GLboolean b
#define SDL_RWtell(ctx)
Definition: SDL_rwops.h:186
#define SDL_BYTEORDER
SDL_BlitInfo info
Definition: SDL_blit.h:91