Mercurial > sdl-ios-xcode
comparison src/video/SDL_bmp.c @ 3310:b907e83deb88
Fixed crash with right side up BMP files
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 26 Sep 2009 06:21:36 +0000 |
parents | 69ab1117dd3b |
children | 74d2f44a85de |
comparison
equal
deleted
inserted
replaced
3309:e1f161215f72 | 3310:b907e83deb88 |
---|---|
47 | 47 |
48 | 48 |
49 SDL_Surface * | 49 SDL_Surface * |
50 SDL_LoadBMP_RW(SDL_RWops * src, int freesrc) | 50 SDL_LoadBMP_RW(SDL_RWops * src, int freesrc) |
51 { | 51 { |
52 int was_error; | 52 SDL_bool was_error; |
53 long fp_offset; | 53 long fp_offset; |
54 int bmpPitch; | 54 int bmpPitch; |
55 int i, pad; | 55 int i, pad; |
56 SDL_Surface *surface; | 56 SDL_Surface *surface; |
57 Uint32 Rmask; | 57 Uint32 Rmask; |
58 Uint32 Gmask; | 58 Uint32 Gmask; |
59 Uint32 Bmask; | 59 Uint32 Bmask; |
60 SDL_Palette *palette; | 60 SDL_Palette *palette; |
61 Uint8 *bits; | 61 Uint8 *bits; |
62 Uint8 *top, *end; | |
63 SDL_bool topDown; | |
62 int ExpandBMP; | 64 int ExpandBMP; |
63 | 65 |
64 /* The Win32 BMP file header (14 bytes) */ | 66 /* The Win32 BMP file header (14 bytes) */ |
65 char magic[2]; | 67 char magic[2]; |
66 Uint32 bfSize; | 68 Uint32 bfSize; |
81 Uint32 biClrUsed; | 83 Uint32 biClrUsed; |
82 Uint32 biClrImportant; | 84 Uint32 biClrImportant; |
83 | 85 |
84 /* Make sure we are passed a valid data source */ | 86 /* Make sure we are passed a valid data source */ |
85 surface = NULL; | 87 surface = NULL; |
86 was_error = 0; | 88 was_error = SDL_FALSE; |
87 if (src == NULL) { | 89 if (src == NULL) { |
88 was_error = 1; | 90 was_error = SDL_TRUE; |
89 goto done; | 91 goto done; |
90 } | 92 } |
91 | 93 |
92 /* Read in the BMP file header */ | 94 /* Read in the BMP file header */ |
93 fp_offset = SDL_RWtell(src); | 95 fp_offset = SDL_RWtell(src); |
94 SDL_ClearError(); | 96 SDL_ClearError(); |
95 if (SDL_RWread(src, magic, 1, 2) != 2) { | 97 if (SDL_RWread(src, magic, 1, 2) != 2) { |
96 SDL_Error(SDL_EFREAD); | 98 SDL_Error(SDL_EFREAD); |
97 was_error = 1; | 99 was_error = SDL_TRUE; |
98 goto done; | 100 goto done; |
99 } | 101 } |
100 if (SDL_strncmp(magic, "BM", 2) != 0) { | 102 if (SDL_strncmp(magic, "BM", 2) != 0) { |
101 SDL_SetError("File is not a Windows BMP file"); | 103 SDL_SetError("File is not a Windows BMP file"); |
102 was_error = 1; | 104 was_error = SDL_TRUE; |
103 goto done; | 105 goto done; |
104 } | 106 } |
105 bfSize = SDL_ReadLE32(src); | 107 bfSize = SDL_ReadLE32(src); |
106 bfReserved1 = SDL_ReadLE16(src); | 108 bfReserved1 = SDL_ReadLE16(src); |
107 bfReserved2 = SDL_ReadLE16(src); | 109 bfReserved2 = SDL_ReadLE16(src); |
130 biXPelsPerMeter = SDL_ReadLE32(src); | 132 biXPelsPerMeter = SDL_ReadLE32(src); |
131 biYPelsPerMeter = SDL_ReadLE32(src); | 133 biYPelsPerMeter = SDL_ReadLE32(src); |
132 biClrUsed = SDL_ReadLE32(src); | 134 biClrUsed = SDL_ReadLE32(src); |
133 biClrImportant = SDL_ReadLE32(src); | 135 biClrImportant = SDL_ReadLE32(src); |
134 } | 136 } |
137 if (biHeight < 0) { | |
138 topDown = SDL_TRUE; | |
139 biHeight = -biHeight; | |
140 } else { | |
141 topDown = SDL_FALSE; | |
142 } | |
135 | 143 |
136 /* Check for read error */ | 144 /* Check for read error */ |
137 if (SDL_strcmp(SDL_GetError(), "") != 0) { | 145 if (SDL_strcmp(SDL_GetError(), "") != 0) { |
138 was_error = 1; | 146 was_error = SDL_TRUE; |
139 goto done; | 147 goto done; |
140 } | 148 } |
141 | 149 |
142 /* Expand 1 and 4 bit bitmaps to 8 bits per pixel */ | 150 /* Expand 1 and 4 bit bitmaps to 8 bits per pixel */ |
143 switch (biBitCount) { | 151 switch (biBitCount) { |
197 break; | 205 break; |
198 } | 206 } |
199 break; | 207 break; |
200 default: | 208 default: |
201 SDL_SetError("Compressed BMP files not supported"); | 209 SDL_SetError("Compressed BMP files not supported"); |
202 was_error = 1; | 210 was_error = SDL_TRUE; |
203 goto done; | 211 goto done; |
204 } | 212 } |
205 | 213 |
206 /* Create a compatible surface, note that the colors are RGB ordered */ | 214 /* Create a compatible surface, note that the colors are RGB ordered */ |
207 surface = | 215 surface = |
208 SDL_CreateRGBSurface(0, biWidth, biHeight, biBitCount, Rmask, Gmask, | 216 SDL_CreateRGBSurface(0, biWidth, biHeight, biBitCount, Rmask, Gmask, |
209 Bmask, 0); | 217 Bmask, 0); |
210 if (surface == NULL) { | 218 if (surface == NULL) { |
211 was_error = 1; | 219 was_error = SDL_TRUE; |
212 goto done; | 220 goto done; |
213 } | 221 } |
214 | 222 |
215 /* Load the palette, if any */ | 223 /* Load the palette, if any */ |
216 palette = (surface->format)->palette; | 224 palette = (surface->format)->palette; |
224 (SDL_Color *) SDL_realloc(palette->colors, | 232 (SDL_Color *) SDL_realloc(palette->colors, |
225 palette->ncolors * | 233 palette->ncolors * |
226 sizeof(*palette->colors)); | 234 sizeof(*palette->colors)); |
227 if (!palette->colors) { | 235 if (!palette->colors) { |
228 SDL_OutOfMemory(); | 236 SDL_OutOfMemory(); |
229 was_error = 1; | 237 was_error = SDL_TRUE; |
230 goto done; | 238 goto done; |
231 } | 239 } |
232 } else if ((int) biClrUsed < palette->ncolors) { | 240 } else if ((int) biClrUsed < palette->ncolors) { |
233 palette->ncolors = biClrUsed; | 241 palette->ncolors = biClrUsed; |
234 } | 242 } |
250 } | 258 } |
251 | 259 |
252 /* Read the surface pixels. Note that the bmp image is upside down */ | 260 /* Read the surface pixels. Note that the bmp image is upside down */ |
253 if (SDL_RWseek(src, fp_offset + bfOffBits, RW_SEEK_SET) < 0) { | 261 if (SDL_RWseek(src, fp_offset + bfOffBits, RW_SEEK_SET) < 0) { |
254 SDL_Error(SDL_EFSEEK); | 262 SDL_Error(SDL_EFSEEK); |
255 was_error = 1; | 263 was_error = SDL_TRUE; |
256 goto done; | 264 goto done; |
257 } | 265 } |
258 bits = (Uint8 *) surface->pixels + (surface->h * surface->pitch); | 266 top = (Uint8 *)surface->pixels; |
267 end = (Uint8 *)surface->pixels+(surface->h*surface->pitch); | |
259 switch (ExpandBMP) { | 268 switch (ExpandBMP) { |
260 case 1: | 269 case 1: |
261 bmpPitch = (biWidth + 7) >> 3; | 270 bmpPitch = (biWidth + 7) >> 3; |
262 pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0); | 271 pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0); |
263 break; | 272 break; |
267 break; | 276 break; |
268 default: | 277 default: |
269 pad = ((surface->pitch % 4) ? (4 - (surface->pitch % 4)) : 0); | 278 pad = ((surface->pitch % 4) ? (4 - (surface->pitch % 4)) : 0); |
270 break; | 279 break; |
271 } | 280 } |
272 while (bits > (Uint8 *) surface->pixels) { | 281 if (topDown) { |
273 bits -= surface->pitch; | 282 bits = top; |
283 } else { | |
284 bits = end - surface->pitch; | |
285 } | |
286 while (bits >= top && bits < end) { | |
274 switch (ExpandBMP) { | 287 switch (ExpandBMP) { |
275 case 1: | 288 case 1: |
276 case 4: | 289 case 4:{ |
277 { | |
278 Uint8 pixel = 0; | 290 Uint8 pixel = 0; |
279 int shift = (8 - ExpandBMP); | 291 int shift = (8 - ExpandBMP); |
280 for (i = 0; i < surface->w; ++i) { | 292 for (i = 0; i < surface->w; ++i) { |
281 if (i % (8 / ExpandBMP) == 0) { | 293 if (i % (8 / ExpandBMP) == 0) { |
282 if (!SDL_RWread(src, &pixel, 1, 1)) { | 294 if (!SDL_RWread(src, &pixel, 1, 1)) { |
283 SDL_SetError("Error reading from BMP"); | 295 SDL_SetError("Error reading from BMP"); |
284 was_error = 1; | 296 was_error = SDL_TRUE; |
285 goto done; | 297 goto done; |
286 } | 298 } |
287 } | 299 } |
288 *(bits + i) = (pixel >> shift); | 300 *(bits + i) = (pixel >> shift); |
289 pixel <<= ExpandBMP; | 301 pixel <<= ExpandBMP; |
293 | 305 |
294 default: | 306 default: |
295 if (SDL_RWread(src, bits, 1, surface->pitch) | 307 if (SDL_RWread(src, bits, 1, surface->pitch) |
296 != surface->pitch) { | 308 != surface->pitch) { |
297 SDL_Error(SDL_EFREAD); | 309 SDL_Error(SDL_EFREAD); |
298 was_error = 1; | 310 was_error = SDL_TRUE; |
299 goto done; | 311 goto done; |
300 } | 312 } |
301 #if SDL_BYTEORDER == SDL_BIG_ENDIAN | 313 #if SDL_BYTEORDER == SDL_BIG_ENDIAN |
302 /* Byte-swap the pixels if needed. Note that the 24bpp | 314 /* Byte-swap the pixels if needed. Note that the 24bpp |
303 case has already been taken care of above. */ | 315 case has already been taken care of above. */ |
304 switch (biBitCount) { | 316 switch (biBitCount) { |
305 case 15: | 317 case 15: |
306 case 16: | 318 case 16:{ |
307 { | |
308 Uint16 *pix = (Uint16 *) bits; | 319 Uint16 *pix = (Uint16 *) bits; |
309 for (i = 0; i < surface->w; i++) | 320 for (i = 0; i < surface->w; i++) |
310 pix[i] = SDL_Swap16(pix[i]); | 321 pix[i] = SDL_Swap16(pix[i]); |
311 break; | 322 break; |
312 } | 323 } |
313 | 324 |
314 case 32: | 325 case 32:{ |
315 { | |
316 Uint32 *pix = (Uint32 *) bits; | 326 Uint32 *pix = (Uint32 *) bits; |
317 for (i = 0; i < surface->w; i++) | 327 for (i = 0; i < surface->w; i++) |
318 pix[i] = SDL_Swap32(pix[i]); | 328 pix[i] = SDL_Swap32(pix[i]); |
319 break; | 329 break; |
320 } | 330 } |
326 if (pad) { | 336 if (pad) { |
327 Uint8 padbyte; | 337 Uint8 padbyte; |
328 for (i = 0; i < pad; ++i) { | 338 for (i = 0; i < pad; ++i) { |
329 SDL_RWread(src, &padbyte, 1, 1); | 339 SDL_RWread(src, &padbyte, 1, 1); |
330 } | 340 } |
341 } | |
342 if (topDown) { | |
343 bits += surface->pitch; | |
344 } else { | |
345 bits -= surface->pitch; | |
331 } | 346 } |
332 } | 347 } |
333 done: | 348 done: |
334 if (was_error) { | 349 if (was_error) { |
335 if (src) { | 350 if (src) { |