ICO/CUR icon directory encoding and decoding.
An .ico (or .cur) file opens with a 6-byte ICONDIR header followed by
imageCount fixed-size 16-byte ICONDIRENTRY records, one per embedded
image:
ICONDIR (6 bytes) 0 7 8 15 +------------------+------------------+ | Reserved (0) | +------------------+------------------+ | Image Type | +------------------+------------------+ | Image Count | +------------------+------------------+ ICONDIRENTRY (16 bytes, repeated Image Count times) 0 7 8 15 16 23 24 31 +----------+----------+----------+----------+ | Width | Height |ColorCount| Reserved | +----------+----------+----------+----------+ | Planes | Bit Count | +----------+----------+----------+----------+ | Data Size | +----------+----------+----------+----------+ | Data Offset | +----------+----------+----------+----------+
All multi-byte fields are little-endian, matching the format's Windows origin.
This coder covers the directory only — dataOffset and dataSize locate
each embedded image (a BMP or PNG payload) within the file, but decoding
that payload is left to the caller and, for BMP entries, to
@binstruct/bmp. v0.0.1 is
deliberately shallow: no image payload parsing, no compression, no
validation of width/height/colorCount beyond surfacing them verbatim.
Round-trip a directory with one entry
Round-trip a directory with one entry
import { assertEquals } from "@std/assert"; import { icoDir, ICO_IMAGE_TYPE } from "@binstruct/ico"; const coder = icoDir(); const dir = { reserved: 0, imageType: ICO_IMAGE_TYPE.ICON, imageCount: 1, entries: [ { width: 32, height: 32, colorCount: 0, reserved: 0, planes: 1, bitCount: 32, dataSize: 744, dataOffset: 22, }, ], }; const buffer = new Uint8Array(64); const written = coder.encode(dir, buffer); const [decoded, read] = coder.decode(buffer.subarray(0, written)); assertEquals(written, read); assertEquals(decoded, dir);