~ubuntu-branches/ubuntu/hoary/devil/hoary

« back to all changes in this revision

Viewing changes to src-IL/src/il_icon.c

  • Committer: Bazaar Package Importer
  • Author(s): Marcelo E. Magallon
  • Date: 2005-01-03 19:57:42 UTC
  • Revision ID: james.westby@ubuntu.com-20050103195742-4ipkplcwygu3irv0
Tags: upstream-1.6.7
ImportĀ upstreamĀ versionĀ 1.6.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//-----------------------------------------------------------------------------
 
2
//
 
3
// ImageLib Sources
 
4
// Copyright (C) 2001-2002 by Denton Woods
 
5
// Last modified: 06/13/2001 <--Y2K Compliant! =]
 
6
//
 
7
// Filename: src-IL/src/il_icon.c
 
8
//
 
9
// Description: Reads from a Windows icon (.ico) file.
 
10
//
 
11
//-----------------------------------------------------------------------------
 
12
 
 
13
 
 
14
#include "il_internal.h"
 
15
#ifndef IL_NO_ICO
 
16
#include "il_icon.h"
 
17
 
 
18
 
 
19
//! Reads an icon file.
 
20
ILboolean ilLoadIcon(const ILstring FileName)
 
21
{
 
22
        ILHANDLE        IconFile;
 
23
        ILboolean       bIcon = IL_FALSE;
 
24
 
 
25
        IconFile = iopenr(FileName);
 
26
        if (IconFile == NULL) {
 
27
                ilSetError(IL_COULD_NOT_OPEN_FILE);
 
28
                return bIcon;
 
29
        }
 
30
 
 
31
        bIcon = ilLoadIconF(IconFile);
 
32
        icloser(IconFile);
 
33
 
 
34
        return bIcon;
 
35
}
 
36
 
 
37
 
 
38
//! Reads an already-opened icon file.
 
39
ILboolean ilLoadIconF(ILHANDLE File)
 
40
{
 
41
        ILuint          FirstPos;
 
42
        ILboolean       bRet;
 
43
 
 
44
        iSetInputFile(File);
 
45
        FirstPos = itell();
 
46
        bRet = iLoadIconInternal();
 
47
        iseek(FirstPos, IL_SEEK_SET);
 
48
 
 
49
        return bRet;
 
50
}
 
51
 
 
52
 
 
53
//! Reads from a memory "lump" that contains an icon.
 
54
ILboolean ilLoadIconL(ILvoid *Lump, ILuint Size)
 
55
{
 
56
        iSetInputLump(Lump, Size);
 
57
        return iLoadIconInternal();
 
58
}
 
59
 
 
60
 
 
61
// Internal function used to load the icon.
 
62
ILboolean iLoadIconInternal()
 
63
{
 
64
        ICODIR          IconDir;
 
65
        ICODIRENTRY     *DirEntries = NULL;
 
66
        ICOIMAGE        *IconImages = NULL;
 
67
        ILimage         *Image = NULL;
 
68
        ILint           i;
 
69
        ILuint          Size, PadSize, j, k, l, m, /*NumImages = 0,*/ CurAndByte, PadCount, AndBytes;
 
70
        ILboolean       BaseCreated = IL_FALSE;
 
71
 
 
72
        if (iCurImage == NULL) {
 
73
                ilSetError(IL_ILLEGAL_OPERATION);
 
74
                return IL_FALSE;
 
75
        }
 
76
 
 
77
        if (iread(&IconDir, sizeof(ICODIR), 1) != 1)
 
78
                goto file_read_error;
 
79
        Short(&IconDir.Count);
 
80
        Short(&IconDir.Type);
 
81
 
 
82
        DirEntries = (ICODIRENTRY*)ialloc(sizeof(ICODIRENTRY) * IconDir.Count);
 
83
        IconImages = (ICOIMAGE*)ialloc(sizeof(ICOIMAGE) * IconDir.Count);
 
84
        if (DirEntries == NULL || IconImages == NULL) {
 
85
                ifree(DirEntries);
 
86
                ifree(IconImages);
 
87
                return IL_FALSE;
 
88
        }
 
89
 
 
90
        // Make it easier for file_read_error.
 
91
        for (i = 0; i < IconDir.Count; i++)
 
92
                imemclear(&IconImages[i], sizeof(ICOIMAGE));
 
93
        if (iread(DirEntries, sizeof(ICODIRENTRY), IconDir.Count) != (ILuint)IconDir.Count)
 
94
                goto file_read_error;
 
95
 
 
96
        for (i = 0; i < IconDir.Count; i++) {
 
97
                Short(&DirEntries[i].Planes);
 
98
                Short(&DirEntries[i].Bpp);
 
99
                UInt(&DirEntries[i].SizeOfData);
 
100
                UInt(&DirEntries[i].Offset);
 
101
 
 
102
                iseek(DirEntries[i].Offset, IL_SEEK_SET);
 
103
                if (iread(&IconImages[i].Head, sizeof(INFOHEAD), 1) != 1)
 
104
                        goto file_read_error;
 
105
 
 
106
                Int(&IconImages[i].Head.Size);
 
107
                Int(&IconImages[i].Head.Width);
 
108
                Int(&IconImages[i].Head.Height);
 
109
                Short(&IconImages[i].Head.Planes);
 
110
                Short(&IconImages[i].Head.BitCount);
 
111
                Int(&IconImages[i].Head.Compression);
 
112
                Int(&IconImages[i].Head.SizeImage);
 
113
                Int(&IconImages[i].Head.XPixPerMeter);
 
114
                Int(&IconImages[i].Head.YPixPerMeter);
 
115
                Int(&IconImages[i].Head.ColourUsed);
 
116
                Int(&IconImages[i].Head.ColourImportant);
 
117
 
 
118
                if (IconImages[i].Head.BitCount < 8) {
 
119
                        if (IconImages[i].Head.ColourUsed == 0) {
 
120
                                switch (IconImages[i].Head.BitCount)
 
121
                                {
 
122
                                        case 1:
 
123
                                                IconImages[i].Head.ColourUsed = 2;
 
124
                                                break;
 
125
                                        case 4:
 
126
                                                IconImages[i].Head.ColourUsed = 16;
 
127
                                                break;
 
128
                                }
 
129
                        }
 
130
                        IconImages[i].Pal = (ILubyte*)ialloc(IconImages[i].Head.ColourUsed * 4);
 
131
                        if (IconImages[i].Pal == NULL)
 
132
                                goto file_read_error;  // @TODO: Rename the label.
 
133
                        if (iread(IconImages[i].Pal, IconImages[i].Head.ColourUsed * 4, 1) != 1)
 
134
                                goto file_read_error;
 
135
                }
 
136
                else if (IconImages[i].Head.BitCount == 8) {
 
137
                        IconImages[i].Pal = (ILubyte*)ialloc(256 * 4);
 
138
                        if (IconImages[i].Pal == NULL)
 
139
                                goto file_read_error;
 
140
                        if (iread(IconImages[i].Pal, 1, 256 * 4) != 256*4)
 
141
                                goto file_read_error;
 
142
                }
 
143
                else {
 
144
                        IconImages[i].Pal = NULL;
 
145
                }
 
146
 
 
147
                PadSize = (IconImages[i].Head.Width >> 3) % 4;  // Has to be DWORD-aligned.
 
148
 
 
149
                if (IconImages[i].Head.BitCount == 1) {
 
150
                        Size = ((IconImages[i].Head.Width >> 3) + PadSize) * (IconImages[i].Head.Height / 2);
 
151
                }
 
152
                else {
 
153
                        Size = (IconImages[i].Head.Width * (IconImages[i].Head.Height / 2) * IconImages[i].Head.BitCount) >> 3;
 
154
                }
 
155
                IconImages[i].Data = (ILubyte*)ialloc(Size);
 
156
                if (IconImages[i].Data == NULL)
 
157
                        goto file_read_error;
 
158
                if (iread(IconImages[i].Data, 1, Size) != Size)
 
159
                        goto file_read_error;
 
160
 
 
161
                //Size = (IconImages[i].Head.Width * (IconImages[i].Head.Height / 2)) >> 3;  // 1 bpp
 
162
                Size = ((IconImages[i].Head.Width >> 3) + PadSize) * (IconImages[i].Head.Height / 2);
 
163
                IconImages[i].AND = (ILubyte*)ialloc(Size);
 
164
                if (IconImages[i].AND == NULL)
 
165
                        goto file_read_error;
 
166
                if (iread(IconImages[i].AND, 1, Size) != Size)
 
167
                        goto file_read_error;
 
168
        }
 
169
 
 
170
 
 
171
        for (i = 0; i < IconDir.Count; i++) {
 
172
                if (IconImages[i].Head.BitCount != 1 && IconImages[i].Head.BitCount != 4 &&
 
173
                        IconImages[i].Head.BitCount != 8 && IconImages[i].Head.BitCount != 24)
 
174
                        continue;
 
175
 
 
176
                if (!BaseCreated) {
 
177
                        ilTexImage(IconImages[i].Head.Width, IconImages[i].Head.Height / 2, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL);
 
178
                        iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
 
179
                        Image = iCurImage;
 
180
                        BaseCreated = IL_TRUE;
 
181
                        iCurImage->NumNext = 0;
 
182
                }
 
183
                else {
 
184
                        Image->Next = ilNewImage(IconImages[i].Head.Width, IconImages[i].Head.Height / 2, 1, 4, 1);
 
185
                        Image = Image->Next;
 
186
                        Image->Format = IL_BGRA;
 
187
                        iCurImage->NumNext++;
 
188
                }
 
189
                Image->Type = IL_UNSIGNED_BYTE;
 
190
 
 
191
                j = 0;  k = 0;  l = 128;  CurAndByte = 0;  PadCount = 0;
 
192
                PadSize = (IconImages[i].Head.Width >> 3) % 4;
 
193
                AndBytes = (IconImages[i].Head.Width >> 3);
 
194
 
 
195
                if (IconImages[i].Head.BitCount == 1) {
 
196
                        for (; j < Image->SizeOfData; k++) {
 
197
                                for (m = 128; m; m >>= 1) {
 
198
                                        Image->Data[j] = IconImages[i].Pal[!!(IconImages[i].Data[k] & m) * 4];
 
199
                                        Image->Data[j+1] = IconImages[i].Pal[!!(IconImages[i].Data[k] & m) * 4 + 1];
 
200
                                        Image->Data[j+2] = IconImages[i].Pal[!!(IconImages[i].Data[k] & m) * 4 + 2];
 
201
                                        Image->Data[j+3] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255;
 
202
                                        j += 4;
 
203
                                        l >>= 1;
 
204
                                }
 
205
                                if (l == 0) {
 
206
                                        l = 128;
 
207
                                        CurAndByte++;
 
208
                                        if (++PadCount == AndBytes) {
 
209
                                                CurAndByte += PadSize;
 
210
                                                k += PadSize;
 
211
                                                PadCount = 0;
 
212
                                        }
 
213
                                }
 
214
                        }
 
215
                }
 
216
                else if (IconImages[i].Head.BitCount == 4) {
 
217
                        for (; j < Image->SizeOfData; j += 8, k++) {
 
218
                                Image->Data[j] = IconImages[i].Pal[((IconImages[i].Data[k] & 0xF0) >> 4) * 4];
 
219
                                Image->Data[j+1] = IconImages[i].Pal[((IconImages[i].Data[k] & 0xF0) >> 4) * 4 + 1];
 
220
                                Image->Data[j+2] = IconImages[i].Pal[((IconImages[i].Data[k] & 0xF0) >> 4) * 4 + 2];
 
221
                                Image->Data[j+3] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255;
 
222
                                l >>= 1;
 
223
                                Image->Data[j+4] = IconImages[i].Pal[(IconImages[i].Data[k] & 0x0F) * 4];
 
224
                                Image->Data[j+5] = IconImages[i].Pal[(IconImages[i].Data[k] & 0x0F) * 4 + 1];
 
225
                                Image->Data[j+6] = IconImages[i].Pal[(IconImages[i].Data[k] & 0x0F) * 4 + 2];
 
226
                                Image->Data[j+7] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255;
 
227
                                l >>= 1;
 
228
                                if (l == 0) {
 
229
                                        l = 128;
 
230
                                        CurAndByte++;
 
231
                                        if (++PadCount == AndBytes) {
 
232
                                                CurAndByte += PadSize;
 
233
                                                PadCount = 0;
 
234
                                        }
 
235
                                }
 
236
                        }
 
237
                }
 
238
                else if (IconImages[i].Head.BitCount == 8) {
 
239
                        for (; j < Image->SizeOfData; j += 4, k++) {
 
240
                                Image->Data[j] = IconImages[i].Pal[IconImages[i].Data[k] * 4];
 
241
                                Image->Data[j+1] = IconImages[i].Pal[IconImages[i].Data[k] * 4 + 1];
 
242
                                Image->Data[j+2] = IconImages[i].Pal[IconImages[i].Data[k] * 4 + 2];
 
243
                                Image->Data[j+3] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255;
 
244
                                l >>= 1;
 
245
                                if (l == 0) {
 
246
                                        l = 128;
 
247
                                        CurAndByte++;
 
248
                                        if (++PadCount == AndBytes) {
 
249
                                                CurAndByte += PadSize;
 
250
                                                PadCount = 0;
 
251
                                        }
 
252
                                }
 
253
                        }
 
254
                }
 
255
                else if (IconImages[i].Head.BitCount == 24) {
 
256
                        for (; j < Image->SizeOfData; j += 4, k += 3) {
 
257
                                Image->Data[j] = IconImages[i].Data[k];
 
258
                                Image->Data[j+1] = IconImages[i].Data[k+1];
 
259
                                Image->Data[j+2] = IconImages[i].Data[k+2];
 
260
                                Image->Data[j+3] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255;
 
261
                                l >>= 1;
 
262
                                if (l == 0) {
 
263
                                        l = 128;
 
264
                                        CurAndByte++;
 
265
                                        if (++PadCount == AndBytes) {
 
266
                                                CurAndByte += PadSize;
 
267
                                                PadCount = 0;
 
268
                                        }
 
269
                                }
 
270
                        }
 
271
                }
 
272
        }
 
273
 
 
274
 
 
275
        for (i = 0; i < IconDir.Count; i++) {
 
276
                ifree(IconImages[i].Pal);
 
277
                ifree(IconImages[i].Data);
 
278
                ifree(IconImages[i].AND);
 
279
        }
 
280
        ifree(IconImages);
 
281
        ifree(DirEntries);
 
282
 
 
283
        ilFixImage();
 
284
 
 
285
        return IL_TRUE;
 
286
 
 
287
file_read_error:
 
288
        if (IconImages) {
 
289
                for (i = 0; i < IconDir.Count; i++) {
 
290
                        if (IconImages[i].Pal)
 
291
                                ifree(IconImages[i].Pal);
 
292
                        if (IconImages[i].Data)
 
293
                                ifree(IconImages[i].Data);
 
294
                        if (IconImages[i].AND)
 
295
                                ifree(IconImages[i].AND);
 
296
                }
 
297
                ifree(IconImages);
 
298
        }
 
299
        if (DirEntries)
 
300
                ifree(DirEntries);
 
301
        return IL_FALSE;
 
302
}
 
303
 
 
304
 
 
305
#endif