win-icon-extractor 0.1.0

Extract file icons on Windows — pure Rust, no C dependency
# win-icon-extractor


Extract file icons on Windows — pure Rust, no C dependency.

- **Raw RGBA pixels** from any file (exe, dll, ico, or shell fallback)
- **Extension icons** — get associated icon by file extension, no file needed
- **System stock icons** — folder, drive, recycle bin, shield, etc.
- **Icon enumeration** — query how many icons a PE file contains
- **WebP / PNG encoding** with configurable options
- **Disk + memory cache** with mtime-based staleness detection
- **Bulk parallel extraction** via rayon

## Quick Start


```rust
use win_icon_extractor::*;

// Raw RGBA pixels from a file
let icon = extract_icon(r"C:\Windows\explorer.exe").unwrap();
println!("{}x{}, {} bytes", icon.width, icon.height, icon.rgba.len());

// By index or size
let icon = extract_icon_at(r"C:\Windows\explorer.exe", 1).unwrap();
let icon = extract_icon_with_size(r"C:\Windows\explorer.exe", 256).unwrap();

// Icon count in a PE file
let count = icon_count(r"C:\Windows\System32\shell32.dll"); // 335
```

## Extension Icons


Get the associated icon for any file extension — the file does not need to exist:

```rust
let icon = extract_icon_for_extension(".pdf").unwrap();
let icon = extract_icon_for_extension(".docx").unwrap();
```

## System Stock Icons


Extract Windows system-defined icons:

```rust
use win_icon_extractor::StockIcon;

let icon = extract_stock_icon(StockIcon::Folder).unwrap();
let icon = extract_stock_icon(StockIcon::DriveFixed).unwrap();
let icon = extract_stock_icon(StockIcon::Recycler).unwrap();
let icon = extract_stock_icon(StockIcon::Shield).unwrap();

// Custom size
let icon = extract_stock_icon_sized(StockIcon::Folder, 48).unwrap();
```

Available stock icons: `Folder`, `FolderOpen`, `DriveFixed`, `DriveRemovable`, `DriveNet`, `DriveCd`, `DriveDvd`, `Recycler`, `RecyclerFull`, `Shield`, `Warning`, `Error`, `Info`, `Internet`, `Server`, `Printer`, `Users`, `ZipFile`, `Settings`, and more.

## Encoding


```rust
// WebP (feature = "webp")
let webp = extract_icon_webp(r"C:\Windows\explorer.exe").unwrap();
std::fs::write("icon.webp", &webp).unwrap();

// PNG (feature = "png")
let png = extract_icon_png(r"C:\Windows\explorer.exe").unwrap();
std::fs::write("icon.png", &png).unwrap();

// Encode raw RGBA data
let webp = encode_webp(&icon.rgba, icon.width, icon.height).unwrap();
let png = encode_png(&icon.rgba, icon.width, icon.height).unwrap();
```

### Custom Encoding Options


```rust
use win_icon_extractor::*;

// WebP: custom quality, method, lossless mode
let opts = WebPOptions {
    quality: 90.0,          // 0.0–100.0 (default: 75.0)
    method: 6,              // 0=fast, 6=best (default: 5)
    lossless: true,         // lossless encoding (default: false)
    alpha_quality: 100,     // 0–100 (default: 100)
    exact: true,            // preserve RGB under transparent areas (default: false)
    ..Default::default()
};
let webp = encode_webp_with(&icon.rgba, icon.width, icon.height, &opts).unwrap();

// WebP best quality preset (lossless, max effort)
let webp = encode_webp_with(&icon.rgba, icon.width, icon.height, &WebPOptions::best_quality()).unwrap();

// PNG: custom filter and compression level
let opts = PngOptions {
    filter: PngFilter::None, // None (default, best for icons) or Sub
    compression_level: 10,   // 0–10 (default: 6)
};
let png = encode_png_with(&icon.rgba, icon.width, icon.height, &opts).unwrap();

// PNG best quality preset (max compression, None filter)
let png = encode_png_with(&icon.rgba, icon.width, icon.height, &PngOptions::best_quality()).unwrap();
```

## Caching


```rust
use win_icon_extractor::{IconCache, ImageFormat};

let cache = IconCache::with_app_name("my-app").unwrap();
let path = cache.extract_to_file(r"C:\Windows\explorer.exe").unwrap();

// Use PNG format instead of WebP
let mut cache = IconCache::with_app_name("my-app").unwrap();
cache.set_format(ImageFormat::Png);

// Custom encoding options on cache
cache.set_webp_options(WebPOptions::best_quality());
cache.set_png_options(PngOptions::best_quality());

// Bulk parallel extraction (returns Result per path)
let paths = &[r"C:\Windows\System32\cmd.exe", r"C:\Windows\explorer.exe"];
let results = cache.extract_to_file_bulk(paths);
for (path, result) in &results {
    match result {
        Ok(cached) => println!("{path} → {}", cached.display()),
        Err(e) => eprintln!("{path}: {e}"),
    }
}

// Maintenance
let stats = cache.stats().unwrap();
cache.cleanup(30).unwrap(); // remove files older than 30 days
```

## Features


| Feature | Default | Description |
|---------|---------|-------------|
| `webp`  || WebP encoding via libwebp-sys |
| `png`   |   | PNG encoding (hand-written encoder + miniz_oxide) |
| `cache` || Disk + memory cache with mtime validation |
| `bulk`  || Parallel extraction via rayon |

```toml
# All defaults (webp + cache + bulk)

win-icon-extractor = "0.1"

# Minimal — raw extraction only

win-icon-extractor = { version = "0.1", default-features = false }

# PNG instead of WebP

win-icon-extractor = { version = "0.1", default-features = false, features = ["png", "cache"] }
```

## Performance


Benchmarked on Windows 11, release mode:

| API | Latency |
|-----|---------|
| `icon_count` | ~40µs |
| `extract_stock_icon` | ~126µs |
| `extract_icon_for_extension` | ~235µs |
| `extract_icon` (file) | ~1.6ms |
| Cache warm hit | ~1.4ms |

## License


AGPL-3.0