Crate icns

source ·
Expand description

A library for encoding/decoding Apple Icon Image (.icns) files.

ICNS concepts

To understand this library, it helps to be familiar with the structure of an ICNS file; this section will give a high-level overview, or see Wikipedia for more details about the file format. If you prefer to learn by example, you can just skip down to the Example usage section below.

An ICNS file encodes a collection of images (typically different versions of the same icon at different resolutions) called an icon family. The file consists of a short header followed by a sequence of data blocks called icon elements. Each icon element consists of a header with an OSType – which is essentially a four-byte identifier indicating the type of data in the element – and a blob of binary data.

Each image in the ICNS file is encoded either as a single icon element, or as two elements – one for the color data and one for the alpha mask. For example, 48x48 pixel icons are stored as two elements: an ih32 element containing compressed 24-bit RGB data, and an h8mk element containing the 8-bit alpha mask. By contrast, 64x64 pixel icons are stored as a single icp6 element, which contains either PNG or JPEG 2000 data for the whole 32-bit image.

Some icon sizes have multiple possible encodings. For example, a 128x128 icon can be stored either as an it32 and an t8mk element together (containing compressed RGB and alpha, respectively), or as a single ic07 element (containing PNG or JPEG 2000 data). And for some icon sizes, there are separate OSTypes for single and double-pixel-density versions of the icon (for “retina” displays). For example, an ic08 element encodes a single-density 256x256 image, while an ic14 element encodes a double-density 256x256 image – that is, the image data is actually 512x512 pixels, and is considered different from the single-density 512x512 pixel image encoded by an ic09 element.

Finally, there are some additional, optional element types that don’t encode images at all. For example, the TOC element summarizes the contents of the ICNS file, and the icnV element stores version information.

API overview

The API for this library is modelled loosely after that of libicns.

The icon family stored in an ICNS file is represeted by the IconFamily struct, which provides methods for reading and writing ICNS files, as well as for high-level operations on the icon set, such as adding, extracting, and listing the encoded images.

An IconFamily contains a vector of IconElement structs, which represent individual data blocks in the ICNS file. Each IconElement has an OSType indicating the type of data in the element, as well as a Vec<u8> containing the data itself. Usually, you won’t need to work with IconElements directly, and can instead use the higher-level operations provided by IconFamily.

Since raw OSTypes like t8mk and icp4 can be hard to remember, the IconType type enumerates all the icon element types that are supported by this library, with more mnemonic names (for example, IconType::RGB24_48x48 indicates 24-bit RGB data for a 48x48 pixel icon, and is a bit more understandable than the corresponding OSType, ih32). The IconType enum also provides methods for getting the properties of each icon type, such as the size of the encoded image, or the associated mask type (for icons that are stored as two elements instead of one).

Regardless of whether you use the higher-level IconFamily methods or the lower-level IconElement methods, icons from the ICNS file can be decoded into Image structs, which can be converted to and from any of several PixelFormats to allow the raw pixel data to be easily transferred to another image library for further processing. Since this library already depends on the PNG codec anyway (since some ICNS icons are PNG-encoded), as a convenience, the Image struct also provides methods for reading and writing PNG files.

Limitations

The ICNS format allows some icon types to be encoded either as PNG data or as JPEG 2000 data; however, when encoding icons, this library always uses PNG format, and when decoding icons, it cannot decode JPEG 2000 icons at all (it will detect the JPEG 2000 header and return an error). The reason for this is the apparent lack of JPEG 2000 libraries for Rust; if this ever changes, please feel free to file a bug or a send a pull request.

Additionally, this library does not yet support many of the older icon types used by earlier versions of Mac OS (such as ICN#, a 32x32 black and white icon). Again, pull requests (with suitable tests) are welcome.

Example usage

use icns::{IconFamily, IconType, Image};
use std::fs::File;
use std::io::{BufReader, BufWriter};

// Load an icon family from an ICNS file.
let file = BufReader::new(File::open("16.icns").unwrap());
let mut icon_family = IconFamily::read(file).unwrap();

// Extract an icon from the family and save it as a PNG.
let image = icon_family.get_icon_with_type(IconType::RGB24_16x16).unwrap();
let file = BufWriter::new(File::create("16.png").unwrap());
image.write_png(file).unwrap();

// Read in another icon from a PNG file, and add it to the icon family.
let file = BufReader::new(File::open("32.png").unwrap());
let image = Image::read_png(file).unwrap();
icon_family.add_icon(&image).unwrap();

// Save the updated icon family to a new ICNS file.
let file = BufWriter::new(File::create("16-and-32.icns").unwrap());
icon_family.write(file).unwrap();

Structs

One data block in an ICNS file. Depending on the resource type, this may represent an icon, or part of an icon (such as an alpha mask, or color data without the mask).
A set of icons stored in a single ICNS file.
A decoded icon image.
A Macintosh OSType (also known as a ResType), used in ICNS files to identify the type of each icon element.

Enums

Methods of encoding an image within an icon element.
Types of icon elements that can be decoded as images or masks.
Formats for storing pixel data in an image.