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.

Examples

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);