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.

◆ BI_RGB

#define BI_RGB   0

Definition at line 45 of file SDL_bmp.c.

◆ 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.

◆ 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.

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) {
81  alpha += 4;
82  }
83  }
84 }

References SDL_ALPHA_OPAQUE, SDL_FALSE, and SDL_TRUE.

Referenced by SDL_LoadBMP_RW().

◆ 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.

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

References SDL_Color::a, SDL_Color::b, BI_BITFIELDS, BI_RGB, SDL_Palette::colors, colors, CorrectAlphaChannel(), done, SDL_Color::g, i, SDL_Palette::ncolors, NULL, 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 void.

◆ 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.

464 {
465  Sint64 fp_offset;
466  int i, pad;
468  Uint8 *bits;
469  SDL_bool save32bit = SDL_FALSE;
470  SDL_bool saveLegacyBMP = SDL_FALSE;
471 
472  /* The Win32 BMP file header (14 bytes) */
473  char magic[2] = { 'B', 'M' };
474  Uint32 bfSize;
475  Uint16 bfReserved1;
476  Uint16 bfReserved2;
477  Uint32 bfOffBits;
478 
479  /* The Win32 BITMAPINFOHEADER struct (40 bytes) */
480  Uint32 biSize;
481  Sint32 biWidth;
482  Sint32 biHeight;
483  Uint16 biPlanes;
484  Uint16 biBitCount;
485  Uint32 biCompression;
486  Uint32 biSizeImage;
487  Sint32 biXPelsPerMeter;
488  Sint32 biYPelsPerMeter;
489  Uint32 biClrUsed;
490  Uint32 biClrImportant;
491 
492  /* The additional header members from the Win32 BITMAPV4HEADER struct (108 bytes in total) */
493  Uint32 bV4RedMask = 0;
494  Uint32 bV4GreenMask = 0;
495  Uint32 bV4BlueMask = 0;
496  Uint32 bV4AlphaMask = 0;
497  Uint32 bV4CSType = 0;
498  Sint32 bV4Endpoints[3 * 3] = {0};
499  Uint32 bV4GammaRed = 0;
500  Uint32 bV4GammaGreen = 0;
501  Uint32 bV4GammaBlue = 0;
502 
503  /* Make sure we have somewhere to save */
504  surface = NULL;
505  if (dst) {
506 #ifdef SAVE_32BIT_BMP
507  /* We can save alpha information in a 32-bit BMP */
508  if (saveme->format->BitsPerPixel >= 8 && (saveme->format->Amask ||
509  saveme->map->info.flags & SDL_COPY_COLORKEY)) {
510  save32bit = SDL_TRUE;
511  }
512 #endif /* SAVE_32BIT_BMP */
513 
514  if (saveme->format->palette && !save32bit) {
515  if (saveme->format->BitsPerPixel == 8) {
516  surface = saveme;
517  } else {
518  SDL_SetError("%d bpp BMP files not supported",
519  saveme->format->BitsPerPixel);
520  }
521  } else if ((saveme->format->BitsPerPixel == 24) && !save32bit &&
523  (saveme->format->Rmask == 0x00FF0000) &&
524  (saveme->format->Gmask == 0x0000FF00) &&
525  (saveme->format->Bmask == 0x000000FF)
526 #else
527  (saveme->format->Rmask == 0x000000FF) &&
528  (saveme->format->Gmask == 0x0000FF00) &&
529  (saveme->format->Bmask == 0x00FF0000)
530 #endif
531  ) {
532  surface = saveme;
533  } else {
535 
536  /* If the surface has a colorkey or alpha channel we'll save a
537  32-bit BMP with alpha channel, otherwise save a 24-bit BMP. */
538  if (save32bit) {
540  } else {
542  }
543  surface = SDL_ConvertSurface(saveme, &format, 0);
544  if (!surface) {
545  SDL_SetError("Couldn't convert image to %d bpp",
546  format.BitsPerPixel);
547  }
548  }
549  } else {
550  /* Set no error here because it may overwrite a more useful message from
551  SDL_RWFromFile() if SDL_SaveBMP_RW() is called from SDL_SaveBMP(). */
552  return -1;
553  }
554 
555  if (save32bit) {
557  }
558 
559  if (surface && (SDL_LockSurface(surface) == 0)) {
560  const int bw = surface->w * surface->format->BytesPerPixel;
561 
562  /* Set the BMP file header values */
563  bfSize = 0; /* We'll write this when we're done */
564  bfReserved1 = 0;
565  bfReserved2 = 0;
566  bfOffBits = 0; /* We'll write this when we're done */
567 
568  /* Write the BMP file header values */
569  fp_offset = SDL_RWtell(dst);
570  SDL_ClearError();
571  SDL_RWwrite(dst, magic, 2, 1);
572  SDL_WriteLE32(dst, bfSize);
573  SDL_WriteLE16(dst, bfReserved1);
574  SDL_WriteLE16(dst, bfReserved2);
575  SDL_WriteLE32(dst, bfOffBits);
576 
577  /* Set the BMP info values */
578  biSize = 40;
579  biWidth = surface->w;
580  biHeight = surface->h;
581  biPlanes = 1;
582  biBitCount = surface->format->BitsPerPixel;
583  biCompression = BI_RGB;
584  biSizeImage = surface->h * surface->pitch;
585  biXPelsPerMeter = 0;
586  biYPelsPerMeter = 0;
587  if (surface->format->palette) {
588  biClrUsed = surface->format->palette->ncolors;
589  } else {
590  biClrUsed = 0;
591  }
592  biClrImportant = 0;
593 
594  /* Set the BMP info values for the version 4 header */
595  if (save32bit && !saveLegacyBMP) {
596  biSize = 108;
597  biCompression = BI_BITFIELDS;
598  /* The BMP format is always little endian, these masks stay the same */
599  bV4RedMask = 0x00ff0000;
600  bV4GreenMask = 0x0000ff00;
601  bV4BlueMask = 0x000000ff;
602  bV4AlphaMask = 0xff000000;
603  bV4CSType = LCS_WINDOWS_COLOR_SPACE;
604  bV4GammaRed = 0;
605  bV4GammaGreen = 0;
606  bV4GammaBlue = 0;
607  }
608 
609  /* Write the BMP info values */
610  SDL_WriteLE32(dst, biSize);
611  SDL_WriteLE32(dst, biWidth);
612  SDL_WriteLE32(dst, biHeight);
613  SDL_WriteLE16(dst, biPlanes);
614  SDL_WriteLE16(dst, biBitCount);
615  SDL_WriteLE32(dst, biCompression);
616  SDL_WriteLE32(dst, biSizeImage);
617  SDL_WriteLE32(dst, biXPelsPerMeter);
618  SDL_WriteLE32(dst, biYPelsPerMeter);
619  SDL_WriteLE32(dst, biClrUsed);
620  SDL_WriteLE32(dst, biClrImportant);
621 
622  /* Write the BMP info values for the version 4 header */
623  if (save32bit && !saveLegacyBMP) {
624  SDL_WriteLE32(dst, bV4RedMask);
625  SDL_WriteLE32(dst, bV4GreenMask);
626  SDL_WriteLE32(dst, bV4BlueMask);
627  SDL_WriteLE32(dst, bV4AlphaMask);
628  SDL_WriteLE32(dst, bV4CSType);
629  for (i = 0; i < 3 * 3; i++) {
630  SDL_WriteLE32(dst, bV4Endpoints[i]);
631  }
632  SDL_WriteLE32(dst, bV4GammaRed);
633  SDL_WriteLE32(dst, bV4GammaGreen);
634  SDL_WriteLE32(dst, bV4GammaBlue);
635  }
636 
637  /* Write the palette (in BGR color order) */
638  if (surface->format->palette) {
639  SDL_Color *colors;
640  int ncolors;
641 
642  colors = surface->format->palette->colors;
643  ncolors = surface->format->palette->ncolors;
644  for (i = 0; i < ncolors; ++i) {
645  SDL_RWwrite(dst, &colors[i].b, 1, 1);
646  SDL_RWwrite(dst, &colors[i].g, 1, 1);
647  SDL_RWwrite(dst, &colors[i].r, 1, 1);
648  SDL_RWwrite(dst, &colors[i].a, 1, 1);
649  }
650  }
651 
652  /* Write the bitmap offset */
653  bfOffBits = (Uint32)(SDL_RWtell(dst) - fp_offset);
654  if (SDL_RWseek(dst, fp_offset + 10, RW_SEEK_SET) < 0) {
656  }
657  SDL_WriteLE32(dst, bfOffBits);
658  if (SDL_RWseek(dst, fp_offset + bfOffBits, RW_SEEK_SET) < 0) {
660  }
661 
662  /* Write the bitmap image upside down */
663  bits = (Uint8 *) surface->pixels + (surface->h * surface->pitch);
664  pad = ((bw % 4) ? (4 - (bw % 4)) : 0);
665  while (bits > (Uint8 *) surface->pixels) {
666  bits -= surface->pitch;
667  if (SDL_RWwrite(dst, bits, 1, bw) != bw) {
669  break;
670  }
671  if (pad) {
672  const Uint8 padbyte = 0;
673  for (i = 0; i < pad; ++i) {
674  SDL_RWwrite(dst, &padbyte, 1, 1);
675  }
676  }
677  }
678 
679  /* Write the BMP file size */
680  bfSize = (Uint32)(SDL_RWtell(dst) - fp_offset);
681  if (SDL_RWseek(dst, fp_offset + 2, RW_SEEK_SET) < 0) {
683  }
684  SDL_WriteLE32(dst, bfSize);
685  if (SDL_RWseek(dst, fp_offset + bfSize, RW_SEEK_SET) < 0) {
687  }
688 
689  /* Close it up.. */
691  if (surface != saveme) {
693  }
694  }
695 
696  if (freedst && dst) {
697  SDL_RWclose(dst);
698  }
699  return ((SDL_strcmp(SDL_GetError(), "") == 0) ? 0 : -1);
700 }

References SDL_PixelFormat::Amask, BI_BITFIELDS, BI_RGB, SDL_PixelFormat::BitsPerPixel, SDL_PixelFormat::Bmask, colors, SDL_BlitInfo::flags, SDL_Surface::format, SDL_PixelFormat::Gmask, i, SDL_BlitMap::info, LCS_WINDOWS_COLOR_SPACE, SDL_Surface::map, NULL, SDL_PixelFormat::palette, 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, and SDL_WriteLE32.

SDL_UnlockSurface
#define SDL_UnlockSurface
Definition: SDL_dynapi_overrides.h:449
format
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:179
SDL_GetError
#define SDL_GetError
Definition: SDL_dynapi_overrides.h:113
Sint32
int32_t Sint32
Definition: SDL_stdinc.h:197
SDL_PixelFormat::BitsPerPixel
Uint8 BitsPerPixel
Definition: SDL_pixels.h:319
SDL_RWwrite
#define SDL_RWwrite(ctx, ptr, size, n)
Definition: SDL_rwops.h:188
Uint16
uint16_t Uint16
Definition: SDL_stdinc.h:191
SDL_Palette::ncolors
int ncolors
Definition: SDL_pixels.h:306
SDL_Color::b
Uint8 b
Definition: SDL_pixels.h:299
SDL_Surface
A collection of pixels used in software blitting.
Definition: SDL_surface.h:70
SDL_ClearError
#define SDL_ClearError
Definition: SDL_dynapi_overrides.h:114
end
GLuint GLuint end
Definition: SDL_opengl.h:1571
NULL
#define NULL
Definition: begin_code.h:164
surface
EGLSurface surface
Definition: eglext.h:248
SDL_ALPHA_OPAQUE
#define SDL_ALPHA_OPAQUE
Definition: SDL_pixels.h:46
b
GLboolean GLboolean GLboolean b
Definition: SDL_opengl_glext.h:1109
SDL_PIXELFORMAT_BGR24
@ SDL_PIXELFORMAT_BGR24
Definition: SDL_pixels.h:233
SDL_Swap16
SDL_FORCE_INLINE Uint16 SDL_Swap16(Uint16 x)
Definition: SDL_endian.h:107
g
GLboolean GLboolean g
Definition: SDL_opengl_glext.h:1109
SDL_WriteLE16
#define SDL_WriteLE16
Definition: SDL_dynapi_overrides.h:364
SDL_Color::r
Uint8 r
Definition: SDL_pixels.h:297
r
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2079
SDL_ConvertSurface
#define SDL_ConvertSurface
Definition: SDL_dynapi_overrides.h:463
SDL_realloc
#define SDL_realloc
Definition: SDL_dynapi_overrides.h:376
top
GLdouble GLdouble GLdouble GLdouble top
Definition: SDL_opengl_glext.h:6103
SDL_COPY_COLORKEY
#define SDL_COPY_COLORKEY
Definition: SDL_blit.h:39
SDL_PIXELFORMAT_BGRA32
@ SDL_PIXELFORMAT_BGRA32
Definition: SDL_pixels.h:273
Uint32
uint32_t Uint32
Definition: SDL_stdinc.h:203
SDL_BlitMap::info
SDL_BlitInfo info
Definition: SDL_blit.h:92
SDL_strncmp
#define SDL_strncmp
Definition: SDL_dynapi_overrides.h:418
SDL_PixelFormat::Rmask
Uint32 Rmask
Definition: SDL_pixels.h:322
a
GLboolean GLboolean GLboolean GLboolean a
Definition: SDL_opengl_glext.h:1109
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_RWseek
#define SDL_RWseek(ctx, offset, whence)
Definition: SDL_rwops.h:185
SDL_Color::a
Uint8 a
Definition: SDL_pixels.h:300
alpha
GLfloat GLfloat GLfloat alpha
Definition: SDL_opengl_glext.h:412
dst
GLenum GLenum dst
Definition: SDL_opengl_glext.h:1737
SDL_Error
#define SDL_Error
Definition: SDL_dynapi_overrides.h:115
SDL_LIL_ENDIAN
#define SDL_LIL_ENDIAN
Definition: SDL_endian.h:37
SDL_GetHintBoolean
#define SDL_GetHintBoolean
Definition: SDL_dynapi_overrides.h:608
done
int done
Definition: checkkeys.c:28
SDL_ReadLE16
#define SDL_ReadLE16
Definition: SDL_dynapi_overrides.h:357
SDL_Palette::colors
SDL_Color * colors
Definition: SDL_pixels.h:307
SDL_Color::g
Uint8 g
Definition: SDL_pixels.h:298
SDL_FreeSurface
#define SDL_FreeSurface
Definition: SDL_dynapi_overrides.h:446
SDL_PixelFormat::palette
SDL_Palette * palette
Definition: SDL_pixels.h:318
SDL_Swap32
SDL_FORCE_INLINE Uint32 SDL_Swap32(Uint32 x)
Definition: SDL_endian.h:162
LCS_WINDOWS_COLOR_SPACE
#define LCS_WINDOWS_COLOR_SPACE
Definition: SDL_bmp.c:54
SDL_PixelFormat::Amask
Uint32 Amask
Definition: SDL_pixels.h:325
SDL_Surface::map
struct SDL_BlitMap * map
Definition: SDL_surface.h:88
SDL_TRUE
@ SDL_TRUE
Definition: SDL_stdinc.h:164
SDL_PixelFormat
Definition: SDL_pixels.h:316
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:932
SDL_PixelFormat::Gmask
Uint32 Gmask
Definition: SDL_pixels.h:323
SDL_assert
#define SDL_assert(condition)
Definition: SDL_assert.h:169
CorrectAlphaChannel
static void CorrectAlphaChannel(SDL_Surface *surface)
Definition: SDL_bmp.c:57
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
BI_RGB
#define BI_RGB
Definition: SDL_bmp.c:45
SDL_LockSurface
#define SDL_LockSurface
Definition: SDL_dynapi_overrides.h:448
SDL_CreateRGBSurface
#define SDL_CreateRGBSurface
Definition: SDL_dynapi_overrides.h:444
SDL_RWclose
#define SDL_RWclose(ctx)
Definition: SDL_rwops.h:189
SDL_PixelFormat::Bmask
Uint32 Bmask
Definition: SDL_pixels.h:324
SDL_Palette
Definition: SDL_pixels.h:305
src
GLenum src
Definition: SDL_opengl_glext.h:1737
Sint64
int64_t Sint64
Definition: SDL_stdinc.h:210
RW_SEEK_SET
#define RW_SEEK_SET
Definition: SDL_rwops.h:174
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
RW_SEEK_CUR
#define RW_SEEK_CUR
Definition: SDL_rwops.h:175
SDL_Color
Definition: SDL_pixels.h:296
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:162
SDL_BlitInfo::flags
int flags
Definition: SDL_blit.h:68
SDL_WriteLE32
#define SDL_WriteLE32
Definition: SDL_dynapi_overrides.h:366
bits
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
Definition: SDL_opengl_glext.h:6176
SDL_FALSE
@ SDL_FALSE
Definition: SDL_stdinc.h:163
SDL_EFSEEK
@ SDL_EFSEEK
Definition: SDL_error.h:60
SDL_strcmp
#define SDL_strcmp
Definition: SDL_dynapi_overrides.h:417
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_BYTEORDER
#define SDL_BYTEORDER
Definition: SDL_config_pandora.h:37
BI_BITFIELDS
#define BI_BITFIELDS
Definition: SDL_bmp.c:48
SDL_Surface::format
SDL_PixelFormat * format
Definition: SDL_surface.h:72
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_EFWRITE
@ SDL_EFWRITE
Definition: SDL_error.h:59
SDL_RWtell
#define SDL_RWtell(ctx)
Definition: SDL_rwops.h:186
SDL_EFREAD
@ SDL_EFREAD
Definition: SDL_error.h:58
colors
static int colors[7]
Definition: testgesture.c:39
SDL_InitFormat
int SDL_InitFormat(SDL_PixelFormat *format, Uint32 pixel_format)
Definition: SDL_pixels.c:537