IMG_bmp.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 02 Nov 2008 23:13:00 +0000
changeset 184 578a70f2c6d7
parent 154 201cc5c1b373
child 186 5fbbeabf647f
permissions -rw-r--r--
Fixed buffer overflow in BMP loading code, discovered by j00ru//vx
slouken@0
     1
/*
slouken@53
     2
    SDL_image:  An example image loading library for use with SDL
slouken@121
     3
    Copyright (C) 1997-2006 Sam Lantinga
slouken@0
     4
slouken@0
     5
    This library is free software; you can redistribute it and/or
slouken@121
     6
    modify it under the terms of the GNU Lesser General Public
slouken@0
     7
    License as published by the Free Software Foundation; either
slouken@121
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@0
     9
slouken@0
    10
    This library is distributed in the hope that it will be useful,
slouken@0
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@0
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@121
    13
    Lesser General Public License for more details.
slouken@0
    14
slouken@121
    15
    You should have received a copy of the GNU Lesser General Public
slouken@121
    16
    License along with this library; if not, write to the Free Software
slouken@121
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@0
    18
slouken@0
    19
    Sam Lantinga
slouken@53
    20
    slouken@libsdl.org
slouken@0
    21
*/
slouken@0
    22
slouken@0
    23
/* This is a BMP image file loading framework */
slouken@0
    24
slouken@0
    25
#include <stdio.h>
slouken@0
    26
#include <string.h>
slouken@0
    27
slouken@0
    28
#include "SDL_image.h"
slouken@0
    29
slouken@0
    30
#ifdef LOAD_BMP
slouken@0
    31
slouken@0
    32
/* See if an image is contained in a data source */
slouken@0
    33
int IMG_isBMP(SDL_RWops *src)
slouken@0
    34
{
slouken@117
    35
	int start;
slouken@0
    36
	int is_BMP;
slouken@0
    37
	char magic[2];
slouken@0
    38
icculus@154
    39
	if ( !src )
icculus@154
    40
		return 0;
slouken@117
    41
	start = SDL_RWtell(src);
slouken@0
    42
	is_BMP = 0;
slouken@117
    43
	if ( SDL_RWread(src, magic, sizeof(magic), 1) ) {
slouken@0
    44
		if ( strncmp(magic, "BM", 2) == 0 ) {
slouken@0
    45
			is_BMP = 1;
slouken@0
    46
		}
slouken@0
    47
	}
slouken@117
    48
	SDL_RWseek(src, start, SEEK_SET);
slouken@0
    49
	return(is_BMP);
slouken@0
    50
}
slouken@0
    51
slouken@101
    52
#include "SDL_error.h"
slouken@101
    53
#include "SDL_video.h"
slouken@101
    54
#include "SDL_endian.h"
slouken@101
    55
slouken@101
    56
/* Compression encodings for BMP files */
slouken@101
    57
#ifndef BI_RGB
slouken@101
    58
#define BI_RGB		0
slouken@101
    59
#define BI_RLE8		1
slouken@101
    60
#define BI_RLE4		2
slouken@101
    61
#define BI_BITFIELDS	3
slouken@101
    62
#endif
slouken@101
    63
slouken@101
    64
static int readRlePixels(SDL_Surface * surface, SDL_RWops * src, int isRle8)
slouken@101
    65
{
slouken@101
    66
	/*
slouken@101
    67
	| Sets the surface pixels from src.  A bmp image is upside down.
slouken@101
    68
	*/
slouken@101
    69
	int pitch = surface->pitch;
slouken@101
    70
	int height = surface->h;
slouken@184
    71
	Uint8 *start = (Uint8 *)surface->pixels;
slouken@184
    72
	Uint8 *end = start + (height*pitch);
slouken@184
    73
	Uint8 *bits = end-pitch, *spot;
slouken@101
    74
	int ofs = 0;
slouken@101
    75
	Uint8 ch;
slouken@101
    76
	Uint8 needsPad;
slouken@101
    77
slouken@184
    78
#define COPY_PIXEL(x)	spot = &bits[ofs++]; if(spot >= start && spot < end) *spot = (x)
slouken@184
    79
slouken@101
    80
	for (;;) {
slouken@101
    81
		if ( !SDL_RWread(src, &ch, 1, 1) ) return 1;
slouken@101
    82
		/*
slouken@101
    83
		| encoded mode starts with a run length, and then a byte
slouken@101
    84
		| with two colour indexes to alternate between for the run
slouken@101
    85
		*/
slouken@101
    86
		if ( ch ) {
slouken@101
    87
			Uint8 pixel;
slouken@101
    88
			if ( !SDL_RWread(src, &pixel, 1, 1) ) return 1;
slouken@101
    89
			if ( isRle8 ) {                 /* 256-color bitmap, compressed */
slouken@101
    90
				do {
slouken@184
    91
					COPY_PIXEL(pixel);
slouken@101
    92
				} while (--ch);
slouken@184
    93
			} else {                         /* 16-color bitmap, compressed */
slouken@101
    94
				Uint8 pixel0 = pixel >> 4;
slouken@101
    95
				Uint8 pixel1 = pixel & 0x0F;
slouken@101
    96
				for (;;) {
slouken@184
    97
					COPY_PIXEL(pixel0);	/* even count, high nibble */
slouken@101
    98
					if (!--ch) break;
slouken@184
    99
					COPY_PIXEL(pixel1);	/* odd count, low nibble */
slouken@101
   100
					if (!--ch) break;
slouken@101
   101
				}
slouken@101
   102
			}
slouken@101
   103
		} else {
slouken@101
   104
			/*
slouken@101
   105
			| A leading zero is an escape; it may signal the end of the bitmap,
slouken@101
   106
			| a cursor move, or some absolute data.
slouken@101
   107
			| zero tag may be absolute mode or an escape
slouken@101
   108
			*/
slouken@101
   109
			if ( !SDL_RWread(src, &ch, 1, 1) ) return 1;
slouken@101
   110
			switch (ch) {
slouken@101
   111
			case 0:                         /* end of line */
slouken@101
   112
				ofs = 0;
slouken@101
   113
				bits -= pitch;               /* go to previous */
slouken@101
   114
				break;
slouken@101
   115
			case 1:                         /* end of bitmap */
slouken@101
   116
				return 0;                    /* success! */
slouken@101
   117
			case 2:                         /* delta */
slouken@101
   118
				if ( !SDL_RWread(src, &ch, 1, 1) ) return 1;
slouken@101
   119
				ofs += ch;
slouken@101
   120
				if ( !SDL_RWread(src, &ch, 1, 1) ) return 1;
slouken@101
   121
				bits -= (ch * pitch);
slouken@101
   122
				break;
slouken@101
   123
			default:                        /* no compression */
slouken@101
   124
				if (isRle8) {
slouken@101
   125
					needsPad = ( ch & 1 );
slouken@101
   126
					do {
slouken@184
   127
						Uint8 pixel;
slouken@184
   128
						if ( !SDL_RWread(src, &pixel, 1, 1) ) return 1;
slouken@184
   129
						COPY_PIXEL(pixel);
slouken@101
   130
					} while (--ch);
slouken@101
   131
				} else {
slouken@101
   132
					needsPad = ( ((ch+1)>>1) & 1 ); /* (ch+1)>>1: bytes size */
slouken@101
   133
					for (;;) {
slouken@101
   134
						Uint8 pixel;
slouken@101
   135
						if ( !SDL_RWread(src, &pixel, 1, 1) ) return 1;
slouken@184
   136
						COPY_PIXEL(pixel >> 4);
slouken@101
   137
						if (!--ch) break;
slouken@184
   138
						COPY_PIXEL(pixel & 0x0F);
slouken@101
   139
						if (!--ch) break;
slouken@101
   140
					}
slouken@101
   141
				}
slouken@101
   142
				/* pad at even boundary */
slouken@101
   143
				if ( needsPad && !SDL_RWread(src, &ch, 1, 1) ) return 1;
slouken@101
   144
				break;
slouken@101
   145
			}
slouken@101
   146
		}
slouken@101
   147
	}
slouken@101
   148
}
slouken@101
   149
slouken@101
   150
static SDL_Surface *LoadBMP_RW (SDL_RWops *src, int freesrc)
slouken@101
   151
{
slouken@101
   152
	int was_error;
slouken@101
   153
	long fp_offset;
slouken@101
   154
	int bmpPitch;
slouken@101
   155
	int i, pad;
slouken@101
   156
	SDL_Surface *surface;
slouken@101
   157
	Uint32 Rmask;
slouken@101
   158
	Uint32 Gmask;
slouken@101
   159
	Uint32 Bmask;
slouken@106
   160
	Uint32 Amask;
slouken@101
   161
	SDL_Palette *palette;
slouken@101
   162
	Uint8 *bits;
slouken@101
   163
	int ExpandBMP;
slouken@101
   164
slouken@101
   165
	/* The Win32 BMP file header (14 bytes) */
slouken@101
   166
	char   magic[2];
slouken@101
   167
	Uint32 bfSize;
slouken@101
   168
	Uint16 bfReserved1;
slouken@101
   169
	Uint16 bfReserved2;
slouken@101
   170
	Uint32 bfOffBits;
slouken@101
   171
slouken@101
   172
	/* The Win32 BITMAPINFOHEADER struct (40 bytes) */
slouken@101
   173
	Uint32 biSize;
slouken@101
   174
	Sint32 biWidth;
slouken@101
   175
	Sint32 biHeight;
slouken@101
   176
	Uint16 biPlanes;
slouken@101
   177
	Uint16 biBitCount;
slouken@101
   178
	Uint32 biCompression;
slouken@101
   179
	Uint32 biSizeImage;
slouken@101
   180
	Sint32 biXPelsPerMeter;
slouken@101
   181
	Sint32 biYPelsPerMeter;
slouken@101
   182
	Uint32 biClrUsed;
slouken@101
   183
	Uint32 biClrImportant;
slouken@101
   184
slouken@101
   185
	/* Make sure we are passed a valid data source */
slouken@101
   186
	surface = NULL;
slouken@101
   187
	was_error = 0;
slouken@101
   188
	if ( src == NULL ) {
slouken@101
   189
		was_error = 1;
slouken@101
   190
		goto done;
slouken@101
   191
	}
slouken@101
   192
slouken@101
   193
	/* Read in the BMP file header */
slouken@101
   194
	fp_offset = SDL_RWtell(src);
slouken@101
   195
	SDL_ClearError();
slouken@101
   196
	if ( SDL_RWread(src, magic, 1, 2) != 2 ) {
slouken@101
   197
		SDL_Error(SDL_EFREAD);
slouken@101
   198
		was_error = 1;
slouken@101
   199
		goto done;
slouken@101
   200
	}
slouken@101
   201
	if ( strncmp(magic, "BM", 2) != 0 ) {
slouken@101
   202
		SDL_SetError("File is not a Windows BMP file");
slouken@101
   203
		was_error = 1;
slouken@101
   204
		goto done;
slouken@101
   205
	}
slouken@101
   206
	bfSize		= SDL_ReadLE32(src);
slouken@101
   207
	bfReserved1	= SDL_ReadLE16(src);
slouken@101
   208
	bfReserved2	= SDL_ReadLE16(src);
slouken@101
   209
	bfOffBits	= SDL_ReadLE32(src);
slouken@101
   210
slouken@101
   211
	/* Read the Win32 BITMAPINFOHEADER */
slouken@101
   212
	biSize		= SDL_ReadLE32(src);
slouken@101
   213
	if ( biSize == 12 ) {
slouken@101
   214
		biWidth		= (Uint32)SDL_ReadLE16(src);
slouken@101
   215
		biHeight	= (Uint32)SDL_ReadLE16(src);
slouken@101
   216
		biPlanes	= SDL_ReadLE16(src);
slouken@101
   217
		biBitCount	= SDL_ReadLE16(src);
slouken@101
   218
		biCompression	= BI_RGB;
slouken@101
   219
		biSizeImage	= 0;
slouken@101
   220
		biXPelsPerMeter	= 0;
slouken@101
   221
		biYPelsPerMeter	= 0;
slouken@101
   222
		biClrUsed	= 0;
slouken@101
   223
		biClrImportant	= 0;
slouken@101
   224
	} else {
slouken@101
   225
		biWidth		= SDL_ReadLE32(src);
slouken@101
   226
		biHeight	= SDL_ReadLE32(src);
slouken@101
   227
		biPlanes	= SDL_ReadLE16(src);
slouken@101
   228
		biBitCount	= SDL_ReadLE16(src);
slouken@101
   229
		biCompression	= SDL_ReadLE32(src);
slouken@101
   230
		biSizeImage	= SDL_ReadLE32(src);
slouken@101
   231
		biXPelsPerMeter	= SDL_ReadLE32(src);
slouken@101
   232
		biYPelsPerMeter	= SDL_ReadLE32(src);
slouken@101
   233
		biClrUsed	= SDL_ReadLE32(src);
slouken@101
   234
		biClrImportant	= SDL_ReadLE32(src);
slouken@101
   235
	}
slouken@101
   236
slouken@101
   237
	/* Check for read error */
slouken@101
   238
	if ( strcmp(SDL_GetError(), "") != 0 ) {
slouken@101
   239
		was_error = 1;
slouken@101
   240
		goto done;
slouken@101
   241
	}
slouken@101
   242
slouken@101
   243
	/* Expand 1 and 4 bit bitmaps to 8 bits per pixel */
slouken@101
   244
	switch (biBitCount) {
slouken@101
   245
		case 1:
slouken@101
   246
		case 4:
slouken@101
   247
			ExpandBMP = biBitCount;
slouken@101
   248
			biBitCount = 8;
slouken@101
   249
			break;
slouken@101
   250
		default:
slouken@101
   251
			ExpandBMP = 0;
slouken@101
   252
			break;
slouken@101
   253
	}
slouken@101
   254
slouken@101
   255
	/* RLE4 and RLE8 BMP compression is supported */
slouken@106
   256
	Rmask = Gmask = Bmask = Amask = 0;
slouken@101
   257
	switch (biCompression) {
slouken@101
   258
		case BI_RGB:
slouken@101
   259
			/* If there are no masks, use the defaults */
slouken@101
   260
			if ( bfOffBits == (14+biSize) ) {
slouken@101
   261
				/* Default values for the BMP format */
slouken@101
   262
				switch (biBitCount) {
slouken@101
   263
					case 15:
slouken@101
   264
					case 16:
slouken@101
   265
						Rmask = 0x7C00;
slouken@101
   266
						Gmask = 0x03E0;
slouken@101
   267
						Bmask = 0x001F;
slouken@101
   268
						break;
slouken@101
   269
					case 24:
slouken@101
   270
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
slouken@101
   271
					        Rmask = 0x000000FF;
slouken@101
   272
					        Gmask = 0x0000FF00;
slouken@101
   273
					        Bmask = 0x00FF0000;
slouken@106
   274
#else
slouken@106
   275
						Rmask = 0x00FF0000;
slouken@106
   276
						Gmask = 0x0000FF00;
slouken@106
   277
						Bmask = 0x000000FF;
slouken@106
   278
#endif
slouken@101
   279
						break;
slouken@101
   280
					case 32:
slouken@106
   281
						Amask = 0xFF000000;
slouken@101
   282
						Rmask = 0x00FF0000;
slouken@101
   283
						Gmask = 0x0000FF00;
slouken@101
   284
						Bmask = 0x000000FF;
slouken@101
   285
						break;
slouken@101
   286
					default:
slouken@101
   287
						break;
slouken@101
   288
				}
slouken@101
   289
				break;
slouken@101
   290
			}
slouken@101
   291
			/* Fall through -- read the RGB masks */
slouken@101
   292
slouken@101
   293
		default:
slouken@101
   294
			switch (biBitCount) {
slouken@101
   295
				case 15:
slouken@101
   296
				case 16:
slouken@101
   297
				case 32:
slouken@101
   298
					Rmask = SDL_ReadLE32(src);
slouken@101
   299
					Gmask = SDL_ReadLE32(src);
slouken@101
   300
					Bmask = SDL_ReadLE32(src);
slouken@106
   301
					Amask = SDL_ReadLE32(src);
slouken@101
   302
					break;
slouken@101
   303
				default:
slouken@101
   304
					break;
slouken@101
   305
			}
slouken@101
   306
			break;
slouken@101
   307
	}
slouken@101
   308
slouken@101
   309
	/* Create a compatible surface, note that the colors are RGB ordered */
slouken@101
   310
	surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
slouken@106
   311
			biWidth, biHeight, biBitCount, Rmask, Gmask, Bmask, Amask);
slouken@101
   312
	if ( surface == NULL ) {
slouken@101
   313
		was_error = 1;
slouken@101
   314
		goto done;
slouken@101
   315
	}
slouken@101
   316
slouken@101
   317
	/* Load the palette, if any */
slouken@101
   318
	palette = (surface->format)->palette;
slouken@101
   319
	if ( palette ) {
slouken@151
   320
		if ( SDL_RWseek(src, fp_offset+14+biSize, SEEK_SET) < 0 ) {
slouken@151
   321
			SDL_Error(SDL_EFSEEK);
slouken@151
   322
			was_error = 1;
slouken@151
   323
			goto done;
slouken@151
   324
		}
slouken@151
   325
slouken@101
   326
		/*
slouken@101
   327
		| guich: always use 1<<bpp b/c some bitmaps can bring wrong information
slouken@101
   328
		| for colorsUsed
slouken@101
   329
		*/
slouken@101
   330
		/* if ( biClrUsed == 0 ) {  */
slouken@101
   331
		biClrUsed = 1 << biBitCount;
slouken@101
   332
		/* } */
slouken@101
   333
		if ( biSize == 12 ) {
slouken@101
   334
			for ( i = 0; i < (int)biClrUsed; ++i ) {
slouken@101
   335
				SDL_RWread(src, &palette->colors[i].b, 1, 1);
slouken@101
   336
				SDL_RWread(src, &palette->colors[i].g, 1, 1);
slouken@101
   337
				SDL_RWread(src, &palette->colors[i].r, 1, 1);
slouken@101
   338
				palette->colors[i].unused = 0;
slouken@101
   339
			}	
slouken@101
   340
		} else {
slouken@101
   341
			for ( i = 0; i < (int)biClrUsed; ++i ) {
slouken@101
   342
				SDL_RWread(src, &palette->colors[i].b, 1, 1);
slouken@101
   343
				SDL_RWread(src, &palette->colors[i].g, 1, 1);
slouken@101
   344
				SDL_RWread(src, &palette->colors[i].r, 1, 1);
slouken@101
   345
				SDL_RWread(src, &palette->colors[i].unused, 1, 1);
slouken@101
   346
			}	
slouken@101
   347
		}
slouken@101
   348
		palette->ncolors = biClrUsed;
slouken@101
   349
	}
slouken@101
   350
slouken@101
   351
	/* Read the surface pixels.  Note that the bmp image is upside down */
slouken@101
   352
	if ( SDL_RWseek(src, fp_offset+bfOffBits, SEEK_SET) < 0 ) {
slouken@101
   353
		SDL_Error(SDL_EFSEEK);
slouken@101
   354
		was_error = 1;
slouken@101
   355
		goto done;
slouken@101
   356
	}
slouken@101
   357
	if ((biCompression == BI_RLE4) || (biCompression == BI_RLE8)) {
slouken@101
   358
		was_error = readRlePixels(surface, src, biCompression == BI_RLE8);
slouken@101
   359
		if (was_error) SDL_SetError("Error reading from BMP");
slouken@101
   360
		goto done;
slouken@101
   361
	}
slouken@101
   362
	bits = (Uint8 *)surface->pixels+(surface->h*surface->pitch);
slouken@101
   363
	switch (ExpandBMP) {
slouken@101
   364
		case 1:
slouken@101
   365
			bmpPitch = (biWidth + 7) >> 3;
slouken@101
   366
			pad  = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0);
slouken@101
   367
			break;
slouken@101
   368
		case 4:
slouken@101
   369
			bmpPitch = (biWidth + 1) >> 1;
slouken@101
   370
			pad  = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0);
slouken@101
   371
			break;
slouken@101
   372
		default:
slouken@101
   373
			pad  = ((surface->pitch%4) ?
slouken@101
   374
					(4-(surface->pitch%4)) : 0);
slouken@101
   375
			break;
slouken@101
   376
	}
slouken@101
   377
	while ( bits > (Uint8 *)surface->pixels ) {
slouken@101
   378
		bits -= surface->pitch;
slouken@101
   379
		switch (ExpandBMP) {
slouken@101
   380
			case 1:
slouken@101
   381
			case 4: {
slouken@101
   382
			Uint8 pixel = 0;
slouken@101
   383
			int   shift = (8-ExpandBMP);
slouken@101
   384
			for ( i=0; i<surface->w; ++i ) {
slouken@101
   385
				if ( i%(8/ExpandBMP) == 0 ) {
slouken@101
   386
					if ( !SDL_RWread(src, &pixel, 1, 1) ) {
slouken@101
   387
						SDL_SetError(
slouken@101
   388
					"Error reading from BMP");
slouken@101
   389
						was_error = 1;
slouken@101
   390
						goto done;
slouken@101
   391
					}
slouken@101
   392
				}
slouken@101
   393
				*(bits+i) = (pixel>>shift);
slouken@101
   394
				pixel <<= ExpandBMP;
slouken@101
   395
			} }
slouken@101
   396
			break;
slouken@101
   397
slouken@101
   398
			default:
slouken@101
   399
			if ( SDL_RWread(src, bits, 1, surface->pitch)
slouken@101
   400
							 != surface->pitch ) {
slouken@101
   401
				SDL_Error(SDL_EFREAD);
slouken@101
   402
				was_error = 1;
slouken@101
   403
				goto done;
slouken@101
   404
			}
slouken@101
   405
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
slouken@101
   406
			/* Byte-swap the pixels if needed. Note that the 24bpp
slouken@101
   407
			   case has already been taken care of above. */
slouken@101
   408
			switch(biBitCount) {
slouken@101
   409
				case 15:
slouken@101
   410
				case 16: {
slouken@101
   411
				        Uint16 *pix = (Uint16 *)bits;
slouken@101
   412
					for(i = 0; i < surface->w; i++)
slouken@101
   413
					        pix[i] = SDL_Swap16(pix[i]);
slouken@101
   414
					break;
slouken@101
   415
				}
slouken@101
   416
slouken@101
   417
				case 32: {
slouken@101
   418
				        Uint32 *pix = (Uint32 *)bits;
slouken@101
   419
					for(i = 0; i < surface->w; i++)
slouken@101
   420
					        pix[i] = SDL_Swap32(pix[i]);
slouken@101
   421
					break;
slouken@101
   422
				}
slouken@101
   423
			}
slouken@101
   424
#endif
slouken@101
   425
			break;
slouken@101
   426
		}
slouken@101
   427
		/* Skip padding bytes, ugh */
slouken@101
   428
		if ( pad ) {
slouken@101
   429
			Uint8 padbyte;
slouken@101
   430
			for ( i=0; i<pad; ++i ) {
slouken@101
   431
				SDL_RWread(src, &padbyte, 1, 1);
slouken@101
   432
			}
slouken@101
   433
		}
slouken@101
   434
	}
slouken@101
   435
done:
slouken@101
   436
	if ( was_error ) {
slouken@118
   437
		if ( src ) {
slouken@118
   438
			SDL_RWseek(src, fp_offset, SEEK_SET);
slouken@118
   439
		}
slouken@101
   440
		if ( surface ) {
slouken@101
   441
			SDL_FreeSurface(surface);
slouken@101
   442
		}
slouken@101
   443
		surface = NULL;
slouken@101
   444
	}
slouken@101
   445
	if ( freesrc && src ) {
slouken@101
   446
		SDL_RWclose(src);
slouken@101
   447
	}
slouken@101
   448
	return(surface);
slouken@101
   449
}
slouken@101
   450
slouken@0
   451
/* Load a BMP type image from an SDL datasource */
slouken@0
   452
SDL_Surface *IMG_LoadBMP_RW(SDL_RWops *src)
slouken@0
   453
{
slouken@101
   454
	return(LoadBMP_RW(src, 0));
slouken@0
   455
}
slouken@0
   456
slouken@0
   457
#else
slouken@0
   458
slouken@0
   459
/* See if an image is contained in a data source */
slouken@0
   460
int IMG_isBMP(SDL_RWops *src)
slouken@0
   461
{
slouken@0
   462
	return(0);
slouken@0
   463
}
slouken@0
   464
slouken@0
   465
/* Load a BMP type image from an SDL datasource */
slouken@0
   466
SDL_Surface *IMG_LoadBMP_RW(SDL_RWops *src)
slouken@0
   467
{
slouken@0
   468
	return(NULL);
slouken@0
   469
}
slouken@0
   470
slouken@0
   471
#endif /* LOAD_BMP */