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