Every bitmap in the library has a <DOMBitmapItem> in
DOMDocument.xml, whose bitmapDataHRef attribute names a file
in bin/, such as bitmapDataHRef="M 31 1372941248.dat" for
bin/M 31 1372941248.dat. That file is in one of two forms, and
isJPEG on the item says which. The .dat files are stored in
the ZIP archive without compression.
JPEG bitmaps
When the item has isJPEG="true", the .dat file is the JPEG
file itself, exactly as imported: it starts FF D8, with its Exif and other
segments. Renamed to .jpg, it opens in any image viewer. The explorer
shows it as it is.
Lossless bitmaps
Every other bitmap, such as one imported from a PNG, is kept in Flash’s own lossless form: a 26-byte header, then the pixels compressed with zlib and cut into chunks. The same form is used in the Media streams of a binary FLA. All numbers are little-endian.
| Offset | Size | Type | Field | Meaning |
|---|---|---|---|---|
| 0 | 2 | bytes | Signature | 03 05. |
| 2 | 2 | u16 | Row size | Bytes in one row of pixels: the width × 4. |
| 4 | 2 | u16 | Width | In pixels. |
| 6 | 2 | u16 | Height | In pixels. |
| 8 | 4 | u32 | Left | The bitmap’s bounds, in twips (pixels × 20): left edge, 0 in the files seen. |
| 12 | 4 | u32 | Right | Right edge: the width × 20. |
| 16 | 4 | u32 | Top | Top edge, 0 in the files seen. |
| 20 | 4 | u32 | Bottom | Bottom edge: the height × 20. |
| 24 | 1 | u8 | Flags | Bit 0: the bitmap has transparency. Without it, every pixel is opaque. |
| 25 | 1 | u8 | Variant | 1: the pixels follow as zlib data in chunks. This is the only variant the explorer reads. |
| 26 | … | chunks | Pixel data | Chunks, each a u16 length and that many bytes, until a length of zero. |
To read the pixels:
- Read the header and check the signature.
- From offset 26, read a u16 length; if it is zero, stop; otherwise take that many bytes and repeat.
- Join the chunks. They make one zlib stream (RFC 1950, starting
78 01): skip its 2-byte header and inflate the Deflate data to row size × height bytes. - Each row is row size bytes, top row first. Each pixel is four bytes: alpha, red, green, blue.
- The colours are premultiplied: each is stored as colour × alpha ÷ 256. To get the colour back, multiply by 256 ÷ alpha (leave it when alpha is 0). Fully opaque pixels therefore come out one lower than in the original image (255 is stored as 254).
- If bit 0 of the flags is clear, treat every pixel as opaque.
The pixel order was established for this site by decoding
bin/M 31 1372941248.dat of a Flash CS5.5 document beside the PNG it was
imported from, LIBRARY/Assets/Other/minimap.png in the same document,
pixel for pixel. Kreijstal’s notes give the order as alpha, blue, green, red for the
Media streams of binary FLAs; that was not checked against a source image.
00000000 03 05 28 00 0A 00 06 00 00 00 00 00 C8 00 00 00
00000010 00 00 00 00 78 00 00 00 01 01 02 00 78 01 9E 00
00000020 …
bin/M 1 1383060122.dat, a 10 × 6 bitmap| Bytes | Field | Value |
|---|---|---|
03 05 | Signature | a lossless bitmap |
28 00 | Row size | 40 bytes (10 × 4) |
0A 00 | Width | 10 pixels |
06 00 | Height | 6 pixels |
00 00 00 00, C8 00 00 00 | Left, right | 0 to 200 twips (10 pixels) |
00 00 00 00, 78 00 00 00 | Top, bottom | 0 to 120 twips (6 pixels) |
01 | Flags | has transparency |
01 | Variant | zlib in chunks |
02 00 78 01 | First chunk | 2 bytes: the zlib header |
9E 00 … | Second chunk | 158 bytes of Deflate data, and so on |
Other .dat files
Some documents also hold .dat files of 1,296 or 1,584 bytes that are all
zeros. They seem to go with components; what they are has not been established.