comparison src/video/SDL_bmp.c @ 4241:d3a210342761 SDL-1.2

Fixed crash with right side up BMP files
author Sam Lantinga <slouken@libsdl.org>
date Sat, 26 Sep 2009 06:01:27 +0000
parents a1b03ba2fcd0
children
comparison
equal deleted inserted replaced
4240:cb44bf8f8a0f 4241:d3a210342761
45 #endif 45 #endif
46 46
47 47
48 SDL_Surface * SDL_LoadBMP_RW (SDL_RWops *src, int freesrc) 48 SDL_Surface * SDL_LoadBMP_RW (SDL_RWops *src, int freesrc)
49 { 49 {
50 int was_error; 50 SDL_bool was_error;
51 long fp_offset; 51 long fp_offset;
52 int bmpPitch; 52 int bmpPitch;
53 int i, pad; 53 int i, pad;
54 SDL_Surface *surface; 54 SDL_Surface *surface;
55 Uint32 Rmask; 55 Uint32 Rmask;
56 Uint32 Gmask; 56 Uint32 Gmask;
57 Uint32 Bmask; 57 Uint32 Bmask;
58 SDL_Palette *palette; 58 SDL_Palette *palette;
59 Uint8 *bits; 59 Uint8 *bits;
60 Uint8 *top, *end;
61 SDL_bool topDown;
60 int ExpandBMP; 62 int ExpandBMP;
61 63
62 /* The Win32 BMP file header (14 bytes) */ 64 /* The Win32 BMP file header (14 bytes) */
63 char magic[2]; 65 char magic[2];
64 Uint32 bfSize; 66 Uint32 bfSize;
79 Uint32 biClrUsed; 81 Uint32 biClrUsed;
80 Uint32 biClrImportant; 82 Uint32 biClrImportant;
81 83
82 /* Make sure we are passed a valid data source */ 84 /* Make sure we are passed a valid data source */
83 surface = NULL; 85 surface = NULL;
84 was_error = 0; 86 was_error = SDL_FALSE;
85 if ( src == NULL ) { 87 if ( src == NULL ) {
86 was_error = 1; 88 was_error = SDL_TRUE;
87 goto done; 89 goto done;
88 } 90 }
89 91
90 /* Read in the BMP file header */ 92 /* Read in the BMP file header */
91 fp_offset = SDL_RWtell(src); 93 fp_offset = SDL_RWtell(src);
92 SDL_ClearError(); 94 SDL_ClearError();
93 if ( SDL_RWread(src, magic, 1, 2) != 2 ) { 95 if ( SDL_RWread(src, magic, 1, 2) != 2 ) {
94 SDL_Error(SDL_EFREAD); 96 SDL_Error(SDL_EFREAD);
95 was_error = 1; 97 was_error = SDL_TRUE;
96 goto done; 98 goto done;
97 } 99 }
98 if ( SDL_strncmp(magic, "BM", 2) != 0 ) { 100 if ( SDL_strncmp(magic, "BM", 2) != 0 ) {
99 SDL_SetError("File is not a Windows BMP file"); 101 SDL_SetError("File is not a Windows BMP file");
100 was_error = 1; 102 was_error = SDL_TRUE;
101 goto done; 103 goto done;
102 } 104 }
103 bfSize = SDL_ReadLE32(src); 105 bfSize = SDL_ReadLE32(src);
104 bfReserved1 = SDL_ReadLE16(src); 106 bfReserved1 = SDL_ReadLE16(src);
105 bfReserved2 = SDL_ReadLE16(src); 107 bfReserved2 = SDL_ReadLE16(src);
128 biXPelsPerMeter = SDL_ReadLE32(src); 130 biXPelsPerMeter = SDL_ReadLE32(src);
129 biYPelsPerMeter = SDL_ReadLE32(src); 131 biYPelsPerMeter = SDL_ReadLE32(src);
130 biClrUsed = SDL_ReadLE32(src); 132 biClrUsed = SDL_ReadLE32(src);
131 biClrImportant = SDL_ReadLE32(src); 133 biClrImportant = SDL_ReadLE32(src);
132 } 134 }
135 if (biHeight < 0) {
136 topDown = SDL_TRUE;
137 biHeight = -biHeight;
138 } else {
139 topDown = SDL_FALSE;
140 }
133 141
134 /* Check for read error */ 142 /* Check for read error */
135 if ( SDL_strcmp(SDL_GetError(), "") != 0 ) { 143 if ( SDL_strcmp(SDL_GetError(), "") != 0 ) {
136 was_error = 1; 144 was_error = SDL_TRUE;
137 goto done; 145 goto done;
138 } 146 }
139 147
140 /* Expand 1 and 4 bit bitmaps to 8 bits per pixel */ 148 /* Expand 1 and 4 bit bitmaps to 8 bits per pixel */
141 switch (biBitCount) { 149 switch (biBitCount) {
195 break; 203 break;
196 } 204 }
197 break; 205 break;
198 default: 206 default:
199 SDL_SetError("Compressed BMP files not supported"); 207 SDL_SetError("Compressed BMP files not supported");
200 was_error = 1; 208 was_error = SDL_TRUE;
201 goto done; 209 goto done;
202 } 210 }
203 211
204 /* Create a compatible surface, note that the colors are RGB ordered */ 212 /* Create a compatible surface, note that the colors are RGB ordered */
205 surface = SDL_CreateRGBSurface(SDL_SWSURFACE, 213 surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
206 biWidth, biHeight, biBitCount, Rmask, Gmask, Bmask, 0); 214 biWidth, biHeight, biBitCount, Rmask, Gmask, Bmask, 0);
207 if ( surface == NULL ) { 215 if ( surface == NULL ) {
208 was_error = 1; 216 was_error = SDL_TRUE;
209 goto done; 217 goto done;
210 } 218 }
211 219
212 /* Load the palette, if any */ 220 /* Load the palette, if any */
213 palette = (surface->format)->palette; 221 palette = (surface->format)->palette;
234 } 242 }
235 243
236 /* Read the surface pixels. Note that the bmp image is upside down */ 244 /* Read the surface pixels. Note that the bmp image is upside down */
237 if ( SDL_RWseek(src, fp_offset+bfOffBits, RW_SEEK_SET) < 0 ) { 245 if ( SDL_RWseek(src, fp_offset+bfOffBits, RW_SEEK_SET) < 0 ) {
238 SDL_Error(SDL_EFSEEK); 246 SDL_Error(SDL_EFSEEK);
239 was_error = 1; 247 was_error = SDL_TRUE;
240 goto done; 248 goto done;
241 } 249 }
242 bits = (Uint8 *)surface->pixels+(surface->h*surface->pitch); 250 top = (Uint8 *)surface->pixels;
251 end = (Uint8 *)surface->pixels+(surface->h*surface->pitch);
243 switch (ExpandBMP) { 252 switch (ExpandBMP) {
244 case 1: 253 case 1:
245 bmpPitch = (biWidth + 7) >> 3; 254 bmpPitch = (biWidth + 7) >> 3;
246 pad = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0); 255 pad = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0);
247 break; 256 break;
252 default: 261 default:
253 pad = ((surface->pitch%4) ? 262 pad = ((surface->pitch%4) ?
254 (4-(surface->pitch%4)) : 0); 263 (4-(surface->pitch%4)) : 0);
255 break; 264 break;
256 } 265 }
257 while ( bits > (Uint8 *)surface->pixels ) { 266 if ( topDown ) {
258 bits -= surface->pitch; 267 bits = top;
268 } else {
269 bits = end - surface->pitch;
270 }
271 while ( bits >= top && bits < end ) {
259 switch (ExpandBMP) { 272 switch (ExpandBMP) {
260 case 1: 273 case 1:
261 case 4: { 274 case 4: {
262 Uint8 pixel = 0; 275 Uint8 pixel = 0;
263 int shift = (8-ExpandBMP); 276 int shift = (8-ExpandBMP);
264 for ( i=0; i<surface->w; ++i ) { 277 for ( i=0; i<surface->w; ++i ) {
265 if ( i%(8/ExpandBMP) == 0 ) { 278 if ( i%(8/ExpandBMP) == 0 ) {
266 if ( !SDL_RWread(src, &pixel, 1, 1) ) { 279 if ( !SDL_RWread(src, &pixel, 1, 1) ) {
267 SDL_SetError( 280 SDL_SetError(
268 "Error reading from BMP"); 281 "Error reading from BMP");
269 was_error = 1; 282 was_error = SDL_TRUE;
270 goto done; 283 goto done;
271 } 284 }
272 } 285 }
273 *(bits+i) = (pixel>>shift); 286 *(bits+i) = (pixel>>shift);
274 pixel <<= ExpandBMP; 287 pixel <<= ExpandBMP;
277 290
278 default: 291 default:
279 if ( SDL_RWread(src, bits, 1, surface->pitch) 292 if ( SDL_RWread(src, bits, 1, surface->pitch)
280 != surface->pitch ) { 293 != surface->pitch ) {
281 SDL_Error(SDL_EFREAD); 294 SDL_Error(SDL_EFREAD);
282 was_error = 1; 295 was_error = SDL_TRUE;
283 goto done; 296 goto done;
284 } 297 }
285 #if SDL_BYTEORDER == SDL_BIG_ENDIAN 298 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
286 /* Byte-swap the pixels if needed. Note that the 24bpp 299 /* Byte-swap the pixels if needed. Note that the 24bpp
287 case has already been taken care of above. */ 300 case has already been taken care of above. */
308 if ( pad ) { 321 if ( pad ) {
309 Uint8 padbyte; 322 Uint8 padbyte;
310 for ( i=0; i<pad; ++i ) { 323 for ( i=0; i<pad; ++i ) {
311 SDL_RWread(src, &padbyte, 1, 1); 324 SDL_RWread(src, &padbyte, 1, 1);
312 } 325 }
326 }
327 if ( topDown ) {
328 bits += surface->pitch;
329 } else {
330 bits -= surface->pitch;
313 } 331 }
314 } 332 }
315 done: 333 done:
316 if ( was_error ) { 334 if ( was_error ) {
317 if ( src ) { 335 if ( src ) {