1
//-----------------------------------------------------------------------------
4
// Copyright (C) 2001-2002 by Denton Woods
5
// Last modified: 06/13/2001 <--Y2K Compliant! =]
7
// Filename: src-IL/src/il_icon.c
9
// Description: Reads from a Windows icon (.ico) file.
11
//-----------------------------------------------------------------------------
14
#include "il_internal.h"
19
//! Reads an icon file.
20
ILboolean ilLoadIcon(const ILstring FileName)
23
ILboolean bIcon = IL_FALSE;
25
IconFile = iopenr(FileName);
26
if (IconFile == NULL) {
27
ilSetError(IL_COULD_NOT_OPEN_FILE);
31
bIcon = ilLoadIconF(IconFile);
38
//! Reads an already-opened icon file.
39
ILboolean ilLoadIconF(ILHANDLE File)
46
bRet = iLoadIconInternal();
47
iseek(FirstPos, IL_SEEK_SET);
53
//! Reads from a memory "lump" that contains an icon.
54
ILboolean ilLoadIconL(ILvoid *Lump, ILuint Size)
56
iSetInputLump(Lump, Size);
57
return iLoadIconInternal();
61
// Internal function used to load the icon.
62
ILboolean iLoadIconInternal()
65
ICODIRENTRY *DirEntries = NULL;
66
ICOIMAGE *IconImages = NULL;
67
ILimage *Image = NULL;
69
ILuint Size, PadSize, j, k, l, m, /*NumImages = 0,*/ CurAndByte, PadCount, AndBytes;
70
ILboolean BaseCreated = IL_FALSE;
72
if (iCurImage == NULL) {
73
ilSetError(IL_ILLEGAL_OPERATION);
77
if (iread(&IconDir, sizeof(ICODIR), 1) != 1)
79
Short(&IconDir.Count);
82
DirEntries = (ICODIRENTRY*)ialloc(sizeof(ICODIRENTRY) * IconDir.Count);
83
IconImages = (ICOIMAGE*)ialloc(sizeof(ICOIMAGE) * IconDir.Count);
84
if (DirEntries == NULL || IconImages == NULL) {
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)
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);
102
iseek(DirEntries[i].Offset, IL_SEEK_SET);
103
if (iread(&IconImages[i].Head, sizeof(INFOHEAD), 1) != 1)
104
goto file_read_error;
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);
118
if (IconImages[i].Head.BitCount < 8) {
119
if (IconImages[i].Head.ColourUsed == 0) {
120
switch (IconImages[i].Head.BitCount)
123
IconImages[i].Head.ColourUsed = 2;
126
IconImages[i].Head.ColourUsed = 16;
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;
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;
144
IconImages[i].Pal = NULL;
147
PadSize = (IconImages[i].Head.Width >> 3) % 4; // Has to be DWORD-aligned.
149
if (IconImages[i].Head.BitCount == 1) {
150
Size = ((IconImages[i].Head.Width >> 3) + PadSize) * (IconImages[i].Head.Height / 2);
153
Size = (IconImages[i].Head.Width * (IconImages[i].Head.Height / 2) * IconImages[i].Head.BitCount) >> 3;
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;
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;
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)
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;
180
BaseCreated = IL_TRUE;
181
iCurImage->NumNext = 0;
184
Image->Next = ilNewImage(IconImages[i].Head.Width, IconImages[i].Head.Height / 2, 1, 4, 1);
186
Image->Format = IL_BGRA;
187
iCurImage->NumNext++;
189
Image->Type = IL_UNSIGNED_BYTE;
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);
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;
208
if (++PadCount == AndBytes) {
209
CurAndByte += PadSize;
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;
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;
231
if (++PadCount == AndBytes) {
232
CurAndByte += PadSize;
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;
248
if (++PadCount == AndBytes) {
249
CurAndByte += PadSize;
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;
265
if (++PadCount == AndBytes) {
266
CurAndByte += PadSize;
275
for (i = 0; i < IconDir.Count; i++) {
276
ifree(IconImages[i].Pal);
277
ifree(IconImages[i].Data);
278
ifree(IconImages[i].AND);
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);