Mercurial > sdl-ios-xcode
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 ) { |