SDL  2.0
SDL_bmp.c File Reference
#include "../SDL_internal.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
 

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

#define BI_BITFIELDS   3

Definition at line 47 of file SDL_bmp.c.

Referenced by SDL_LoadBMP_RW().

#define BI_RGB   0

Definition at line 44 of file SDL_bmp.c.

Referenced by SDL_LoadBMP_RW(), and SDL_SaveBMP_RW().

#define BI_RLE4   2

Definition at line 46 of file SDL_bmp.c.

#define BI_RLE8   1

Definition at line 45 of file SDL_bmp.c.

#define SAVE_32BIT_BMP

Definition at line 40 of file SDL_bmp.c.

Function Documentation

static void CorrectAlphaChannel ( SDL_Surface surface)
static

Definition at line 51 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().

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

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

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

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 454 of file SDL_bmp.c.

References SDL_PixelFormat::Amask, 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, 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_InitFormat(), SDL_LIL_ENDIAN, SDL_LockSurface, SDL_PIXELFORMAT_ARGB8888, SDL_PIXELFORMAT_BGR24, SDL_PIXELFORMAT_BGRA8888, SDL_RWclose, SDL_RWseek, SDL_RWtell, SDL_RWwrite, SDL_SetError, SDL_strcmp, SDL_TRUE, SDL_UnlockSurface, SDL_WriteLE16, SDL_WriteLE32, and SDL_Surface::w.

455 {
456  Sint64 fp_offset;
457  int i, pad;
458  SDL_Surface *surface;
459  Uint8 *bits;
460 
461  /* The Win32 BMP file header (14 bytes) */
462  char magic[2] = { 'B', 'M' };
463  Uint32 bfSize;
464  Uint16 bfReserved1;
465  Uint16 bfReserved2;
466  Uint32 bfOffBits;
467 
468  /* The Win32 BITMAPINFOHEADER struct (40 bytes) */
469  Uint32 biSize;
470  Sint32 biWidth;
471  Sint32 biHeight;
472  Uint16 biPlanes;
473  Uint16 biBitCount;
474  Uint32 biCompression;
475  Uint32 biSizeImage;
476  Sint32 biXPelsPerMeter;
477  Sint32 biYPelsPerMeter;
478  Uint32 biClrUsed;
479  Uint32 biClrImportant;
480 
481  /* Make sure we have somewhere to save */
482  surface = NULL;
483  if (dst) {
484  SDL_bool save32bit = SDL_FALSE;
485 #ifdef SAVE_32BIT_BMP
486  /* We can save alpha information in a 32-bit BMP */
487  if (saveme->map->info.flags & SDL_COPY_COLORKEY ||
488  saveme->format->Amask) {
489  save32bit = SDL_TRUE;
490  }
491 #endif /* SAVE_32BIT_BMP */
492 
493  if (saveme->format->palette && !save32bit) {
494  if (saveme->format->BitsPerPixel == 8) {
495  surface = saveme;
496  } else {
497  SDL_SetError("%d bpp BMP files not supported",
498  saveme->format->BitsPerPixel);
499  }
500  } else if ((saveme->format->BitsPerPixel == 24) &&
502  (saveme->format->Rmask == 0x00FF0000) &&
503  (saveme->format->Gmask == 0x0000FF00) &&
504  (saveme->format->Bmask == 0x000000FF)
505 #else
506  (saveme->format->Rmask == 0x000000FF) &&
507  (saveme->format->Gmask == 0x0000FF00) &&
508  (saveme->format->Bmask == 0x00FF0000)
509 #endif
510  ) {
511  surface = saveme;
512  } else {
514 
515  /* If the surface has a colorkey or alpha channel we'll save a
516  32-bit BMP with alpha channel, otherwise save a 24-bit BMP. */
517  if (save32bit) {
518  SDL_InitFormat(&format,
521 #else
523 #endif
524  );
525  } else {
527  }
528  surface = SDL_ConvertSurface(saveme, &format, 0);
529  if (!surface) {
530  SDL_SetError("Couldn't convert image to %d bpp",
531  format.BitsPerPixel);
532  }
533  }
534  } else {
535  /* Set no error here because it may overwrite a more useful message from
536  SDL_RWFromFile() if SDL_SaveBMP_RW() is called from SDL_SaveBMP(). */
537  return -1;
538  }
539 
540  if (surface && (SDL_LockSurface(surface) == 0)) {
541  const int bw = surface->w * surface->format->BytesPerPixel;
542 
543  /* Set the BMP file header values */
544  bfSize = 0; /* We'll write this when we're done */
545  bfReserved1 = 0;
546  bfReserved2 = 0;
547  bfOffBits = 0; /* We'll write this when we're done */
548 
549  /* Write the BMP file header values */
550  fp_offset = SDL_RWtell(dst);
551  SDL_ClearError();
552  SDL_RWwrite(dst, magic, 2, 1);
553  SDL_WriteLE32(dst, bfSize);
554  SDL_WriteLE16(dst, bfReserved1);
555  SDL_WriteLE16(dst, bfReserved2);
556  SDL_WriteLE32(dst, bfOffBits);
557 
558  /* Set the BMP info values */
559  biSize = 40;
560  biWidth = surface->w;
561  biHeight = surface->h;
562  biPlanes = 1;
563  biBitCount = surface->format->BitsPerPixel;
564  biCompression = BI_RGB;
565  biSizeImage = surface->h * surface->pitch;
566  biXPelsPerMeter = 0;
567  biYPelsPerMeter = 0;
568  if (surface->format->palette) {
569  biClrUsed = surface->format->palette->ncolors;
570  } else {
571  biClrUsed = 0;
572  }
573  biClrImportant = 0;
574 
575  /* Write the BMP info values */
576  SDL_WriteLE32(dst, biSize);
577  SDL_WriteLE32(dst, biWidth);
578  SDL_WriteLE32(dst, biHeight);
579  SDL_WriteLE16(dst, biPlanes);
580  SDL_WriteLE16(dst, biBitCount);
581  SDL_WriteLE32(dst, biCompression);
582  SDL_WriteLE32(dst, biSizeImage);
583  SDL_WriteLE32(dst, biXPelsPerMeter);
584  SDL_WriteLE32(dst, biYPelsPerMeter);
585  SDL_WriteLE32(dst, biClrUsed);
586  SDL_WriteLE32(dst, biClrImportant);
587 
588  /* Write the palette (in BGR color order) */
589  if (surface->format->palette) {
590  SDL_Color *colors;
591  int ncolors;
592 
593  colors = surface->format->palette->colors;
594  ncolors = surface->format->palette->ncolors;
595  for (i = 0; i < ncolors; ++i) {
596  SDL_RWwrite(dst, &colors[i].b, 1, 1);
597  SDL_RWwrite(dst, &colors[i].g, 1, 1);
598  SDL_RWwrite(dst, &colors[i].r, 1, 1);
599  SDL_RWwrite(dst, &colors[i].a, 1, 1);
600  }
601  }
602 
603  /* Write the bitmap offset */
604  bfOffBits = (Uint32)(SDL_RWtell(dst) - fp_offset);
605  if (SDL_RWseek(dst, fp_offset + 10, RW_SEEK_SET) < 0) {
607  }
608  SDL_WriteLE32(dst, bfOffBits);
609  if (SDL_RWseek(dst, fp_offset + bfOffBits, RW_SEEK_SET) < 0) {
611  }
612 
613  /* Write the bitmap image upside down */
614  bits = (Uint8 *) surface->pixels + (surface->h * surface->pitch);
615  pad = ((bw % 4) ? (4 - (bw % 4)) : 0);
616  while (bits > (Uint8 *) surface->pixels) {
617  bits -= surface->pitch;
618  if (SDL_RWwrite(dst, bits, 1, bw) != bw) {
620  break;
621  }
622  if (pad) {
623  const Uint8 padbyte = 0;
624  for (i = 0; i < pad; ++i) {
625  SDL_RWwrite(dst, &padbyte, 1, 1);
626  }
627  }
628  }
629 
630  /* Write the BMP file size */
631  bfSize = (Uint32)(SDL_RWtell(dst) - fp_offset);
632  if (SDL_RWseek(dst, fp_offset + 2, RW_SEEK_SET) < 0) {
634  }
635  SDL_WriteLE32(dst, bfSize);
636  if (SDL_RWseek(dst, fp_offset + bfSize, RW_SEEK_SET) < 0) {
638  }
639 
640  /* Close it up.. */
641  SDL_UnlockSurface(surface);
642  if (surface != saveme) {
643  SDL_FreeSurface(surface);
644  }
645  }
646 
647  if (freedst && dst) {
648  SDL_RWclose(dst);
649  }
650  return ((SDL_strcmp(SDL_GetError(), "") == 0) ? 0 : -1);
651 }
#define BI_RGB
Definition: SDL_bmp.c:44
#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
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:155
#define SDL_RWwrite(ctx, ptr, size, n)
Definition: SDL_rwops.h:188
Uint8 BytesPerPixel
Definition: SDL_pixels.h:304
#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
#define SDL_Error
#define SDL_RWseek(ctx, offset, whence)
Definition: SDL_rwops.h:185
SDL_bool
Definition: SDL_stdinc.h:126
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:139
Uint8 BitsPerPixel
Definition: SDL_pixels.h:303
int32_t Sint32
A signed 32-bit integer type.
Definition: SDL_stdinc.h:151
int SDL_InitFormat(SDL_PixelFormat *format, Uint32 pixel_format)
Definition: SDL_pixels.c:521
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:42
#define NULL
Definition: begin_code.h:143
SDL_Color * colors
Definition: SDL_pixels.h:291
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:147
SDL_Palette * palette
Definition: SDL_pixels.h:302
#define SDL_strcmp
int64_t Sint64
A signed 64-bit integer type.
Definition: SDL_stdinc.h:160
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