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: */