Resources are the records from the MOBI header’s firstResourceRecord
onwards that hold images, fonts and a few other things the text refers to. They are
numbered from 1 at firstResourceRecord, and the text points to them with
kindle:embed:XXXX links,
where XXXX is that number in base 32. The cover and thumbnail are found
through EXTH 201 and 202, which count from 0. A reader tells the kinds of record apart by
their first bytes. Amazon has not documented any of this; it follows calibre and
KindleUnpack.
Kinds of resource record
| First bytes | Record | What a reader does |
|---|---|---|
FF D8 FF, 89 50 4E 47, GIF8, BM | An image: JPEG, PNG, GIF or BMP, stored whole | Use it as it is. |
FONT | An embedded font: see FONT record | Decode it into a TrueType or OpenType font. |
RESC | Spine and page information from the source package: see RESC | Optional; used to rebuild the OPF. |
A0 A0 A0 A0 | A placeholder for a resource kept elsewhere, such as an image moved to the high-resolution container | Skip, but count it. |
CONT, CRES | High-resolution container records: see HD containers | Found in the separate .azw.res file rather than the book. |
FLIS, FCIS, FDST, DATP, SRCS, CMET, PAGE, AUDI, VIDE, BOUN, E9 8E 0D 0A | Not resources | Skip; they may lie after the resources. |
A PAGE record holds page-number data for books with real page numbers;
its layout is not documented.
FONT record
Each embedded font takes one record. The font may be compressed with zlib and its start may be obfuscated with an XOR key, so that it cannot simply be copied out.
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
0 | 4 | char[4] | identifier | FONT. |
4 | 4 | UInt32 | decodedSize | The size of the font once decoded. |
8 | 4 | UInt32 | flags | Bit 0 (0x1): the font data is zlib-compressed. Bit 1 (0x2): the font data is XOR-obfuscated. |
12 | 4 | UInt32 | dataOffset | Where the font data starts in this record; it runs to the end of the record. |
16 | 4 | UInt32 | keyLength | The length of the XOR key. |
20 | 4 | UInt32 | keyOffset | Where the XOR key starts in this record. |
To decode: take the bytes from dataOffset to the end. If bit 1 is set,
XOR each of the first 1,040 bytes (or fewer, if the data is shorter) with the key,
byte n with key byte n mod keyLength. Then, if bit
0 is set, inflate the result with zlib. The output is a TrueType or OpenType font of
decodedSize bytes; its first four bytes (00 01 00 00 or
OTTO) tell which.
The order matters: the XOR is applied to the compressed bytes, so it is undone first.
RESC
A RESC record keeps part of the source OPF package that KF8 has no other
place for, chiefly the spine: one itemref per XHTML file, tied to the
skeleton numbers, with properties such as page-spread-left and
page-spread-right for fixed-layout books. After the four-byte identifier
come a short binary header and then the text, which is XML. The header’s layout is not
documented. KindleUnpack reads the XML to rebuild the spine and its properties.
HD containers
Books with high-resolution images, mostly comics and fixed-layout books, can come
with a second file, .azw.res (or .azw6), that is also a Palm
database. It starts with a CONT record describing the container, holds the
large images in CRES records, one per image, and ends with a record that is
the 12 bytes CONTBOUNDARY. In the book itself, the matching resource records
are A0 A0 A0 A0 placeholders or smaller versions of the images, so the
resource numbers in both files line up. EXTH 536 in the book describes the container.
The internal layouts of CONT and CRES records beyond their
identifiers and the image data are not publicly documented.