Mercurial > sdl-ios-xcode
comparison src/video/SDL_bmp.c @ 3024:1a08749aebce
Add SDL_LoadICO_RW to SDL. Loads best quality icon from *.ico file.
author | Couriersud <couriersud@arcor.de> |
---|---|
date | Sun, 11 Jan 2009 23:56:19 +0000 |
parents | 502adab079a4 |
children | 69ab1117dd3b |
comparison
equal
deleted
inserted
replaced
3023:d72a0dd80e8b | 3024:1a08749aebce |
---|---|
43 #define BI_RLE8 1 | 43 #define BI_RLE8 1 |
44 #define BI_RLE4 2 | 44 #define BI_RLE4 2 |
45 #define BI_BITFIELDS 3 | 45 #define BI_BITFIELDS 3 |
46 #endif | 46 #endif |
47 | 47 |
48 | |
49 static Uint8 | |
50 SDL_Read8(SDL_RWops * src) | |
51 { | |
52 Uint8 value; | |
53 | |
54 SDL_RWread(src, &value, 1, 1); | |
55 return (value); | |
56 } | |
57 | |
58 SDL_Surface * | |
59 SDL_LoadICO_RW(SDL_RWops * src, int freesrc) | |
60 { | |
61 int was_error; | |
62 long fp_offset; | |
63 int bmpPitch; | |
64 int i, pad; | |
65 SDL_Surface *surface; | |
66 Uint32 Rmask; | |
67 Uint32 Gmask; | |
68 Uint32 Bmask; | |
69 Uint8 *bits; | |
70 int ExpandBMP; | |
71 int maxCol = 0; | |
72 int icoOfs = 0; | |
73 Uint32 palette[256]; | |
74 | |
75 /* The Win32 ICO file header (14 bytes) */ | |
76 Uint16 bfReserved; | |
77 Uint16 bfType; | |
78 Uint16 bfCount; | |
79 | |
80 /* The Win32 BITMAPINFOHEADER struct (40 bytes) */ | |
81 Uint32 biSize; | |
82 Sint32 biWidth; | |
83 Sint32 biHeight; | |
84 Uint16 biPlanes; | |
85 Uint16 biBitCount; | |
86 Uint32 biCompression; | |
87 Uint32 biSizeImage; | |
88 Sint32 biXPelsPerMeter; | |
89 Sint32 biYPelsPerMeter; | |
90 Uint32 biClrUsed; | |
91 Uint32 biClrImportant; | |
92 | |
93 /* Make sure we are passed a valid data source */ | |
94 surface = NULL; | |
95 was_error = 0; | |
96 if (src == NULL) { | |
97 was_error = 1; | |
98 goto done; | |
99 } | |
100 | |
101 /* Read in the ICO file header */ | |
102 fp_offset = SDL_RWtell(src); | |
103 SDL_ClearError(); | |
104 | |
105 bfReserved = SDL_ReadLE16(src); | |
106 bfType = SDL_ReadLE16(src); | |
107 bfCount = SDL_ReadLE16(src); | |
108 if ((bfType != 1 && bfType != 2) || (bfCount == 0)) { | |
109 SDL_SetError("File is not a Windows ICO file"); | |
110 was_error = 1; | |
111 goto done; | |
112 } | |
113 | |
114 /* Read the Win32 Icon Directory */ | |
115 for (i = 0; i < bfCount; i++) { | |
116 /* Icon Directory Entries */ | |
117 int bWidth = SDL_Read8(src); /* Uint8, but 0 = 256 ! */ | |
118 int bHeight = SDL_Read8(src); /* Uint8, but 0 = 256 ! */ | |
119 int bColorCount = SDL_Read8(src); /* Uint8, but 0 = 256 ! */ | |
120 Uint8 bReserved = SDL_Read8(src); | |
121 Uint16 wPlanes = SDL_ReadLE16(src); | |
122 Uint16 wBitCount = SDL_ReadLE16(src); | |
123 Uint32 dwBytesInRes = SDL_ReadLE32(src); | |
124 Uint32 dwImageOffset = SDL_ReadLE32(src); | |
125 | |
126 if (!bWidth) | |
127 bWidth = 256; | |
128 if (!bHeight) | |
129 bHeight = 256; | |
130 if (!bColorCount) | |
131 bColorCount = 256; | |
132 | |
133 //printf("%dx%d@%d - %08x\n", bWidth, bHeight, bColorCount, dwImageOffset); | |
134 if (bColorCount > maxCol) { | |
135 maxCol = bColorCount; | |
136 icoOfs = dwImageOffset; | |
137 //printf("marked\n"); | |
138 } | |
139 } | |
140 | |
141 /* Advance to the DIB Data */ | |
142 if (SDL_RWseek(src, icoOfs, RW_SEEK_SET) < 0) { | |
143 SDL_Error(SDL_EFSEEK); | |
144 was_error = 1; | |
145 goto done; | |
146 } | |
147 | |
148 /* Read the Win32 BITMAPINFOHEADER */ | |
149 biSize = SDL_ReadLE32(src); | |
150 if (biSize == 40) { | |
151 biWidth = SDL_ReadLE32(src); | |
152 biHeight = SDL_ReadLE32(src); | |
153 biPlanes = SDL_ReadLE16(src); | |
154 biBitCount = SDL_ReadLE16(src); | |
155 biCompression = SDL_ReadLE32(src); | |
156 biSizeImage = SDL_ReadLE32(src); | |
157 biXPelsPerMeter = SDL_ReadLE32(src); | |
158 biYPelsPerMeter = SDL_ReadLE32(src); | |
159 biClrUsed = SDL_ReadLE32(src); | |
160 biClrImportant = SDL_ReadLE32(src); | |
161 } else { | |
162 SDL_SetError("Unsupported ICO bitmap format"); | |
163 was_error = 1; | |
164 goto done; | |
165 } | |
166 | |
167 /* Check for read error */ | |
168 if (SDL_strcmp(SDL_GetError(), "") != 0) { | |
169 was_error = 1; | |
170 goto done; | |
171 } | |
172 | |
173 /* We don't support any BMP compression right now */ | |
174 switch (biCompression) { | |
175 case BI_RGB: | |
176 /* Default values for the BMP format */ | |
177 switch (biBitCount) { | |
178 case 1: | |
179 case 4: | |
180 ExpandBMP = biBitCount; | |
181 biBitCount = 8; | |
182 break; | |
183 case 8: | |
184 ExpandBMP = 8; | |
185 break; | |
186 case 32: | |
187 Rmask = 0x00FF0000; | |
188 Gmask = 0x0000FF00; | |
189 Bmask = 0x000000FF; | |
190 ExpandBMP = 0; | |
191 break; | |
192 default: | |
193 SDL_SetError("ICO file with unsupported bit count"); | |
194 was_error = 1; | |
195 goto done; | |
196 } | |
197 break; | |
198 default: | |
199 SDL_SetError("Compressed ICO files not supported"); | |
200 was_error = 1; | |
201 goto done; | |
202 } | |
203 | |
204 /* Create a RGBA surface */ | |
205 biHeight = biHeight >> 1; | |
206 //printf("%d x %d\n", biWidth, biHeight); | |
207 surface = | |
208 SDL_CreateRGBSurface(0, biWidth, biHeight, 32, 0x00FF0000, | |
209 0x0000FF00, 0x000000FF, 0xFF000000); | |
210 if (surface == NULL) { | |
211 was_error = 1; | |
212 goto done; | |
213 } | |
214 | |
215 /* Load the palette, if any */ | |
216 //printf("bc %d bused %d\n", biBitCount, biClrUsed); | |
217 if (biBitCount <= 8) { | |
218 if (biClrUsed == 0) { | |
219 biClrUsed = 1 << biBitCount; | |
220 } | |
221 for (i = 0; i < (int) biClrUsed; ++i) { | |
222 SDL_RWread(src, &palette[i], 4, 1); | |
223 } | |
224 } | |
225 | |
226 /* Read the surface pixels. Note that the bmp image is upside down */ | |
227 bits = (Uint8 *) surface->pixels + (surface->h * surface->pitch); | |
228 switch (ExpandBMP) { | |
229 case 1: | |
230 bmpPitch = (biWidth + 7) >> 3; | |
231 pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0); | |
232 break; | |
233 case 4: | |
234 bmpPitch = (biWidth + 1) >> 1; | |
235 pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0); | |
236 break; | |
237 case 8: | |
238 bmpPitch = biWidth; | |
239 pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0); | |
240 break; | |
241 default: | |
242 bmpPitch = biWidth * 4; | |
243 pad = 0; | |
244 break; | |
245 } | |
246 while (bits > (Uint8 *) surface->pixels) { | |
247 bits -= surface->pitch; | |
248 switch (ExpandBMP) { | |
249 case 1: | |
250 case 4: | |
251 case 8: | |
252 { | |
253 Uint8 pixel = 0; | |
254 int shift = (8 - ExpandBMP); | |
255 for (i = 0; i < surface->w; ++i) { | |
256 if (i % (8 / ExpandBMP) == 0) { | |
257 if (!SDL_RWread(src, &pixel, 1, 1)) { | |
258 SDL_SetError("Error reading from ICO"); | |
259 was_error = 1; | |
260 goto done; | |
261 } | |
262 } | |
263 *((Uint32 *) bits + i) = (palette[pixel >> shift]); | |
264 pixel <<= ExpandBMP; | |
265 } | |
266 } | |
267 break; | |
268 | |
269 default: | |
270 if (SDL_RWread(src, bits, 1, surface->pitch) | |
271 != surface->pitch) { | |
272 SDL_Error(SDL_EFREAD); | |
273 was_error = 1; | |
274 goto done; | |
275 } | |
276 break; | |
277 } | |
278 /* Skip padding bytes, ugh */ | |
279 if (pad) { | |
280 Uint8 padbyte; | |
281 for (i = 0; i < pad; ++i) { | |
282 SDL_RWread(src, &padbyte, 1, 1); | |
283 } | |
284 } | |
285 } | |
286 /* Read the mask pixels. Note that the bmp image is upside down */ | |
287 bits = (Uint8 *) surface->pixels + (surface->h * surface->pitch); | |
288 ExpandBMP = 1; | |
289 bmpPitch = (biWidth + 7) >> 3; | |
290 pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0); | |
291 while (bits > (Uint8 *) surface->pixels) { | |
292 Uint8 pixel = 0; | |
293 int shift = (8 - ExpandBMP); | |
294 | |
295 bits -= surface->pitch; | |
296 for (i = 0; i < surface->w; ++i) { | |
297 if (i % (8 / ExpandBMP) == 0) { | |
298 if (!SDL_RWread(src, &pixel, 1, 1)) { | |
299 SDL_SetError("Error reading from ICO"); | |
300 was_error = 1; | |
301 goto done; | |
302 } | |
303 } | |
304 *((Uint32 *) bits + i) |= ((pixel >> shift) ? 0 : 0xFF000000); | |
305 pixel <<= ExpandBMP; | |
306 } | |
307 /* Skip padding bytes, ugh */ | |
308 if (pad) { | |
309 Uint8 padbyte; | |
310 for (i = 0; i < pad; ++i) { | |
311 SDL_RWread(src, &padbyte, 1, 1); | |
312 } | |
313 } | |
314 } | |
315 done: | |
316 if (was_error) { | |
317 if (src) { | |
318 SDL_RWseek(src, fp_offset, RW_SEEK_SET); | |
319 } | |
320 if (surface) { | |
321 SDL_FreeSurface(surface); | |
322 } | |
323 surface = NULL; | |
324 } | |
325 if (freesrc && src) { | |
326 SDL_RWclose(src); | |
327 } | |
328 return (surface); | |
329 } | |
48 | 330 |
49 SDL_Surface * | 331 SDL_Surface * |
50 SDL_LoadBMP_RW(SDL_RWops * src, int freesrc) | 332 SDL_LoadBMP_RW(SDL_RWops * src, int freesrc) |
51 { | 333 { |
52 int was_error; | 334 int was_error; |