An ICL file has no structure of its own. It is a Windows executable library whose only contents are icon resources, so reading one means reading the executable’s resources and picking out two resource types.
Which container
Bytes at the 0x3C pointer | Container | Resources |
|---|---|---|
NE | 16-bit New Executable, the original ICL | the NE resource table |
PE 00 00 | 32-bit Portable Executable, from newer editors | the PE resource directory |
Every ICL starts with an MS-DOS MZ header. The 32-bit value at offset
0x3C gives the offset of the Windows header. An ICL has no code: in an NE
file there are no code segments, and in a PE file the code section is empty.
Resource types
| Type | Name | NE type value | Contents |
|---|---|---|---|
| 14 | RT_GROUP_ICON | 0x800E | one per icon: the list of its sizes and colour depths |
| 3 | RT_ICON | 0x8003 | one per image: the pixels of one size of one icon |
In an NE resource table a numbered type has its top bit set, so type 14 is stored as
0x800E. A PE resource directory stores the plain numbers. An ICL holds
these two types and normally nothing else.
Group icon resource
Each RT_GROUP_ICON resource is a GRPICONDIR: the same 6-byte
header as an ICO file’s directory, then one
14-byte entry per image. Numbers are little-endian and the structure is packed on
2-byte boundaries.
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
| 0 | 2 | u16 | idReserved | 0 |
| 2 | 2 | u16 | idType | 1 for icons |
| 4 | 2 | u16 | idCount | the number of images |
| 6 | 14 × idCount | entries | idEntries | below |
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
| 0 | 1 | u8 | bWidth | width in pixels; 0 means 256 |
| 1 | 1 | u8 | bHeight | height in pixels; 0 means 256 |
| 2 | 1 | u8 | bColorCount | colours for paletted images; 0 for 256 or more |
| 3 | 1 | u8 | bReserved | 0 |
| 4 | 2 | u16 | wPlanes | colour planes, 1 |
| 6 | 2 | u16 | wBitCount | bits per pixel |
| 8 | 4 | u32 | dwBytesInRes | the size of the RT_ICON resource |
| 12 | 2 | u16 | nID | the resource ID of the RT_ICON that holds this image |
The entry is the ICO file’s 16-byte entry with its last field, a 32-bit file offset, replaced by the 16-bit resource ID.
Icon resource
Each RT_ICON resource holds exactly the bytes of one image of an ICO
file: a bitmap with its height doubled to cover
the colour image and the AND mask, or, in files
for Windows Vista and later, a PNG image, usually
for 256 × 256. A 16-bit NE library normally holds only bitmaps.
Icon numbers
Programs refer to an icon in a library as a file name and a number, as in the
Change Icon dialog or a shortcut’s icon setting. Microsoft’s
ExtractIcon documents the number: 0 or more counts the group icon
resources from 0 in the order Windows lists them, and a negative number other than
−1 picks the group whose resource ID is its absolute value. −1 asks how many icons
the file holds.
A group icon resource may have a number or a name. In a PE file, the resource directory lists named entries first, in alphabetical order, then numbered entries in ascending order.
Getting an ICO file back
To turn one icon of an ICL back into a .ico file, read its group icon
resource, then:
- Write the 6-byte header unchanged.
- Write one 16-byte ICO entry per group entry: its first 12 bytes unchanged, then
the offset in the new file where that image will go, 6 + 16 ×
idCountfor the first image and each following one after the last. - Write the data of each
RT_ICONresource named bynID, in the same order.