icns/lib.rs
1//! A library for encoding/decoding Apple Icon Image (.icns) files.
2//!
3//! # ICNS concepts
4//!
5//! To understand this library, it helps to be familiar with the structure of
6//! an ICNS file; this section will give a high-level overview, or see
7//! [Wikipedia](https://en.wikipedia.org/wiki/Apple_Icon_Image_format) or [this
8//! analysis](https://github.com/relikd/icns-analysis) for more details about
9//! the file format. If you prefer to learn by example, you can just skip down
10//! to the [Example usage](#example-usage) section below.
11//!
12//! An ICNS file encodes a collection of images (typically different versions
13//! of the same icon at different resolutions) called an _icon family_. The
14//! file consists of a short header followed by a sequence of data blocks
15//! called _icon elements_. Each icon element consists of a header with an
16//! _OSType_ -- which is essentially a four-byte identifier indicating the type
17//! of data in the element -- and a blob of binary data.
18//!
19//! Each image in the ICNS file is encoded either as a single icon element, or
20//! as two elements -- one for the color data and one for the alpha mask. For
21//! example, 48x48 pixel icons are stored as two elements: an `ih32` element
22//! containing compressed 24-bit RGB data, and an `h8mk` element containing the
23//! 8-bit alpha mask. By contrast, 64x64 pixel icons are stored as a single
24//! `icp6` element, which contains either PNG or JPEG 2000 data for the whole
25//! 32-bit image.
26//!
27//! Some icon sizes have multiple possible encodings. For example, a 128x128
28//! icon can be stored either as an `it32` and an `t8mk` element together
29//! (containing compressed RGB and alpha, respectively), or as a single `ic07`
30//! element (containing PNG or JPEG 2000 data). And for some icon sizes, there
31//! are separate OSTypes for single and double-pixel-density versions of the
32//! icon (for "retina" displays). For example, an `ic08` element encodes a
33//! single-density 256x256 image, while an `ic14` element encodes a
34//! double-density 256x256 image -- that is, the image data is actually 512x512
35//! pixels, and is considered different from the single-density 512x512 pixel
36//! image encoded by an `ic09` element.
37//!
38//! Finally, there are some additional, optional element types that don't
39//! encode images at all. For example, the `TOC` element summarizes the
40//! contents of the ICNS file, and the `icnV` element stores version
41//! information.
42//!
43//! # API overview
44//!
45//! The API for this library is modelled loosely after that of
46//! [libicns](http://icns.sourceforge.net/apidocs.html).
47//!
48//! The icon family stored in an ICNS file is represeted by the
49//! [`IconFamily`](struct.IconFamily.html) struct, which provides methods for
50//! [reading](struct.IconFamily.html#method.read) and
51//! [writing](struct.IconFamily.html#method.write) ICNS files, as well as for
52//! high-level operations on the icon set, such as
53//! [adding](struct.IconFamily.html#method.add_icon_with_type),
54//! [extracting](struct.IconFamily.html#method.get_icon_with_type), and
55//! [listing](struct.IconFamily.html#method.available_icons) the encoded
56//! images.
57//!
58//! An `IconFamily` contains a vector of
59//! [`IconElement`](struct.IconElement.html) structs, which represent
60//! individual data blocks in the ICNS file. Each `IconElement` has an
61//! [`OSType`](struct.OSType.html) indicating the type of data in the element,
62//! as well as a `Vec<u8>` containing the data itself. Usually, you won't
63//! need to work with `IconElement`s directly, and can instead use the
64//! higher-level operations provided by `IconFamily`.
65//!
66//! Since raw OSTypes like `t8mk` and `icp4` can be hard to remember, the
67//! [`IconType`](enum.IconType.html) type enumerates all the icon element types
68//! that are supported by this library, with more mnemonic names (for example,
69//! `IconType::RGB24_48x48` indicates 24-bit RGB data for a 48x48 pixel icon,
70//! and is a bit more understandable than the corresponding OSType, `ih32`).
71//! The `IconType` enum also provides methods for getting the properties of
72//! each icon type, such as the size of the encoded image, or the associated
73//! mask type (for icons that are stored as two elements instead of one).
74//!
75//! Regardless of whether you use the higher-level `IconFamily` methods or the
76//! lower-level `IconElement` methods, icons from the ICNS file can be decoded
77//! into [`Image`](struct.Image.html) structs, which can be
78//! [converted](struct.Image.html#method.convert_to) to and from any of several
79//! [`PixelFormats`](enum.PixelFormat.html) to allow the raw pixel data to be
80//! easily transferred to another image library for further processing. Since
81//! this library already depends on the PNG codec anyway (since some ICNS icons
82//! are PNG-encoded), as a convenience, the [`Image`](struct.Image.html) struct
83//! also provides methods for [reading](struct.Image.html#method.read_png) and
84//! [writing](struct.Image.html#method.write_png) PNG files.
85//!
86//! # Limitations
87//!
88//! The ICNS format allows some icon types to be encoded either as PNG data or
89//! as JPEG 2000 data; however, when encoding icons, this library always uses
90//! PNG format.
91//!
92//! Additionally, this library does not yet support a few of the newer icon
93//! entry variants used by later versions of Mac OS, which may contain metadata
94//! (like `info`) or nested files (like `slct` or `sbtp`). Pull requests
95//! (with suitable tests) are welcome.
96//!
97//! # Example usage
98//!
99//! ```no_run
100//! use icns::{IconFamily, IconType, Image};
101//! use std::fs::File;
102//! use std::io::{BufReader, BufWriter};
103//!
104//! // Load an icon family from an ICNS file.
105//! let file = BufReader::new(File::open("16.icns").unwrap());
106//! let mut icon_family = IconFamily::read(file).unwrap();
107//!
108//! // Extract an icon from the family and save it as a PNG.
109//! let image = icon_family.get_icon_with_type(IconType::RGB24_16x16).unwrap();
110//! let file = BufWriter::new(File::create("16.png").unwrap());
111//! image.write_png(file).unwrap();
112//!
113//! // Read in another icon from a PNG file, and add it to the icon family.
114//! let file = BufReader::new(File::open("32.png").unwrap());
115//! let image = Image::read_png(file).unwrap();
116//! icon_family.add_icon(&image).unwrap();
117//!
118//! // Save the updated icon family to a new ICNS file.
119//! let file = BufWriter::new(File::create("16-and-32.icns").unwrap());
120//! icon_family.write(file).unwrap();
121//! ```
122
123#![warn(missing_docs)]
124
125extern crate byteorder;
126
127#[cfg(feature = "pngio")]
128extern crate png;
129
130#[cfg(feature = "pngio")]
131mod pngio;
132
133#[cfg(feature = "jp2io")]
134extern crate hayro_jpeg2000;
135
136#[cfg(feature = "jp2io")]
137mod jp2io;
138
139mod element;
140pub use self::element::IconElement;
141
142mod family;
143pub use self::family::IconFamily;
144
145mod icontype;
146pub use self::icontype::{Encoding, IconType, OSType};
147
148mod image;
149pub use self::image::{Image, PixelFormat};
150
151mod palette;