Mercurial > sdl-ios-xcode
comparison src/video/SDL_bmp.c @ 1895:c121d94672cb
SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 10 Jul 2006 21:04:37 +0000 |
parents | d910939febfa |
children | 365fe1a2aad5 |
comparison
equal
deleted
inserted
replaced
1894:c69cee13dd76 | 1895:c121d94672cb |
---|---|
43 #define BI_RLE4 2 | 43 #define BI_RLE4 2 |
44 #define BI_BITFIELDS 3 | 44 #define BI_BITFIELDS 3 |
45 #endif | 45 #endif |
46 | 46 |
47 | 47 |
48 SDL_Surface * SDL_LoadBMP_RW (SDL_RWops *src, int freesrc) | 48 SDL_Surface * |
49 SDL_LoadBMP_RW(SDL_RWops * src, int freesrc) | |
49 { | 50 { |
50 int was_error; | 51 int was_error; |
51 long fp_offset; | 52 long fp_offset; |
52 int bmpPitch; | 53 int bmpPitch; |
53 int i, pad; | 54 int i, pad; |
54 SDL_Surface *surface; | 55 SDL_Surface *surface; |
55 Uint32 Rmask; | 56 Uint32 Rmask; |
56 Uint32 Gmask; | 57 Uint32 Gmask; |
57 Uint32 Bmask; | 58 Uint32 Bmask; |
58 SDL_Palette *palette; | 59 SDL_Palette *palette; |
59 Uint8 *bits; | 60 Uint8 *bits; |
60 int ExpandBMP; | 61 int ExpandBMP; |
61 | 62 |
62 /* The Win32 BMP file header (14 bytes) */ | 63 /* The Win32 BMP file header (14 bytes) */ |
63 char magic[2]; | 64 char magic[2]; |
64 Uint32 bfSize; | 65 Uint32 bfSize; |
65 Uint16 bfReserved1; | 66 Uint16 bfReserved1; |
66 Uint16 bfReserved2; | 67 Uint16 bfReserved2; |
67 Uint32 bfOffBits; | 68 Uint32 bfOffBits; |
68 | 69 |
69 /* The Win32 BITMAPINFOHEADER struct (40 bytes) */ | 70 /* The Win32 BITMAPINFOHEADER struct (40 bytes) */ |
70 Uint32 biSize; | 71 Uint32 biSize; |
71 Sint32 biWidth; | 72 Sint32 biWidth; |
72 Sint32 biHeight; | 73 Sint32 biHeight; |
73 Uint16 biPlanes; | 74 Uint16 biPlanes; |
74 Uint16 biBitCount; | 75 Uint16 biBitCount; |
75 Uint32 biCompression; | 76 Uint32 biCompression; |
76 Uint32 biSizeImage; | 77 Uint32 biSizeImage; |
77 Sint32 biXPelsPerMeter; | 78 Sint32 biXPelsPerMeter; |
78 Sint32 biYPelsPerMeter; | 79 Sint32 biYPelsPerMeter; |
79 Uint32 biClrUsed; | 80 Uint32 biClrUsed; |
80 Uint32 biClrImportant; | 81 Uint32 biClrImportant; |
81 | 82 |
82 /* Make sure we are passed a valid data source */ | 83 /* Make sure we are passed a valid data source */ |
83 surface = NULL; | 84 surface = NULL; |
84 was_error = 0; | 85 was_error = 0; |
85 if ( src == NULL ) { | 86 if (src == NULL) { |
86 was_error = 1; | 87 was_error = 1; |
87 goto done; | 88 goto done; |
88 } | 89 } |
89 | 90 |
90 /* Read in the BMP file header */ | 91 /* Read in the BMP file header */ |
91 fp_offset = SDL_RWtell(src); | 92 fp_offset = SDL_RWtell(src); |
92 SDL_ClearError(); | 93 SDL_ClearError(); |
93 if ( SDL_RWread(src, magic, 1, 2) != 2 ) { | 94 if (SDL_RWread(src, magic, 1, 2) != 2) { |
94 SDL_Error(SDL_EFREAD); | 95 SDL_Error(SDL_EFREAD); |
95 was_error = 1; | 96 was_error = 1; |
96 goto done; | 97 goto done; |
97 } | 98 } |
98 if ( SDL_strncmp(magic, "BM", 2) != 0 ) { | 99 if (SDL_strncmp(magic, "BM", 2) != 0) { |
99 SDL_SetError("File is not a Windows BMP file"); | 100 SDL_SetError("File is not a Windows BMP file"); |
100 was_error = 1; | 101 was_error = 1; |
101 goto done; | 102 goto done; |
102 } | 103 } |
103 bfSize = SDL_ReadLE32(src); | 104 bfSize = SDL_ReadLE32(src); |
104 bfReserved1 = SDL_ReadLE16(src); | 105 bfReserved1 = SDL_ReadLE16(src); |
105 bfReserved2 = SDL_ReadLE16(src); | 106 bfReserved2 = SDL_ReadLE16(src); |
106 bfOffBits = SDL_ReadLE32(src); | 107 bfOffBits = SDL_ReadLE32(src); |
107 | 108 |
108 /* Read the Win32 BITMAPINFOHEADER */ | 109 /* Read the Win32 BITMAPINFOHEADER */ |
109 biSize = SDL_ReadLE32(src); | 110 biSize = SDL_ReadLE32(src); |
110 if ( biSize == 12 ) { | 111 if (biSize == 12) { |
111 biWidth = (Uint32)SDL_ReadLE16(src); | 112 biWidth = (Uint32) SDL_ReadLE16(src); |
112 biHeight = (Uint32)SDL_ReadLE16(src); | 113 biHeight = (Uint32) SDL_ReadLE16(src); |
113 biPlanes = SDL_ReadLE16(src); | 114 biPlanes = SDL_ReadLE16(src); |
114 biBitCount = SDL_ReadLE16(src); | 115 biBitCount = SDL_ReadLE16(src); |
115 biCompression = BI_RGB; | 116 biCompression = BI_RGB; |
116 biSizeImage = 0; | 117 biSizeImage = 0; |
117 biXPelsPerMeter = 0; | 118 biXPelsPerMeter = 0; |
118 biYPelsPerMeter = 0; | 119 biYPelsPerMeter = 0; |
119 biClrUsed = 0; | 120 biClrUsed = 0; |
120 biClrImportant = 0; | 121 biClrImportant = 0; |
121 } else { | 122 } else { |
122 biWidth = SDL_ReadLE32(src); | 123 biWidth = SDL_ReadLE32(src); |
123 biHeight = SDL_ReadLE32(src); | 124 biHeight = SDL_ReadLE32(src); |
124 biPlanes = SDL_ReadLE16(src); | 125 biPlanes = SDL_ReadLE16(src); |
125 biBitCount = SDL_ReadLE16(src); | 126 biBitCount = SDL_ReadLE16(src); |
126 biCompression = SDL_ReadLE32(src); | 127 biCompression = SDL_ReadLE32(src); |
127 biSizeImage = SDL_ReadLE32(src); | 128 biSizeImage = SDL_ReadLE32(src); |
128 biXPelsPerMeter = SDL_ReadLE32(src); | 129 biXPelsPerMeter = SDL_ReadLE32(src); |
129 biYPelsPerMeter = SDL_ReadLE32(src); | 130 biYPelsPerMeter = SDL_ReadLE32(src); |
130 biClrUsed = SDL_ReadLE32(src); | 131 biClrUsed = SDL_ReadLE32(src); |
131 biClrImportant = SDL_ReadLE32(src); | 132 biClrImportant = SDL_ReadLE32(src); |
132 } | 133 } |
133 | 134 |
134 /* Check for read error */ | 135 /* Check for read error */ |
135 if ( SDL_strcmp(SDL_GetError(), "") != 0 ) { | 136 if (SDL_strcmp(SDL_GetError(), "") != 0) { |
136 was_error = 1; | 137 was_error = 1; |
137 goto done; | 138 goto done; |
138 } | 139 } |
139 | 140 |
140 /* Expand 1 and 4 bit bitmaps to 8 bits per pixel */ | 141 /* Expand 1 and 4 bit bitmaps to 8 bits per pixel */ |
141 switch (biBitCount) { | 142 switch (biBitCount) { |
142 case 1: | 143 case 1: |
143 case 4: | 144 case 4: |
144 ExpandBMP = biBitCount; | 145 ExpandBMP = biBitCount; |
145 biBitCount = 8; | 146 biBitCount = 8; |
146 break; | 147 break; |
147 default: | 148 default: |
148 ExpandBMP = 0; | 149 ExpandBMP = 0; |
149 break; | 150 break; |
150 } | 151 } |
151 | 152 |
152 /* We don't support any BMP compression right now */ | 153 /* We don't support any BMP compression right now */ |
153 Rmask = Gmask = Bmask = 0; | 154 Rmask = Gmask = Bmask = 0; |
154 switch (biCompression) { | 155 switch (biCompression) { |
155 case BI_RGB: | 156 case BI_RGB: |
156 /* If there are no masks, use the defaults */ | 157 /* If there are no masks, use the defaults */ |
157 if ( bfOffBits == (14+biSize) ) { | 158 if (bfOffBits == (14 + biSize)) { |
158 /* Default values for the BMP format */ | 159 /* Default values for the BMP format */ |
159 switch (biBitCount) { | 160 switch (biBitCount) { |
160 case 15: | 161 case 15: |
161 case 16: | 162 case 16: |
162 Rmask = 0x7C00; | 163 Rmask = 0x7C00; |
163 Gmask = 0x03E0; | 164 Gmask = 0x03E0; |
164 Bmask = 0x001F; | 165 Bmask = 0x001F; |
165 break; | 166 break; |
166 case 24: | 167 case 24: |
167 #if SDL_BYTEORDER == SDL_BIG_ENDIAN | 168 #if SDL_BYTEORDER == SDL_BIG_ENDIAN |
168 Rmask = 0x000000FF; | 169 Rmask = 0x000000FF; |
169 Gmask = 0x0000FF00; | 170 Gmask = 0x0000FF00; |
170 Bmask = 0x00FF0000; | 171 Bmask = 0x00FF0000; |
171 break; | 172 break; |
172 #endif | 173 #endif |
173 case 32: | 174 case 32: |
174 Rmask = 0x00FF0000; | 175 Rmask = 0x00FF0000; |
175 Gmask = 0x0000FF00; | 176 Gmask = 0x0000FF00; |
176 Bmask = 0x000000FF; | 177 Bmask = 0x000000FF; |
177 break; | 178 break; |
178 default: | 179 default: |
179 break; | 180 break; |
180 } | 181 } |
181 break; | 182 break; |
182 } | 183 } |
183 /* Fall through -- read the RGB masks */ | 184 /* Fall through -- read the RGB masks */ |
184 | 185 |
185 case BI_BITFIELDS: | 186 case BI_BITFIELDS: |
186 switch (biBitCount) { | 187 switch (biBitCount) { |
187 case 15: | 188 case 15: |
188 case 16: | 189 case 16: |
189 case 32: | 190 case 32: |
190 Rmask = SDL_ReadLE32(src); | 191 Rmask = SDL_ReadLE32(src); |
191 Gmask = SDL_ReadLE32(src); | 192 Gmask = SDL_ReadLE32(src); |
192 Bmask = SDL_ReadLE32(src); | 193 Bmask = SDL_ReadLE32(src); |
193 break; | 194 break; |
194 default: | 195 default: |
195 break; | 196 break; |
196 } | 197 } |
197 break; | 198 break; |
198 default: | 199 default: |
199 SDL_SetError("Compressed BMP files not supported"); | 200 SDL_SetError("Compressed BMP files not supported"); |
200 was_error = 1; | 201 was_error = 1; |
201 goto done; | 202 goto done; |
202 } | 203 } |
203 | 204 |
204 /* Create a compatible surface, note that the colors are RGB ordered */ | 205 /* Create a compatible surface, note that the colors are RGB ordered */ |
205 surface = SDL_CreateRGBSurface(SDL_SWSURFACE, | 206 surface = |
206 biWidth, biHeight, biBitCount, Rmask, Gmask, Bmask, 0); | 207 SDL_CreateRGBSurface(0, biWidth, biHeight, biBitCount, Rmask, Gmask, |
207 if ( surface == NULL ) { | 208 Bmask, 0); |
208 was_error = 1; | 209 if (surface == NULL) { |
209 goto done; | 210 was_error = 1; |
210 } | 211 goto done; |
211 | 212 } |
212 /* Load the palette, if any */ | 213 |
213 palette = (surface->format)->palette; | 214 /* Load the palette, if any */ |
214 if ( palette ) { | 215 palette = (surface->format)->palette; |
215 if ( biClrUsed == 0 ) { | 216 if (palette) { |
216 biClrUsed = 1 << biBitCount; | 217 if (biClrUsed == 0) { |
217 } | 218 biClrUsed = 1 << biBitCount; |
218 if ( biSize == 12 ) { | 219 } |
219 for ( i = 0; i < (int)biClrUsed; ++i ) { | 220 if (biSize == 12) { |
220 SDL_RWread(src, &palette->colors[i].b, 1, 1); | 221 for (i = 0; i < (int) biClrUsed; ++i) { |
221 SDL_RWread(src, &palette->colors[i].g, 1, 1); | 222 SDL_RWread(src, &palette->colors[i].b, 1, 1); |
222 SDL_RWread(src, &palette->colors[i].r, 1, 1); | 223 SDL_RWread(src, &palette->colors[i].g, 1, 1); |
223 palette->colors[i].unused = 0; | 224 SDL_RWread(src, &palette->colors[i].r, 1, 1); |
224 } | 225 palette->colors[i].unused = SDL_ALPHA_OPAQUE; |
225 } else { | 226 } |
226 for ( i = 0; i < (int)biClrUsed; ++i ) { | 227 } else { |
227 SDL_RWread(src, &palette->colors[i].b, 1, 1); | 228 for (i = 0; i < (int) biClrUsed; ++i) { |
228 SDL_RWread(src, &palette->colors[i].g, 1, 1); | 229 SDL_RWread(src, &palette->colors[i].b, 1, 1); |
229 SDL_RWread(src, &palette->colors[i].r, 1, 1); | 230 SDL_RWread(src, &palette->colors[i].g, 1, 1); |
230 SDL_RWread(src, &palette->colors[i].unused, 1, 1); | 231 SDL_RWread(src, &palette->colors[i].r, 1, 1); |
231 } | 232 SDL_RWread(src, &palette->colors[i].unused, 1, 1); |
232 } | 233 } |
233 palette->ncolors = biClrUsed; | 234 } |
234 } | 235 } |
235 | 236 |
236 /* Read the surface pixels. Note that the bmp image is upside down */ | 237 /* Read the surface pixels. Note that the bmp image is upside down */ |
237 if ( SDL_RWseek(src, fp_offset+bfOffBits, RW_SEEK_SET) < 0 ) { | 238 if (SDL_RWseek(src, fp_offset + bfOffBits, RW_SEEK_SET) < 0) { |
238 SDL_Error(SDL_EFSEEK); | 239 SDL_Error(SDL_EFSEEK); |
239 was_error = 1; | 240 was_error = 1; |
240 goto done; | 241 goto done; |
241 } | 242 } |
242 bits = (Uint8 *)surface->pixels+(surface->h*surface->pitch); | 243 bits = (Uint8 *) surface->pixels + (surface->h * surface->pitch); |
243 switch (ExpandBMP) { | 244 switch (ExpandBMP) { |
244 case 1: | 245 case 1: |
245 bmpPitch = (biWidth + 7) >> 3; | 246 bmpPitch = (biWidth + 7) >> 3; |
246 pad = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0); | 247 pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0); |
247 break; | 248 break; |
248 case 4: | 249 case 4: |
249 bmpPitch = (biWidth + 1) >> 1; | 250 bmpPitch = (biWidth + 1) >> 1; |
250 pad = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0); | 251 pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0); |
251 break; | 252 break; |
252 default: | 253 default: |
253 pad = ((surface->pitch%4) ? | 254 pad = ((surface->pitch % 4) ? (4 - (surface->pitch % 4)) : 0); |
254 (4-(surface->pitch%4)) : 0); | 255 break; |
255 break; | 256 } |
256 } | 257 while (bits > (Uint8 *) surface->pixels) { |
257 while ( bits > (Uint8 *)surface->pixels ) { | 258 bits -= surface->pitch; |
258 bits -= surface->pitch; | 259 switch (ExpandBMP) { |
259 switch (ExpandBMP) { | 260 case 1: |
260 case 1: | 261 case 4: |
261 case 4: { | 262 { |
262 Uint8 pixel = 0; | 263 Uint8 pixel = 0; |
263 int shift = (8-ExpandBMP); | 264 int shift = (8 - ExpandBMP); |
264 for ( i=0; i<surface->w; ++i ) { | 265 for (i = 0; i < surface->w; ++i) { |
265 if ( i%(8/ExpandBMP) == 0 ) { | 266 if (i % (8 / ExpandBMP) == 0) { |
266 if ( !SDL_RWread(src, &pixel, 1, 1) ) { | 267 if (!SDL_RWread(src, &pixel, 1, 1)) { |
267 SDL_SetError( | 268 SDL_SetError("Error reading from BMP"); |
268 "Error reading from BMP"); | 269 was_error = 1; |
269 was_error = 1; | 270 goto done; |
270 goto done; | 271 } |
271 } | 272 } |
272 } | 273 *(bits + i) = (pixel >> shift); |
273 *(bits+i) = (pixel>>shift); | 274 pixel <<= ExpandBMP; |
274 pixel <<= ExpandBMP; | 275 } |
275 } } | 276 } |
276 break; | 277 break; |
277 | 278 |
278 default: | 279 default: |
279 if ( SDL_RWread(src, bits, 1, surface->pitch) | 280 if (SDL_RWread(src, bits, 1, surface->pitch) |
280 != surface->pitch ) { | 281 != surface->pitch) { |
281 SDL_Error(SDL_EFREAD); | 282 SDL_Error(SDL_EFREAD); |
282 was_error = 1; | 283 was_error = 1; |
283 goto done; | 284 goto done; |
284 } | 285 } |
285 #if SDL_BYTEORDER == SDL_BIG_ENDIAN | 286 #if SDL_BYTEORDER == SDL_BIG_ENDIAN |
286 /* Byte-swap the pixels if needed. Note that the 24bpp | 287 /* Byte-swap the pixels if needed. Note that the 24bpp |
287 case has already been taken care of above. */ | 288 case has already been taken care of above. */ |
288 switch(biBitCount) { | 289 switch (biBitCount) { |
289 case 15: | 290 case 15: |
290 case 16: { | 291 case 16: |
291 Uint16 *pix = (Uint16 *)bits; | 292 { |
292 for(i = 0; i < surface->w; i++) | 293 Uint16 *pix = (Uint16 *) bits; |
293 pix[i] = SDL_Swap16(pix[i]); | 294 for (i = 0; i < surface->w; i++) |
294 break; | 295 pix[i] = SDL_Swap16(pix[i]); |
295 } | 296 break; |
296 | 297 } |
297 case 32: { | 298 |
298 Uint32 *pix = (Uint32 *)bits; | 299 case 32: |
299 for(i = 0; i < surface->w; i++) | 300 { |
300 pix[i] = SDL_Swap32(pix[i]); | 301 Uint32 *pix = (Uint32 *) bits; |
301 break; | 302 for (i = 0; i < surface->w; i++) |
302 } | 303 pix[i] = SDL_Swap32(pix[i]); |
303 } | 304 break; |
305 } | |
306 } | |
304 #endif | 307 #endif |
305 break; | 308 break; |
306 } | 309 } |
307 /* Skip padding bytes, ugh */ | 310 /* Skip padding bytes, ugh */ |
308 if ( pad ) { | 311 if (pad) { |
309 Uint8 padbyte; | 312 Uint8 padbyte; |
310 for ( i=0; i<pad; ++i ) { | 313 for (i = 0; i < pad; ++i) { |
311 SDL_RWread(src, &padbyte, 1, 1); | 314 SDL_RWread(src, &padbyte, 1, 1); |
312 } | 315 } |
313 } | 316 } |
314 } | 317 } |
315 done: | 318 done: |
316 if ( was_error ) { | 319 if (was_error) { |
317 if ( src ) { | 320 if (src) { |
318 SDL_RWseek(src, fp_offset, RW_SEEK_SET); | 321 SDL_RWseek(src, fp_offset, RW_SEEK_SET); |
319 } | 322 } |
320 if ( surface ) { | 323 if (surface) { |
321 SDL_FreeSurface(surface); | 324 SDL_FreeSurface(surface); |
322 } | 325 } |
323 surface = NULL; | 326 surface = NULL; |
324 } | 327 } |
325 if ( freesrc && src ) { | 328 if (freesrc && src) { |
326 SDL_RWclose(src); | 329 SDL_RWclose(src); |
327 } | 330 } |
328 return(surface); | 331 return (surface); |
329 } | 332 } |
330 | 333 |
331 int SDL_SaveBMP_RW (SDL_Surface *saveme, SDL_RWops *dst, int freedst) | 334 int |
335 SDL_SaveBMP_RW(SDL_Surface * saveme, SDL_RWops * dst, int freedst) | |
332 { | 336 { |
333 long fp_offset; | 337 long fp_offset; |
334 int i, pad; | 338 int i, pad; |
335 SDL_Surface *surface; | 339 SDL_Surface *surface; |
336 Uint8 *bits; | 340 Uint8 *bits; |
337 | 341 |
338 /* The Win32 BMP file header (14 bytes) */ | 342 /* The Win32 BMP file header (14 bytes) */ |
339 char magic[2] = { 'B', 'M' }; | 343 char magic[2] = { 'B', 'M' }; |
340 Uint32 bfSize; | 344 Uint32 bfSize; |
341 Uint16 bfReserved1; | 345 Uint16 bfReserved1; |
342 Uint16 bfReserved2; | 346 Uint16 bfReserved2; |
343 Uint32 bfOffBits; | 347 Uint32 bfOffBits; |
344 | 348 |
345 /* The Win32 BITMAPINFOHEADER struct (40 bytes) */ | 349 /* The Win32 BITMAPINFOHEADER struct (40 bytes) */ |
346 Uint32 biSize; | 350 Uint32 biSize; |
347 Sint32 biWidth; | 351 Sint32 biWidth; |
348 Sint32 biHeight; | 352 Sint32 biHeight; |
349 Uint16 biPlanes; | 353 Uint16 biPlanes; |
350 Uint16 biBitCount; | 354 Uint16 biBitCount; |
351 Uint32 biCompression; | 355 Uint32 biCompression; |
352 Uint32 biSizeImage; | 356 Uint32 biSizeImage; |
353 Sint32 biXPelsPerMeter; | 357 Sint32 biXPelsPerMeter; |
354 Sint32 biYPelsPerMeter; | 358 Sint32 biYPelsPerMeter; |
355 Uint32 biClrUsed; | 359 Uint32 biClrUsed; |
356 Uint32 biClrImportant; | 360 Uint32 biClrImportant; |
357 | 361 |
358 /* Make sure we have somewhere to save */ | 362 /* Make sure we have somewhere to save */ |
359 surface = NULL; | 363 surface = NULL; |
360 if ( dst ) { | 364 if (dst) { |
361 if ( saveme->format->palette ) { | 365 if (saveme->format->palette) { |
362 if ( saveme->format->BitsPerPixel == 8 ) { | 366 if (saveme->format->BitsPerPixel == 8) { |
363 surface = saveme; | 367 surface = saveme; |
364 } else { | 368 } else { |
365 SDL_SetError("%d bpp BMP files not supported", | 369 SDL_SetError("%d bpp BMP files not supported", |
366 saveme->format->BitsPerPixel); | 370 saveme->format->BitsPerPixel); |
367 } | 371 } |
368 } | 372 } else if ((saveme->format->BitsPerPixel == 24) && |
369 else if ( (saveme->format->BitsPerPixel == 24) && | |
370 #if SDL_BYTEORDER == SDL_LIL_ENDIAN | 373 #if SDL_BYTEORDER == SDL_LIL_ENDIAN |
371 (saveme->format->Rmask == 0x00FF0000) && | 374 (saveme->format->Rmask == 0x00FF0000) && |
372 (saveme->format->Gmask == 0x0000FF00) && | 375 (saveme->format->Gmask == 0x0000FF00) && |
373 (saveme->format->Bmask == 0x000000FF) | 376 (saveme->format->Bmask == 0x000000FF) |
374 #else | 377 #else |
375 (saveme->format->Rmask == 0x000000FF) && | 378 (saveme->format->Rmask == 0x000000FF) && |
376 (saveme->format->Gmask == 0x0000FF00) && | 379 (saveme->format->Gmask == 0x0000FF00) && |
377 (saveme->format->Bmask == 0x00FF0000) | 380 (saveme->format->Bmask == 0x00FF0000) |
378 #endif | 381 #endif |
379 ) { | 382 ) { |
380 surface = saveme; | 383 surface = saveme; |
381 } else { | 384 } else { |
382 SDL_Rect bounds; | 385 SDL_Rect bounds; |
383 | 386 |
384 /* Convert to 24 bits per pixel */ | 387 /* Convert to 24 bits per pixel */ |
385 surface = SDL_CreateRGBSurface(SDL_SWSURFACE, | 388 surface = SDL_CreateRGBSurface(0, saveme->w, saveme->h, 24, |
386 saveme->w, saveme->h, 24, | |
387 #if SDL_BYTEORDER == SDL_LIL_ENDIAN | 389 #if SDL_BYTEORDER == SDL_LIL_ENDIAN |
388 0x00FF0000, 0x0000FF00, 0x000000FF, | 390 0x00FF0000, 0x0000FF00, 0x000000FF, |
389 #else | 391 #else |
390 0x000000FF, 0x0000FF00, 0x00FF0000, | 392 0x000000FF, 0x0000FF00, 0x00FF0000, |
391 #endif | 393 #endif |
392 0); | 394 0); |
393 if ( surface != NULL ) { | 395 if (surface != NULL) { |
394 bounds.x = 0; | 396 bounds.x = 0; |
395 bounds.y = 0; | 397 bounds.y = 0; |
396 bounds.w = saveme->w; | 398 bounds.w = saveme->w; |
397 bounds.h = saveme->h; | 399 bounds.h = saveme->h; |
398 if ( SDL_LowerBlit(saveme, &bounds, surface, | 400 if (SDL_LowerBlit(saveme, &bounds, surface, &bounds) < 0) { |
399 &bounds) < 0 ) { | 401 SDL_FreeSurface(surface); |
400 SDL_FreeSurface(surface); | 402 SDL_SetError("Couldn't convert image to 24 bpp"); |
401 SDL_SetError( | 403 surface = NULL; |
402 "Couldn't convert image to 24 bpp"); | 404 } |
403 surface = NULL; | 405 } |
404 } | 406 } |
405 } | 407 } |
406 } | 408 |
407 } | 409 if (surface && (SDL_LockSurface(surface) == 0)) { |
408 | 410 const int bw = surface->w * surface->format->BytesPerPixel; |
409 if ( surface && (SDL_LockSurface(surface) == 0) ) { | 411 |
410 const int bw = surface->w*surface->format->BytesPerPixel; | 412 /* Set the BMP file header values */ |
411 | 413 bfSize = 0; /* We'll write this when we're done */ |
412 /* Set the BMP file header values */ | 414 bfReserved1 = 0; |
413 bfSize = 0; /* We'll write this when we're done */ | 415 bfReserved2 = 0; |
414 bfReserved1 = 0; | 416 bfOffBits = 0; /* We'll write this when we're done */ |
415 bfReserved2 = 0; | 417 |
416 bfOffBits = 0; /* We'll write this when we're done */ | 418 /* Write the BMP file header values */ |
417 | 419 fp_offset = SDL_RWtell(dst); |
418 /* Write the BMP file header values */ | 420 SDL_ClearError(); |
419 fp_offset = SDL_RWtell(dst); | 421 SDL_RWwrite(dst, magic, 2, 1); |
420 SDL_ClearError(); | 422 SDL_WriteLE32(dst, bfSize); |
421 SDL_RWwrite(dst, magic, 2, 1); | 423 SDL_WriteLE16(dst, bfReserved1); |
422 SDL_WriteLE32(dst, bfSize); | 424 SDL_WriteLE16(dst, bfReserved2); |
423 SDL_WriteLE16(dst, bfReserved1); | 425 SDL_WriteLE32(dst, bfOffBits); |
424 SDL_WriteLE16(dst, bfReserved2); | 426 |
425 SDL_WriteLE32(dst, bfOffBits); | 427 /* Set the BMP info values */ |
426 | 428 biSize = 40; |
427 /* Set the BMP info values */ | 429 biWidth = surface->w; |
428 biSize = 40; | 430 biHeight = surface->h; |
429 biWidth = surface->w; | 431 biPlanes = 1; |
430 biHeight = surface->h; | 432 biBitCount = surface->format->BitsPerPixel; |
431 biPlanes = 1; | 433 biCompression = BI_RGB; |
432 biBitCount = surface->format->BitsPerPixel; | 434 biSizeImage = surface->h * surface->pitch; |
433 biCompression = BI_RGB; | 435 biXPelsPerMeter = 0; |
434 biSizeImage = surface->h*surface->pitch; | 436 biYPelsPerMeter = 0; |
435 biXPelsPerMeter = 0; | 437 if (surface->format->palette) { |
436 biYPelsPerMeter = 0; | 438 biClrUsed = surface->format->palette->ncolors; |
437 if ( surface->format->palette ) { | 439 } else { |
438 biClrUsed = surface->format->palette->ncolors; | 440 biClrUsed = 0; |
439 } else { | 441 } |
440 biClrUsed = 0; | 442 biClrImportant = 0; |
441 } | 443 |
442 biClrImportant = 0; | 444 /* Write the BMP info values */ |
443 | 445 SDL_WriteLE32(dst, biSize); |
444 /* Write the BMP info values */ | 446 SDL_WriteLE32(dst, biWidth); |
445 SDL_WriteLE32(dst, biSize); | 447 SDL_WriteLE32(dst, biHeight); |
446 SDL_WriteLE32(dst, biWidth); | 448 SDL_WriteLE16(dst, biPlanes); |
447 SDL_WriteLE32(dst, biHeight); | 449 SDL_WriteLE16(dst, biBitCount); |
448 SDL_WriteLE16(dst, biPlanes); | 450 SDL_WriteLE32(dst, biCompression); |
449 SDL_WriteLE16(dst, biBitCount); | 451 SDL_WriteLE32(dst, biSizeImage); |
450 SDL_WriteLE32(dst, biCompression); | 452 SDL_WriteLE32(dst, biXPelsPerMeter); |
451 SDL_WriteLE32(dst, biSizeImage); | 453 SDL_WriteLE32(dst, biYPelsPerMeter); |
452 SDL_WriteLE32(dst, biXPelsPerMeter); | 454 SDL_WriteLE32(dst, biClrUsed); |
453 SDL_WriteLE32(dst, biYPelsPerMeter); | 455 SDL_WriteLE32(dst, biClrImportant); |
454 SDL_WriteLE32(dst, biClrUsed); | 456 |
455 SDL_WriteLE32(dst, biClrImportant); | 457 /* Write the palette (in BGR color order) */ |
456 | 458 if (surface->format->palette) { |
457 /* Write the palette (in BGR color order) */ | 459 SDL_Color *colors; |
458 if ( surface->format->palette ) { | 460 int ncolors; |
459 SDL_Color *colors; | 461 |
460 int ncolors; | 462 colors = surface->format->palette->colors; |
461 | 463 ncolors = surface->format->palette->ncolors; |
462 colors = surface->format->palette->colors; | 464 for (i = 0; i < ncolors; ++i) { |
463 ncolors = surface->format->palette->ncolors; | 465 SDL_RWwrite(dst, &colors[i].b, 1, 1); |
464 for ( i=0; i<ncolors; ++i ) { | 466 SDL_RWwrite(dst, &colors[i].g, 1, 1); |
465 SDL_RWwrite(dst, &colors[i].b, 1, 1); | 467 SDL_RWwrite(dst, &colors[i].r, 1, 1); |
466 SDL_RWwrite(dst, &colors[i].g, 1, 1); | 468 SDL_RWwrite(dst, &colors[i].unused, 1, 1); |
467 SDL_RWwrite(dst, &colors[i].r, 1, 1); | 469 } |
468 SDL_RWwrite(dst, &colors[i].unused, 1, 1); | 470 } |
469 } | 471 |
470 } | 472 /* Write the bitmap offset */ |
471 | 473 bfOffBits = SDL_RWtell(dst) - fp_offset; |
472 /* Write the bitmap offset */ | 474 if (SDL_RWseek(dst, fp_offset + 10, RW_SEEK_SET) < 0) { |
473 bfOffBits = SDL_RWtell(dst)-fp_offset; | 475 SDL_Error(SDL_EFSEEK); |
474 if ( SDL_RWseek(dst, fp_offset+10, RW_SEEK_SET) < 0 ) { | 476 } |
475 SDL_Error(SDL_EFSEEK); | 477 SDL_WriteLE32(dst, bfOffBits); |
476 } | 478 if (SDL_RWseek(dst, fp_offset + bfOffBits, RW_SEEK_SET) < 0) { |
477 SDL_WriteLE32(dst, bfOffBits); | 479 SDL_Error(SDL_EFSEEK); |
478 if ( SDL_RWseek(dst, fp_offset+bfOffBits, RW_SEEK_SET) < 0 ) { | 480 } |
479 SDL_Error(SDL_EFSEEK); | 481 |
480 } | 482 /* Write the bitmap image upside down */ |
481 | 483 bits = (Uint8 *) surface->pixels + (surface->h * surface->pitch); |
482 /* Write the bitmap image upside down */ | 484 pad = ((bw % 4) ? (4 - (bw % 4)) : 0); |
483 bits = (Uint8 *)surface->pixels+(surface->h*surface->pitch); | 485 while (bits > (Uint8 *) surface->pixels) { |
484 pad = ((bw%4) ? (4-(bw%4)) : 0); | 486 bits -= surface->pitch; |
485 while ( bits > (Uint8 *)surface->pixels ) { | 487 if (SDL_RWwrite(dst, bits, 1, bw) != bw) { |
486 bits -= surface->pitch; | 488 SDL_Error(SDL_EFWRITE); |
487 if ( SDL_RWwrite(dst, bits, 1, bw) != bw) { | 489 break; |
488 SDL_Error(SDL_EFWRITE); | 490 } |
489 break; | 491 if (pad) { |
490 } | 492 const Uint8 padbyte = 0; |
491 if ( pad ) { | 493 for (i = 0; i < pad; ++i) { |
492 const Uint8 padbyte = 0; | 494 SDL_RWwrite(dst, &padbyte, 1, 1); |
493 for ( i=0; i<pad; ++i ) { | 495 } |
494 SDL_RWwrite(dst, &padbyte, 1, 1); | 496 } |
495 } | 497 } |
496 } | 498 |
497 } | 499 /* Write the BMP file size */ |
498 | 500 bfSize = SDL_RWtell(dst) - fp_offset; |
499 /* Write the BMP file size */ | 501 if (SDL_RWseek(dst, fp_offset + 2, RW_SEEK_SET) < 0) { |
500 bfSize = SDL_RWtell(dst)-fp_offset; | 502 SDL_Error(SDL_EFSEEK); |
501 if ( SDL_RWseek(dst, fp_offset+2, RW_SEEK_SET) < 0 ) { | 503 } |
502 SDL_Error(SDL_EFSEEK); | 504 SDL_WriteLE32(dst, bfSize); |
503 } | 505 if (SDL_RWseek(dst, fp_offset + bfSize, RW_SEEK_SET) < 0) { |
504 SDL_WriteLE32(dst, bfSize); | 506 SDL_Error(SDL_EFSEEK); |
505 if ( SDL_RWseek(dst, fp_offset+bfSize, RW_SEEK_SET) < 0 ) { | 507 } |
506 SDL_Error(SDL_EFSEEK); | 508 |
507 } | 509 /* Close it up.. */ |
508 | 510 SDL_UnlockSurface(surface); |
509 /* Close it up.. */ | 511 if (surface != saveme) { |
510 SDL_UnlockSurface(surface); | 512 SDL_FreeSurface(surface); |
511 if ( surface != saveme ) { | 513 } |
512 SDL_FreeSurface(surface); | 514 } |
513 } | 515 |
514 } | 516 if (freedst && dst) { |
515 | 517 SDL_RWclose(dst); |
516 if ( freedst && dst ) { | 518 } |
517 SDL_RWclose(dst); | 519 return ((SDL_strcmp(SDL_GetError(), "") == 0) ? 0 : -1); |
518 } | |
519 return((SDL_strcmp(SDL_GetError(), "") == 0) ? 0 : -1); | |
520 } | 520 } |
521 | |
522 /* vi: set ts=4 sw=4 expandtab: */ |