SDL_bmp.c revision 46be48730333120a7b939116cef075e61c12c703
146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* 246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL - Simple DirectMedia Layer 346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Copyright (C) 1997-2006 Sam Lantinga 446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner This library is free software; you can redistribute it and/or 646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner modify it under the terms of the GNU Lesser General Public 746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner License as published by the Free Software Foundation; either 846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner version 2.1 of the License, or (at your option) any later version. 946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 1046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner This library is distributed in the hope that it will be useful, 1146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner but WITHOUT ANY WARRANTY; without even the implied warranty of 1246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Lesser General Public License for more details. 1446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 1546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner You should have received a copy of the GNU Lesser General Public 1646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner License along with this library; if not, write to the Free Software 1746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 1846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 1946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Sam Lantinga 2046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner slouken@libsdl.org 2146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/ 2246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_config.h" 2346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 2446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* 2546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Code to load and save surfaces in Windows BMP format. 2646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 2746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Why support BMP format? Well, it's a native format for Windows, and 2846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner most image processing programs can read and write it. It would be nice 2946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner to be able to have at least one image format that we can natively load 3046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner and save, and since PNG is so complex that it would bloat the library, 3146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner BMP is a good alternative. 3246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 3346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner This code currently supports Win32 DIBs in uncompressed 8 and 24 bpp. 3446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/ 3546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 3646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_video.h" 3746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_endian.h" 3846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 3946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Compression encodings for BMP files */ 4046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef BI_RGB 4146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define BI_RGB 0 4246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define BI_RLE8 1 4346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define BI_RLE4 2 4446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define BI_BITFIELDS 3 4546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 4646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 4746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 4846be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerSDL_Surface * SDL_LoadBMP_RW (SDL_RWops *src, int freesrc) 4946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 5046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int was_error; 5146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner long fp_offset; 5246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int bmpPitch; 5346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int i, pad; 5446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_Surface *surface; 5546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint32 Rmask; 5646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint32 Gmask; 5746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint32 Bmask; 5846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_Palette *palette; 5946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint8 *bits; 6046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int ExpandBMP; 6146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 6246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* The Win32 BMP file header (14 bytes) */ 6346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner char magic[2]; 6446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint32 bfSize; 6546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint16 bfReserved1; 6646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint16 bfReserved2; 6746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint32 bfOffBits; 6846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 6946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* The Win32 BITMAPINFOHEADER struct (40 bytes) */ 7046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint32 biSize; 7146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Sint32 biWidth; 7246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Sint32 biHeight; 7346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint16 biPlanes; 7446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint16 biBitCount; 7546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint32 biCompression; 7646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint32 biSizeImage; 7746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Sint32 biXPelsPerMeter; 7846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Sint32 biYPelsPerMeter; 7946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint32 biClrUsed; 8046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint32 biClrImportant; 8146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 8246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Make sure we are passed a valid data source */ 8346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner surface = NULL; 8446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner was_error = 0; 8546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( src == NULL ) { 8646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner was_error = 1; 8746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner goto done; 8846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 8946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 9046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Read in the BMP file header */ 9146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner fp_offset = SDL_RWtell(src); 9246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_ClearError(); 9346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( SDL_RWread(src, magic, 1, 2) != 2 ) { 9446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_Error(SDL_EFREAD); 9546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner was_error = 1; 9646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner goto done; 9746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 9846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( SDL_strncmp(magic, "BM", 2) != 0 ) { 9946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError("File is not a Windows BMP file"); 10046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner was_error = 1; 10146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner goto done; 10246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 10346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bfSize = SDL_ReadLE32(src); 10446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bfReserved1 = SDL_ReadLE16(src); 10546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bfReserved2 = SDL_ReadLE16(src); 10646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bfOffBits = SDL_ReadLE32(src); 10746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 10846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Read the Win32 BITMAPINFOHEADER */ 10946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biSize = SDL_ReadLE32(src); 11046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( biSize == 12 ) { 11146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biWidth = (Uint32)SDL_ReadLE16(src); 11246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biHeight = (Uint32)SDL_ReadLE16(src); 11346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biPlanes = SDL_ReadLE16(src); 11446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biBitCount = SDL_ReadLE16(src); 11546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biCompression = BI_RGB; 11646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biSizeImage = 0; 11746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biXPelsPerMeter = 0; 11846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biYPelsPerMeter = 0; 11946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biClrUsed = 0; 12046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biClrImportant = 0; 12146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 12246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biWidth = SDL_ReadLE32(src); 12346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biHeight = SDL_ReadLE32(src); 12446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biPlanes = SDL_ReadLE16(src); 12546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biBitCount = SDL_ReadLE16(src); 12646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biCompression = SDL_ReadLE32(src); 12746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biSizeImage = SDL_ReadLE32(src); 12846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biXPelsPerMeter = SDL_ReadLE32(src); 12946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biYPelsPerMeter = SDL_ReadLE32(src); 13046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biClrUsed = SDL_ReadLE32(src); 13146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biClrImportant = SDL_ReadLE32(src); 13246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 13346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 13446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Check for read error */ 13546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( SDL_strcmp(SDL_GetError(), "") != 0 ) { 13646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner was_error = 1; 13746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner goto done; 13846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 13946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 14046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Expand 1 and 4 bit bitmaps to 8 bits per pixel */ 14146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner switch (biBitCount) { 14246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 1: 14346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 4: 14446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner ExpandBMP = biBitCount; 14546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biBitCount = 8; 14646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 14746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner default: 14846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner ExpandBMP = 0; 14946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 15046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 15146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 15246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* We don't support any BMP compression right now */ 15346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Rmask = Gmask = Bmask = 0; 15446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner switch (biCompression) { 15546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case BI_RGB: 15646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* If there are no masks, use the defaults */ 15746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( bfOffBits == (14+biSize) ) { 15846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Default values for the BMP format */ 15946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner switch (biBitCount) { 16046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 15: 16146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 16: 16246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Rmask = 0x7C00; 16346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Gmask = 0x03E0; 16446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Bmask = 0x001F; 16546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 16646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 24: 16746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if SDL_BYTEORDER == SDL_BIG_ENDIAN 16846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Rmask = 0x000000FF; 16946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Gmask = 0x0000FF00; 17046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Bmask = 0x00FF0000; 17146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 17246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 17346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 32: 17446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Rmask = 0x00FF0000; 17546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Gmask = 0x0000FF00; 17646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Bmask = 0x000000FF; 17746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 17846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner default: 17946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 18046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 18146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 18246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 18346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Fall through -- read the RGB masks */ 18446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 18546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case BI_BITFIELDS: 18646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner switch (biBitCount) { 18746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 15: 18846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 16: 18946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 32: 19046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Rmask = SDL_ReadLE32(src); 19146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Gmask = SDL_ReadLE32(src); 19246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Bmask = SDL_ReadLE32(src); 19346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 19446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner default: 19546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 19646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 19746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 19846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner default: 19946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError("Compressed BMP files not supported"); 20046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner was_error = 1; 20146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner goto done; 20246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 20346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 20446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Create a compatible surface, note that the colors are RGB ordered */ 20546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner surface = SDL_CreateRGBSurface(SDL_SWSURFACE, 20646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biWidth, biHeight, biBitCount, Rmask, Gmask, Bmask, 0); 20746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( surface == NULL ) { 20846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner was_error = 1; 20946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner goto done; 21046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 21146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 21246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Load the palette, if any */ 21346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner palette = (surface->format)->palette; 21446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( palette ) { 21546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( biClrUsed == 0 ) { 21646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biClrUsed = 1 << biBitCount; 21746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 21846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( biSize == 12 ) { 21946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for ( i = 0; i < (int)biClrUsed; ++i ) { 22046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_RWread(src, &palette->colors[i].b, 1, 1); 22146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_RWread(src, &palette->colors[i].g, 1, 1); 22246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_RWread(src, &palette->colors[i].r, 1, 1); 22346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner palette->colors[i].unused = 0; 22446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 22546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 22646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for ( i = 0; i < (int)biClrUsed; ++i ) { 22746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_RWread(src, &palette->colors[i].b, 1, 1); 22846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_RWread(src, &palette->colors[i].g, 1, 1); 22946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_RWread(src, &palette->colors[i].r, 1, 1); 23046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_RWread(src, &palette->colors[i].unused, 1, 1); 23146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 23246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 23346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner palette->ncolors = biClrUsed; 23446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 23546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 23646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Read the surface pixels. Note that the bmp image is upside down */ 23746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( SDL_RWseek(src, fp_offset+bfOffBits, RW_SEEK_SET) < 0 ) { 23846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_Error(SDL_EFSEEK); 23946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner was_error = 1; 24046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner goto done; 24146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 24246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bits = (Uint8 *)surface->pixels+(surface->h*surface->pitch); 24346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner switch (ExpandBMP) { 24446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 1: 24546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bmpPitch = (biWidth + 7) >> 3; 24646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pad = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0); 24746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 24846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 4: 24946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bmpPitch = (biWidth + 1) >> 1; 25046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pad = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0); 25146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 25246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner default: 25346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pad = ((surface->pitch%4) ? 25446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner (4-(surface->pitch%4)) : 0); 25546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 25646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 25746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner while ( bits > (Uint8 *)surface->pixels ) { 25846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bits -= surface->pitch; 25946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner switch (ExpandBMP) { 26046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 1: 26146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 4: { 26246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint8 pixel = 0; 26346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int shift = (8-ExpandBMP); 26446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for ( i=0; i<surface->w; ++i ) { 26546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( i%(8/ExpandBMP) == 0 ) { 26646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( !SDL_RWread(src, &pixel, 1, 1) ) { 26746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError( 26846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner "Error reading from BMP"); 26946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner was_error = 1; 27046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner goto done; 27146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 27246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 27346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *(bits+i) = (pixel>>shift); 27446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pixel <<= ExpandBMP; 27546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } } 27646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 27746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 27846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner default: 27946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( SDL_RWread(src, bits, 1, surface->pitch) 28046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner != surface->pitch ) { 28146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_Error(SDL_EFREAD); 28246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner was_error = 1; 28346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner goto done; 28446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 28546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if SDL_BYTEORDER == SDL_BIG_ENDIAN 28646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Byte-swap the pixels if needed. Note that the 24bpp 28746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case has already been taken care of above. */ 28846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner switch(biBitCount) { 28946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 15: 29046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 16: { 29146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint16 *pix = (Uint16 *)bits; 29246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for(i = 0; i < surface->w; i++) 29346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pix[i] = SDL_Swap16(pix[i]); 29446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 29546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 29646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 29746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 32: { 29846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint32 *pix = (Uint32 *)bits; 29946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for(i = 0; i < surface->w; i++) 30046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pix[i] = SDL_Swap32(pix[i]); 30146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 30246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 30346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 30446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 30546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 30646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 30746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Skip padding bytes, ugh */ 30846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( pad ) { 30946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint8 padbyte; 31046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for ( i=0; i<pad; ++i ) { 31146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_RWread(src, &padbyte, 1, 1); 31246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 31346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 31446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 31546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerdone: 31646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( was_error ) { 31746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( src ) { 31846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_RWseek(src, fp_offset, RW_SEEK_SET); 31946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 32046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( surface ) { 32146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_FreeSurface(surface); 32246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 32346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner surface = NULL; 32446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 32546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( freesrc && src ) { 32646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_RWclose(src); 32746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 32846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(surface); 32946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 33046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 33146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint SDL_SaveBMP_RW (SDL_Surface *saveme, SDL_RWops *dst, int freedst) 33246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 33346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner long fp_offset; 33446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int i, pad; 33546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_Surface *surface; 33646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint8 *bits; 33746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 33846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* The Win32 BMP file header (14 bytes) */ 33946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner char magic[2] = { 'B', 'M' }; 34046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint32 bfSize; 34146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint16 bfReserved1; 34246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint16 bfReserved2; 34346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint32 bfOffBits; 34446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 34546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* The Win32 BITMAPINFOHEADER struct (40 bytes) */ 34646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint32 biSize; 34746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Sint32 biWidth; 34846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Sint32 biHeight; 34946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint16 biPlanes; 35046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint16 biBitCount; 35146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint32 biCompression; 35246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint32 biSizeImage; 35346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Sint32 biXPelsPerMeter; 35446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Sint32 biYPelsPerMeter; 35546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint32 biClrUsed; 35646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint32 biClrImportant; 35746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 35846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Make sure we have somewhere to save */ 35946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner surface = NULL; 36046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( dst ) { 36146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( saveme->format->palette ) { 36246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( saveme->format->BitsPerPixel == 8 ) { 36346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner surface = saveme; 36446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 36546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError("%d bpp BMP files not supported", 36646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner saveme->format->BitsPerPixel); 36746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 36846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 36946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner else if ( (saveme->format->BitsPerPixel == 24) && 37046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if SDL_BYTEORDER == SDL_LIL_ENDIAN 37146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner (saveme->format->Rmask == 0x00FF0000) && 37246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner (saveme->format->Gmask == 0x0000FF00) && 37346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner (saveme->format->Bmask == 0x000000FF) 37446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else 37546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner (saveme->format->Rmask == 0x000000FF) && 37646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner (saveme->format->Gmask == 0x0000FF00) && 37746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner (saveme->format->Bmask == 0x00FF0000) 37846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 37946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner ) { 38046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner surface = saveme; 38146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 38246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_Rect bounds; 38346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 38446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Convert to 24 bits per pixel */ 38546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner surface = SDL_CreateRGBSurface(SDL_SWSURFACE, 38646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner saveme->w, saveme->h, 24, 38746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if SDL_BYTEORDER == SDL_LIL_ENDIAN 38846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 0x00FF0000, 0x0000FF00, 0x000000FF, 38946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else 39046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 0x000000FF, 0x0000FF00, 0x00FF0000, 39146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 39246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 0); 39346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( surface != NULL ) { 39446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bounds.x = 0; 39546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bounds.y = 0; 39646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bounds.w = saveme->w; 39746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bounds.h = saveme->h; 39846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( SDL_LowerBlit(saveme, &bounds, surface, 39946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner &bounds) < 0 ) { 40046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_FreeSurface(surface); 40146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError( 40246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner "Couldn't convert image to 24 bpp"); 40346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner surface = NULL; 40446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 40546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 40646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 40746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 40846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 40946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( surface && (SDL_LockSurface(surface) == 0) ) { 41046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner const int bw = surface->w*surface->format->BytesPerPixel; 41146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 41246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Set the BMP file header values */ 41346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bfSize = 0; /* We'll write this when we're done */ 41446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bfReserved1 = 0; 41546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bfReserved2 = 0; 41646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bfOffBits = 0; /* We'll write this when we're done */ 41746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 41846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Write the BMP file header values */ 41946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner fp_offset = SDL_RWtell(dst); 42046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_ClearError(); 42146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_RWwrite(dst, magic, 2, 1); 42246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_WriteLE32(dst, bfSize); 42346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_WriteLE16(dst, bfReserved1); 42446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_WriteLE16(dst, bfReserved2); 42546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_WriteLE32(dst, bfOffBits); 42646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 42746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Set the BMP info values */ 42846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biSize = 40; 42946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biWidth = surface->w; 43046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biHeight = surface->h; 43146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biPlanes = 1; 43246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biBitCount = surface->format->BitsPerPixel; 43346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biCompression = BI_RGB; 43446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biSizeImage = surface->h*surface->pitch; 43546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biXPelsPerMeter = 0; 43646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biYPelsPerMeter = 0; 43746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( surface->format->palette ) { 43846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biClrUsed = surface->format->palette->ncolors; 43946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 44046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biClrUsed = 0; 44146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 44246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner biClrImportant = 0; 44346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 44446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Write the BMP info values */ 44546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_WriteLE32(dst, biSize); 44646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_WriteLE32(dst, biWidth); 44746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_WriteLE32(dst, biHeight); 44846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_WriteLE16(dst, biPlanes); 44946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_WriteLE16(dst, biBitCount); 45046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_WriteLE32(dst, biCompression); 45146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_WriteLE32(dst, biSizeImage); 45246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_WriteLE32(dst, biXPelsPerMeter); 45346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_WriteLE32(dst, biYPelsPerMeter); 45446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_WriteLE32(dst, biClrUsed); 45546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_WriteLE32(dst, biClrImportant); 45646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 45746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Write the palette (in BGR color order) */ 45846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( surface->format->palette ) { 45946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_Color *colors; 46046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int ncolors; 46146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 46246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner colors = surface->format->palette->colors; 46346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner ncolors = surface->format->palette->ncolors; 46446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for ( i=0; i<ncolors; ++i ) { 46546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_RWwrite(dst, &colors[i].b, 1, 1); 46646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_RWwrite(dst, &colors[i].g, 1, 1); 46746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_RWwrite(dst, &colors[i].r, 1, 1); 46846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_RWwrite(dst, &colors[i].unused, 1, 1); 46946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 47046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 47146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 47246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Write the bitmap offset */ 47346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bfOffBits = SDL_RWtell(dst)-fp_offset; 47446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( SDL_RWseek(dst, fp_offset+10, RW_SEEK_SET) < 0 ) { 47546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_Error(SDL_EFSEEK); 47646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 47746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_WriteLE32(dst, bfOffBits); 47846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( SDL_RWseek(dst, fp_offset+bfOffBits, RW_SEEK_SET) < 0 ) { 47946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_Error(SDL_EFSEEK); 48046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 48146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 48246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Write the bitmap image upside down */ 48346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bits = (Uint8 *)surface->pixels+(surface->h*surface->pitch); 48446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pad = ((bw%4) ? (4-(bw%4)) : 0); 48546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner while ( bits > (Uint8 *)surface->pixels ) { 48646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bits -= surface->pitch; 48746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( SDL_RWwrite(dst, bits, 1, bw) != bw) { 48846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_Error(SDL_EFWRITE); 48946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 49046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 49146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( pad ) { 49246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner const Uint8 padbyte = 0; 49346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for ( i=0; i<pad; ++i ) { 49446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_RWwrite(dst, &padbyte, 1, 1); 49546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 49646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 49746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 49846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 49946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Write the BMP file size */ 50046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bfSize = SDL_RWtell(dst)-fp_offset; 50146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( SDL_RWseek(dst, fp_offset+2, RW_SEEK_SET) < 0 ) { 50246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_Error(SDL_EFSEEK); 50346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 50446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_WriteLE32(dst, bfSize); 50546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( SDL_RWseek(dst, fp_offset+bfSize, RW_SEEK_SET) < 0 ) { 50646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_Error(SDL_EFSEEK); 50746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 50846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 50946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Close it up.. */ 51046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_UnlockSurface(surface); 51146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( surface != saveme ) { 51246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_FreeSurface(surface); 51346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 51446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 51546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 51646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( freedst && dst ) { 51746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_RWclose(dst); 51846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 51946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return((SDL_strcmp(SDL_GetError(), "") == 0) ? 0 : -1); 52046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 521