rust-ico

A pure Rust library for encoding and decoding Windows ICO icon and CUR cursor files.

Library
Cargo
v0.5.0
29stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
39/100Needs Attention
Development Activity52
Maintenance12
Community20
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
72/100Good
Architecture76
Code Quality78
Innovation58
Learning Curve75

ico gives Rust programs direct read and write access to the Windows ICO and CUR file formats, the container format behind desktop application icons, website favicons, and Windows cursor images. It parses the ICONDIR structure, walks each embedded entry, and decodes the underlying image data whether it was stored as a raw BMP bitmap or an embedded PNG, exposing the result as a plain IconImage with flat RGBA pixel data.

Because it works from raw pixel buffers as well as decoded files, the crate supports both directions of a typical icon workflow: reading an existing .ico/.cur file to inspect or extract its images, and assembling a brand-new one from PNGs or generated RGBA data with IconDir::add_entry() and IconDirEntry::encode(). CUR-specific cursor hotspot coordinates are read and written transparently alongside the image data, and an optional serde feature adds Serialize/Deserialize support for teams that need to persist parsed icon metadata.

What You Get

  • An IconDir::read() / IconDir::write() API for parsing and serializing whole ICO/CUR files from any Read + Seek source
  • Automatic decoding of both BMP- and PNG-encoded icon entries into a single IconImage representation
  • Raw RGBA pixel access via IconImage::rgba_data() for handing decoded images to another image or GUI library
  • Encoding helpers (IconDirEntry::encode, encode_as_bmp, encode_as_png) for building new icon files from scratch
  • Cursor hotspot read/write support for CUR files, and an opt-in serde feature for serializing parsed icon metadata

Common Use Cases

  • Generating multi-resolution favicon.ico files for a website build pipeline from a set of source PNGs
  • Extracting embedded icons from a Windows .ico/.cur asset for use in a cross-platform image viewer or converter
  • Building a desktop application’s installer icon from a stack of differently-sized PNG renders
  • Writing a CLI icon-inspection or icon-conversion tool (as demonstrated by the crate’s own icotool example)

Under The Hood

Architecture The crate is organized around three small, single-purpose modules that mirror the ICO file format itself: icondir.rs implements IconDir/IconDirEntry and the byte-level ICONDIR/ICONDIRENTRY parsing and serialization logic (including bounds-checking each entry’s data span against the actual file length before reading it), image.rs implements IconImage and the BMP/PNG codec paths (including a private bmpdepth module for BMP color-depth handling), and restype.rs is a tiny enum distinguishing Icon vs. Cursor resource types. Reading proceeds in three passes over the ICONDIR structure — parse all entry headers, seek to and read each entry’s raw data span, then decode each entry to backfill its true width/height from the image data itself — a deliberate tolerance for malformed dimension bytes that lets callers still inspect a directory even if one entry’s payload is corrupt. There is no runtime dependency injection or plugin surface; the whole crate is a stateless codec over a Read + Seek (or Write) stream.

Tech Stack Pure Rust (2021 edition) with a minimal dependency footprint: byteorder for little-endian integer reads/writes matching the ICO binary format, png (0.18) for PNG entry decoding/encoding, and an optional serde (1.0, default-features = false) gated behind a feature flag for consumers who want IconDir/IconImage to (de)serialize. Dev-dependencies pull in clap 2.30 solely to build the icotool example CLI. There is no build step beyond cargo build and no platform-specific code — it’s a portable library, not a Windows-only binding.

Code Quality The crate has a real integration test suite (tests/decode.rs, tests/encode.rs) that round-trips several real-world .ico files (including hand-picked edge cases like an entry with biClrUsed != 0) against known-good PNG renders, plus unit tests inline in restype.rs and icondir.rs. CI (.github/workflows/tests.yml) runs cargo fmt --check and cargo clippy -- -D warnings as a required linting job, then runs the full test suite across Ubuntu, Windows, and macOS on stable Rust — a meaningful check for a format-parsing crate where endianness and struct-layout bugs are easy to introduce. Public constructors panic on invalid dimensions/data lengths rather than returning Result, which is a deliberate but debatable API choice; file I/O and format-validation errors, by contrast, are surfaced properly via io::Result with descriptive InvalidData messages.

What Makes It Unique Most general-purpose Rust image crates (e.g. the image crate) treat ICO as one format among dozens and don’t expose ICO-specific concepts like per-entry BMP-vs-PNG storage or CUR cursor hotspots. rust-ico does one format well: it models the ICONDIR/ICONDIRENTRY structure directly, handles the format’s legacy quirks (the 0-means-256 width/height encoding, biClrUsed idiosyncrasies), and treats ICO and CUR as first-class siblings rather than an afterthought, making it the more precise tool when the task is specifically icon/cursor file manipulation rather than general image conversion.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search