cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_bmp.c (20964B)


      1/*
      2  Simple DirectMedia Layer
      3  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
      4
      5  This software is provided 'as-is', without any express or implied
      6  warranty.  In no event will the authors be held liable for any damages
      7  arising from the use of this software.
      8
      9  Permission is granted to anyone to use this software for any purpose,
     10  including commercial applications, and to alter it and redistribute it
     11  freely, subject to the following restrictions:
     12
     13  1. The origin of this software must not be misrepresented; you must not
     14     claim that you wrote the original software. If you use this software
     15     in a product, an acknowledgment in the product documentation would be
     16     appreciated but is not required.
     17  2. Altered source versions must be plainly marked as such, and must not be
     18     misrepresented as being the original software.
     19  3. This notice may not be removed or altered from any source distribution.
     20*/
     21#include "../SDL_internal.h"
     22
     23/*
     24   Code to load and save surfaces in Windows BMP format.
     25
     26   Why support BMP format?  Well, it's a native format for Windows, and
     27   most image processing programs can read and write it.  It would be nice
     28   to be able to have at least one image format that we can natively load
     29   and save, and since PNG is so complex that it would bloat the library,
     30   BMP is a good alternative.
     31
     32   This code currently supports Win32 DIBs in uncompressed 8 and 24 bpp.
     33*/
     34
     35#include "SDL_video.h"
     36#include "SDL_assert.h"
     37#include "SDL_endian.h"
     38#include "SDL_pixels_c.h"
     39
     40#define SAVE_32BIT_BMP
     41
     42/* Compression encodings for BMP files */
     43#ifndef BI_RGB
     44#define BI_RGB      0
     45#define BI_RLE8     1
     46#define BI_RLE4     2
     47#define BI_BITFIELDS    3
     48#endif
     49
     50
     51static void CorrectAlphaChannel(SDL_Surface *surface)
     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}
     79
     80SDL_Surface *
     81SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
     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) {
    133        SDL_Error(SDL_EFREAD);
    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            palette->ncolors = biClrUsed;
    310            palette->colors =
    311                (SDL_Color *) SDL_realloc(palette->colors,
    312                                          palette->ncolors *
    313                                          sizeof(*palette->colors));
    314            if (!palette->colors) {
    315                SDL_OutOfMemory();
    316                was_error = SDL_TRUE;
    317                goto done;
    318            }
    319        } else if ((int) biClrUsed < palette->ncolors) {
    320            palette->ncolors = biClrUsed;
    321        }
    322        if (biSize == 12) {
    323            for (i = 0; i < (int) biClrUsed; ++i) {
    324                SDL_RWread(src, &palette->colors[i].b, 1, 1);
    325                SDL_RWread(src, &palette->colors[i].g, 1, 1);
    326                SDL_RWread(src, &palette->colors[i].r, 1, 1);
    327                palette->colors[i].a = SDL_ALPHA_OPAQUE;
    328            }
    329        } else {
    330            for (i = 0; i < (int) biClrUsed; ++i) {
    331                SDL_RWread(src, &palette->colors[i].b, 1, 1);
    332                SDL_RWread(src, &palette->colors[i].g, 1, 1);
    333                SDL_RWread(src, &palette->colors[i].r, 1, 1);
    334                SDL_RWread(src, &palette->colors[i].a, 1, 1);
    335
    336                /* According to Microsoft documentation, the fourth element
    337                   is reserved and must be zero, so we shouldn't treat it as
    338                   alpha.
    339                */
    340                palette->colors[i].a = SDL_ALPHA_OPAQUE;
    341            }
    342        }
    343    }
    344
    345    /* Read the surface pixels.  Note that the bmp image is upside down */
    346    if (SDL_RWseek(src, fp_offset + bfOffBits, RW_SEEK_SET) < 0) {
    347        SDL_Error(SDL_EFSEEK);
    348        was_error = SDL_TRUE;
    349        goto done;
    350    }
    351    top = (Uint8 *)surface->pixels;
    352    end = (Uint8 *)surface->pixels+(surface->h*surface->pitch);
    353    switch (ExpandBMP) {
    354    case 1:
    355        bmpPitch = (biWidth + 7) >> 3;
    356        pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0);
    357        break;
    358    case 4:
    359        bmpPitch = (biWidth + 1) >> 1;
    360        pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0);
    361        break;
    362    default:
    363        pad = ((surface->pitch % 4) ? (4 - (surface->pitch % 4)) : 0);
    364        break;
    365    }
    366    if (topDown) {
    367        bits = top;
    368    } else {
    369        bits = end - surface->pitch;
    370    }
    371    while (bits >= top && bits < end) {
    372        switch (ExpandBMP) {
    373        case 1:
    374        case 4:{
    375                Uint8 pixel = 0;
    376                int shift = (8 - ExpandBMP);
    377                for (i = 0; i < surface->w; ++i) {
    378                    if (i % (8 / ExpandBMP) == 0) {
    379                        if (!SDL_RWread(src, &pixel, 1, 1)) {
    380                            SDL_SetError("Error reading from BMP");
    381                            was_error = SDL_TRUE;
    382                            goto done;
    383                        }
    384                    }
    385                    *(bits + i) = (pixel >> shift);
    386                    pixel <<= ExpandBMP;
    387                }
    388            }
    389            break;
    390
    391        default:
    392            if (SDL_RWread(src, bits, 1, surface->pitch)
    393                != surface->pitch) {
    394                SDL_Error(SDL_EFREAD);
    395                was_error = SDL_TRUE;
    396                goto done;
    397            }
    398#if SDL_BYTEORDER == SDL_BIG_ENDIAN
    399            /* Byte-swap the pixels if needed. Note that the 24bpp
    400               case has already been taken care of above. */
    401            switch (biBitCount) {
    402            case 15:
    403            case 16:{
    404                    Uint16 *pix = (Uint16 *) bits;
    405                    for (i = 0; i < surface->w; i++)
    406                        pix[i] = SDL_Swap16(pix[i]);
    407                    break;
    408                }
    409
    410            case 32:{
    411                    Uint32 *pix = (Uint32 *) bits;
    412                    for (i = 0; i < surface->w; i++)
    413                        pix[i] = SDL_Swap32(pix[i]);
    414                    break;
    415                }
    416            }
    417#endif
    418            break;
    419        }
    420        /* Skip padding bytes, ugh */
    421        if (pad) {
    422            Uint8 padbyte;
    423            for (i = 0; i < pad; ++i) {
    424                SDL_RWread(src, &padbyte, 1, 1);
    425            }
    426        }
    427        if (topDown) {
    428            bits += surface->pitch;
    429        } else {
    430            bits -= surface->pitch;
    431        }
    432    }
    433    if (correctAlpha) {
    434        CorrectAlphaChannel(surface);
    435    }
    436  done:
    437    if (was_error) {
    438        if (src) {
    439            SDL_RWseek(src, fp_offset, RW_SEEK_SET);
    440        }
    441        SDL_FreeSurface(surface);
    442        surface = NULL;
    443    }
    444    if (freesrc && src) {
    445        SDL_RWclose(src);
    446    }
    447    return (surface);
    448}
    449
    450int
    451SDL_SaveBMP_RW(SDL_Surface * saveme, SDL_RWops * dst, int freedst)
    452{
    453    Sint64 fp_offset;
    454    int i, pad;
    455    SDL_Surface *surface;
    456    Uint8 *bits;
    457
    458    /* The Win32 BMP file header (14 bytes) */
    459    char magic[2] = { 'B', 'M' };
    460    Uint32 bfSize;
    461    Uint16 bfReserved1;
    462    Uint16 bfReserved2;
    463    Uint32 bfOffBits;
    464
    465    /* The Win32 BITMAPINFOHEADER struct (40 bytes) */
    466    Uint32 biSize;
    467    Sint32 biWidth;
    468    Sint32 biHeight;
    469    Uint16 biPlanes;
    470    Uint16 biBitCount;
    471    Uint32 biCompression;
    472    Uint32 biSizeImage;
    473    Sint32 biXPelsPerMeter;
    474    Sint32 biYPelsPerMeter;
    475    Uint32 biClrUsed;
    476    Uint32 biClrImportant;
    477
    478    /* Make sure we have somewhere to save */
    479    surface = NULL;
    480    if (dst) {
    481        SDL_bool save32bit = SDL_FALSE;
    482#ifdef SAVE_32BIT_BMP
    483        /* We can save alpha information in a 32-bit BMP */
    484        if (saveme->map->info.flags & SDL_COPY_COLORKEY ||
    485            saveme->format->Amask) {
    486            save32bit = SDL_TRUE;
    487        }
    488#endif /* SAVE_32BIT_BMP */
    489
    490        if (saveme->format->palette && !save32bit) {
    491            if (saveme->format->BitsPerPixel == 8) {
    492                surface = saveme;
    493            } else {
    494                SDL_SetError("%d bpp BMP files not supported",
    495                             saveme->format->BitsPerPixel);
    496            }
    497        } else if ((saveme->format->BitsPerPixel == 24) &&
    498#if SDL_BYTEORDER == SDL_LIL_ENDIAN
    499                   (saveme->format->Rmask == 0x00FF0000) &&
    500                   (saveme->format->Gmask == 0x0000FF00) &&
    501                   (saveme->format->Bmask == 0x000000FF)
    502#else
    503                   (saveme->format->Rmask == 0x000000FF) &&
    504                   (saveme->format->Gmask == 0x0000FF00) &&
    505                   (saveme->format->Bmask == 0x00FF0000)
    506#endif
    507            ) {
    508            surface = saveme;
    509        } else {
    510            SDL_PixelFormat format;
    511
    512            /* If the surface has a colorkey or alpha channel we'll save a
    513               32-bit BMP with alpha channel, otherwise save a 24-bit BMP. */
    514            if (save32bit) {
    515                SDL_InitFormat(&format,
    516#if SDL_BYTEORDER == SDL_LIL_ENDIAN
    517                               SDL_PIXELFORMAT_ARGB8888
    518#else
    519                               SDL_PIXELFORMAT_BGRA8888
    520#endif
    521                               );
    522            } else {
    523                SDL_InitFormat(&format, SDL_PIXELFORMAT_BGR24);
    524            }
    525            surface = SDL_ConvertSurface(saveme, &format, 0);
    526            if (!surface) {
    527                SDL_SetError("Couldn't convert image to %d bpp",
    528                             format.BitsPerPixel);
    529            }
    530        }
    531    }
    532
    533    if (surface && (SDL_LockSurface(surface) == 0)) {
    534        const int bw = surface->w * surface->format->BytesPerPixel;
    535
    536        /* Set the BMP file header values */
    537        bfSize = 0;             /* We'll write this when we're done */
    538        bfReserved1 = 0;
    539        bfReserved2 = 0;
    540        bfOffBits = 0;          /* We'll write this when we're done */
    541
    542        /* Write the BMP file header values */
    543        fp_offset = SDL_RWtell(dst);
    544        SDL_ClearError();
    545        SDL_RWwrite(dst, magic, 2, 1);
    546        SDL_WriteLE32(dst, bfSize);
    547        SDL_WriteLE16(dst, bfReserved1);
    548        SDL_WriteLE16(dst, bfReserved2);
    549        SDL_WriteLE32(dst, bfOffBits);
    550
    551        /* Set the BMP info values */
    552        biSize = 40;
    553        biWidth = surface->w;
    554        biHeight = surface->h;
    555        biPlanes = 1;
    556        biBitCount = surface->format->BitsPerPixel;
    557        biCompression = BI_RGB;
    558        biSizeImage = surface->h * surface->pitch;
    559        biXPelsPerMeter = 0;
    560        biYPelsPerMeter = 0;
    561        if (surface->format->palette) {
    562            biClrUsed = surface->format->palette->ncolors;
    563        } else {
    564            biClrUsed = 0;
    565        }
    566        biClrImportant = 0;
    567
    568        /* Write the BMP info values */
    569        SDL_WriteLE32(dst, biSize);
    570        SDL_WriteLE32(dst, biWidth);
    571        SDL_WriteLE32(dst, biHeight);
    572        SDL_WriteLE16(dst, biPlanes);
    573        SDL_WriteLE16(dst, biBitCount);
    574        SDL_WriteLE32(dst, biCompression);
    575        SDL_WriteLE32(dst, biSizeImage);
    576        SDL_WriteLE32(dst, biXPelsPerMeter);
    577        SDL_WriteLE32(dst, biYPelsPerMeter);
    578        SDL_WriteLE32(dst, biClrUsed);
    579        SDL_WriteLE32(dst, biClrImportant);
    580
    581        /* Write the palette (in BGR color order) */
    582        if (surface->format->palette) {
    583            SDL_Color *colors;
    584            int ncolors;
    585
    586            colors = surface->format->palette->colors;
    587            ncolors = surface->format->palette->ncolors;
    588            for (i = 0; i < ncolors; ++i) {
    589                SDL_RWwrite(dst, &colors[i].b, 1, 1);
    590                SDL_RWwrite(dst, &colors[i].g, 1, 1);
    591                SDL_RWwrite(dst, &colors[i].r, 1, 1);
    592                SDL_RWwrite(dst, &colors[i].a, 1, 1);
    593            }
    594        }
    595
    596        /* Write the bitmap offset */
    597        bfOffBits = (Uint32)(SDL_RWtell(dst) - fp_offset);
    598        if (SDL_RWseek(dst, fp_offset + 10, RW_SEEK_SET) < 0) {
    599            SDL_Error(SDL_EFSEEK);
    600        }
    601        SDL_WriteLE32(dst, bfOffBits);
    602        if (SDL_RWseek(dst, fp_offset + bfOffBits, RW_SEEK_SET) < 0) {
    603            SDL_Error(SDL_EFSEEK);
    604        }
    605
    606        /* Write the bitmap image upside down */
    607        bits = (Uint8 *) surface->pixels + (surface->h * surface->pitch);
    608        pad = ((bw % 4) ? (4 - (bw % 4)) : 0);
    609        while (bits > (Uint8 *) surface->pixels) {
    610            bits -= surface->pitch;
    611            if (SDL_RWwrite(dst, bits, 1, bw) != bw) {
    612                SDL_Error(SDL_EFWRITE);
    613                break;
    614            }
    615            if (pad) {
    616                const Uint8 padbyte = 0;
    617                for (i = 0; i < pad; ++i) {
    618                    SDL_RWwrite(dst, &padbyte, 1, 1);
    619                }
    620            }
    621        }
    622
    623        /* Write the BMP file size */
    624        bfSize = (Uint32)(SDL_RWtell(dst) - fp_offset);
    625        if (SDL_RWseek(dst, fp_offset + 2, RW_SEEK_SET) < 0) {
    626            SDL_Error(SDL_EFSEEK);
    627        }
    628        SDL_WriteLE32(dst, bfSize);
    629        if (SDL_RWseek(dst, fp_offset + bfSize, RW_SEEK_SET) < 0) {
    630            SDL_Error(SDL_EFSEEK);
    631        }
    632
    633        /* Close it up.. */
    634        SDL_UnlockSurface(surface);
    635        if (surface != saveme) {
    636            SDL_FreeSurface(surface);
    637        }
    638    }
    639
    640    if (freedst && dst) {
    641        SDL_RWclose(dst);
    642    }
    643    return ((SDL_strcmp(SDL_GetError(), "") == 0) ? 0 : -1);
    644}
    645
    646/* vi: set ts=4 sw=4 expandtab: */