iconwriter 1.1.1

A simple solution for generating .ico and .icns icons.
Documentation
# IconWriter

[![Crate](https://img.shields.io/crates/v/iconwriter.svg)](https://crates.io/crates/iconwriter)
[![API](https://docs.rs/iconwriter/badge.svg)](https://docs.rs/iconwriter)
[![Minimum rustc version](https://img.shields.io/badge/rustc-1.32+-lightgray.svg)](https://github.com/rust-random/rand#rust-version-requirements)

A simple solution for generating `.ico` and `.icns` icons. This crate serves as **[IconWriter CLI's](https://github.com/warrengalyen/iconwriter)** internal library.

## Supported Image Formats

| Format | Supported?                                         | 
| ------ | -------------------------------------------------- | 
| `PNG`  | All supported color types                          | 
| `JPEG` | Baseline and progressive                           | 
| `GIF`  | Yes                                                | 
| `BMP`  | Yes                                                | 
| `ICO`  | Yes                                                | 
| `TIFF` | Baseline(no fax support), `LZW`, PackBits          | 
| `WEBP` | Lossy(Luma channel only)                           | 
| `PNM ` | `PBM`, `PGM`, `PPM`, standard `PAM`                |
| `SVG`  | Limited([flat filled shapes only]#svg-support)   |

## Usage

This crate's API revolves around the concept of binding source images to a set of sizes. The following example demonstrates this principle:

```rust
use iconwriter::prelude::*;

const N_ENTRIES: usize = 1;

fn main() {
    // Creating the icon
    let mut icon = Icon::ico(N_ENTRIES);

    // Importing the source image
    let src_image = SourceImage::from_path("img.jpg").unwrap();

    // Adding the sizes
    let _ = icon.add_sizes(&vec![32, 64], &src_image).unwrap();
}
```

Note that the `capacity` argument in the `Icon::ico`, `Icon::icns`, `Icon::png_sequence` and `Icon::new` methods specifies the expected number of _sizes_ in a given `Icon`.

### Sampling From Multiple Sources

Let's say you want to customize your icon so that the smaller versions of it are less detailed. **IconWriter** helps you achieve this by allowing to sample from multiple sources.

You can simply combine separate source images by specifying to which size they should be assigned:

```rust
use iconwriter::prelude::*;

fn main() {
    let mut icon = Icon::ico(N_ENTRIES);

    // Importing the source images
    let small = SourceImage::from_path("small.jpg").unwrap();
    let large = SourceImage::from_path("small.png").unwrap();

    // Adding the sizes
    let _ = icon.add_size(16, &small).unwrap();
    let _ = icon.add_size(32, &large).unwrap();
}
```

Note that different sizes can share a common source image.

### Rasterizing

Icons can be rasterized to a series of bitmap imaged with the help of the `Icon::rasterize` method. The sources will be scalled using the resampling filter provided in the `resampler` argument. The `iconwriter::resample` mod provides a series of standard resampling filters.

```rust
use iconwriter::prelude::*;

const N_ENTRIES: usize = 1;

fn main() {
    // Creating the icon
    let mut icon = Icon::ico(N_ENTRIES);

    // Importing the source image
    let src_image = SourceImage::from_path("img.jpg").unwrap();

    // Adding the sizes
    let _ = icon.add_sizes(&vec![32, 64], &src_image).unwrap();

    // Rasterize the sources
    let rasters = icon.rasterize(iconwriter::resample::linear)
        .unwrap_or_default();
}
```

### Writing to Files

Writing to files can be easily done by calling the [`Icon::write`](https://docs.rs/iconwriter/struct.Icon.html#method.write) method:

```rust
use iconwriter::prelude::*;
use std::fs::File;

/* Const declarations */
fn main() {
    let mut icon = Icon::ico(N_ENTRIES);

    /* Process the icon */
    if let Ok(&file) = File::create("myfile.ico") {
             match icon.write(file, iconwriter::resample::linear) {
            Ok(()) => println!("File 'myfile.ico' saved!"),
            Err(_) => println!("An error occurred ;-;")
        }
    }
}
```

Note that the `Icon::write` method can also write to instances of any type which implements [`Write`](https://doc.rust-lang.org/std/io/trait.Write.html).

## Limitations

There are two main limitations in this crate: both `ICNS` and `SVG` are not fully supported. Due to the use of external dependencies, this crate is not able to fully support the formal specifications of those two file formats.

### ICNS Support


However, the coverage provided by these external dependencies should be more than enought for most use cases.

**Icon Writer** uses the `icns` crate for generating `.icns` files. The [supported icon types](https://github.com/mdsteele/rust-icns/blob/master/README.md#supported-icon-types) are specified by the creators of such crate as follows:

| OSType | Description                             | Supported? |
|--------|-----------------------------------------|------------|
| `ICON` | 32×32 1-bit icon                        | No         |
| `ICN#` | 32×32 1-bit icon with 1-bit mask        | No         |
| `icm#` | 16×12 1-bit icon with 1-bit mask        | No         |
| `icm4` | 16×12 4-bit icon                        | No         |
| `icm8` | 16×12 8-bit icon                        | No         |
| `ics#` | 16×16 1-bit mask                        | No         |
| `ics4` | 16×16 4-bit icon                        | No         |
| `ics8` | 16x16 8-bit icon                        | No         |
| `is32` | 16×16 24-bit icon                       | Yes        |
| `s8mk` | 16x16 8-bit mask                        | Yes        |
| `icl4` | 32×32 4-bit icon                        | No         |
| `icl8` | 32×32 8-bit icon                        | No         |
| `il32` | 32x32 24-bit icon                       | Yes        |
| `l8mk` | 32×32 8-bit mask                        | Yes        |
| `ich#` | 48×48 1-bit mask                        | No         |
| `ich4` | 48×48 4-bit icon                        | No         |
| `ich8` | 48×48 8-bit icon                        | No         |
| `ih32` | 48×48 24-bit icon                       | Yes        |
| `h8mk` | 48×48 8-bit mask                        | Yes        |
| `it32` | 128×128 24-bit icon                     | Yes        |
| `t8mk` | 128×128 8-bit mask                      | Yes        |
| `icp4` | 16x16 32-bit PNG/JP2 icon               | PNG only   |
| `icp5` | 32x32 32-bit PNG/JP2 icon               | PNG only   |
| `icp6` | 64x64 32-bit PNG/JP2 icon               | PNG only   |
| `ic07` | 128x128 32-bit PNG/JP2 icon             | PNG only   |
| `ic08` | 256×256 32-bit PNG/JP2 icon             | PNG only   |
| `ic09` | 512×512 32-bit PNG/JP2 icon             | PNG only   |
| `ic10` | 512x512@2x "retina" 32-bit PNG/JP2 icon | PNG only   |
| `ic11` | 16x16@2x "retina" 32-bit PNG/JP2 icon   | PNG only   |
| `ic12` | 32x32@2x "retina" 32-bit PNG/JP2 icon   | PNG only   |
| `ic13` | 128x128@2x "retina" 32-bit PNG/JP2 icon | PNG only   |
| `ic14` | 256x256@2x "retina" 32-bit PNG/JP2 icon | PNG only   |

### SVG Support


**IconWriter** uses the `nsvg` crate for rasterizing `.svg` files. According to the authors of the crate:

> Like NanoSVG, the rasterizer only renders flat filled shapes. It is not particularly fast or accurate, but it is a simple way to bake vector graphics into textures.

The author of `iconwriter` is inclined to search for alternatives to `nsvg` if inquired to. Help would be appreciated.