A bitmap is a character like a shape, and it is usually drawn through a shape’s bitmap fill. There are JPEG tags and lossless tags. In a CWS movie they sit in the decompressed data; their own image data is compressed again inside them (JPEG, or zlib for lossless pixels and alpha planes). Rows always run top to bottom.
DefineBits (6)
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
| 0 | 2 | UI16 | CharacterID | The character ID |
| 2 | … | bytes | JPEGData | JPEG data without its tables, to the end of the tag |
SWF 1. The quantisation and Huffman tables are in the movie’s one JPEGTables tag, shared by every DefineBits.
JPEGTables (8)
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
| 0 | … | bytes | JPEGData | The encoding tables (DQT, DHT) as a JPEG stream |
A movie has at most one. Some movies’ JPEGTables is only FF D8 FF D9,
with no tables in it.
DefineBitsJPEG2 (21)
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
| 0 | 2 | UI16 | CharacterID | The character ID |
| 2 | … | bytes | ImageData | A complete JPEG with its tables; from SWF 8 also a PNG or a non-animated GIF89a |
SWF 2. The first bytes tell the image types apart: FF D8 JPEG,
89 50 4E 47 0D 0A 1A 0A PNG, GIF89a GIF.
DefineBitsJPEG3 (35)
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
| 0 | 2 | UI16 | CharacterID | The character ID |
| 2 | 4 | UI32 | AlphaDataOffset | The size of ImageData |
| 6 | AlphaDataOffset | bytes | ImageData | A JPEG (PNG or GIF from SWF 8) |
| … | … | bytes | BitmapAlphaData | A zlib stream: one alpha byte a pixel, for JPEG images |
SWF 3. For PNG or GIF image data the alpha comes from the image itself. Whether Flash Player premultiplies the JPEG’s colours by this alpha is not confirmed; the explorer does not divide them out.
DefineBitsJPEG4 (90)
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
| 0 | 2 | UI16 | CharacterID | The character ID |
| 2 | 4 | UI32 | AlphaDataOffset | The size of ImageData |
| 6 | 2 | UI16 | DeblockParam | 8.8 fixed point: the strength of the deblocking filter, 0 to 1 |
| 8 | AlphaDataOffset | bytes | ImageData | A JPEG, PNG or GIF |
| … | … | bytes | BitmapAlphaData | zlib-compressed alpha, as in DefineBitsJPEG3 |
SWF 10.
JPEG data in Flash movies
- Erroneous header: the specification notes that before SWF 8 the JPEG data could start with
FF D9 FF D8before the real start-of-image marker. A CWS movie of SWF 6 or 7 may have it. - Two streams: Flash wrote DefineBitsJPEG2 and 3 data as a stream of tables followed by the image stream,
FF D8tablesFF D9 FF D8imageFF D9. Browsers do not accept that as an image. That Flash wrote it this way comes from experience of such files, which swftools and other converters handle; it is not from the specification text. - For DefineBits, the tables from JPEGTables and the image data together make one JPEG.
The explorer decodes the JPEG itself, baseline and progressive, with and without JPEGTables, and the erroneous header and double streams, so every embedded bitmap shows.
DefineBitsLossless (20)
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
| 0 | 2 | UI16 | CharacterID | The character ID |
| 2 | 1 | UI8 | BitmapFormat | 3 = 8-bit colour-mapped, 4 = 15-bit RGB, 5 = 24-bit RGB |
| 3 | 2 | UI16 | BitmapWidth | In pixels |
| 5 | 2 | UI16 | BitmapHeight | In pixels |
| 7 | 1 | UI8 | BitmapColorTableSize | Format 3 only: the number of colours minus 1 |
| 7 or 8 | … | bytes | ZlibBitmapData | A zlib stream holding the pixels, to the end of the tag |
SWF 2. Inflated, the data is:
| Format | Inflated data | Pixel |
|---|---|---|
| 3 | COLORMAPDATA: the colour table, RGB × (BitmapColorTableSize + 1), then one UI8 index a pixel, each row padded to a multiple of 4 bytes | a palette index |
| 4 | BITMAPDATA of PIX15, each row padded to a multiple of 4 bytes | UB[1] reserved, UB[5] red, UB[5] green, UB[5] blue: 2 bytes |
| 5 | BITMAPDATA of PIX24 | UI8 reserved, then red, green and blue: 4 bytes |
DefineBitsLossless2 (36)
SWF 3. The same fields as DefineBitsLossless, with alpha:
| Format | Inflated data | Pixel |
|---|---|---|
| 3 | ALPHACOLORMAPDATA: an RGBA colour table, then one UI8 index a pixel, rows padded to 4 bytes | a palette index |
| 4 | not used | |
| 5 | ALPHABITMAPDATA | ARGB: alpha, red, green, blue |
The colour values are premultiplied by alpha, as Flash Player and Ruffle read them; the explorer divides them back out for display.
Getting the pixels
- For a lossless bitmap, inflate ZlibBitmapData (a zlib stream with its own header and Adler-32, as in the movie’s own compression).
- Read the colour table first for format 3. Then read rows top to bottom, skipping each row’s padding to a multiple of 4 bytes.
- For DefineBits, join the JPEGTables data and the image data into one JPEG and decode it; for DefineBitsJPEG2, decode the image data as it is, after removing an erroneous header.
- For DefineBitsJPEG3 and 4, inflate BitmapAlphaData to width × height bytes and use them as the alpha of the decoded JPEG.