Image 🖼️

Image

Image format #

The image format used in apps use a BPP (Bits Per Pixel) density of either:

  • 1 BPP: supports 2 colors
  • 2 BPP: supports 4 colors
  • 4 BPP: supports 16 colors

They are either bundled with the app ROM by specifying them in the firefly.toml config or can be generated and modified during runtime.

Data structure of an image:

Section Length (bytes) Data
header 1 magic number 0x21 (marker that signals that this binary is an image)
header 1 BPP (Bits Per Pixel). Either set to 0x01, 0x02, or 0x04
header 2 image width (16-bit, little-endian)
header 1 transparency color. Only lower 4 bits are used
header BPP * 2 color palette, with 1 nibble (4 bits) per color
body width * height * BPP / 8 image body (rest of the image)

The first 5 bytes + BPP * 2 bytes together are considered the header.

Color #

The color palette is an array of colors, where each color is represented as a nibble (4 bits).

  • With 1 BPP, palette is 1 byte and stores 2 colors
  • With 2 BPP, palette is 2 bytes and stores 4 colors
  • With 4 BPP, palette is 8 bytes and stores 16 colors
Hex Binary Color
0x0 0000 #1A1C2C: Black
0x1 0001 #5D275D: Purple
0x2 0010 #B13E53: Red
0x3 0011 #EF7D57: Orange
0x4 0100 #FFCD75: Yellow
0x5 0101 #A7F070: LightGreen
0x6 0110 #38B764: Green
0x7 0111 #257179: DarkGreen
0x8 1000 #29366F: DarkBlue
0x9 1001 #3B5DC9: Blue
0xA 1010 #41A6F6: LightBlue
0xB 1011 #73EFF7: Cyan
0xC 1100 #F4F4F4: White
0xD 1101 #94B0C2: LightGray
0xE 1110 #566C86: Gray
0xF 1111 #333C57: DarkGray

These nibbles are then packed together into bytes that form the palette.

Therefore, a color palette for a 2-BPP using Gray, Green, Blue, Yellow would be represented as:

hex         0xE6     0x94
binary  11100110 10010100

Transparency #

Image transparency is decided by the transparency color. Any pixel in the image body that matches the same color as the transparency color are considered transparent.

If the transparency color is set to a value greater than or equal to 1 << BPP, then the image is considered to have no transparency. Meaning:

  • With 1 BPP, if transparency color is 0x02 or higher, then no transparency
  • With 2 BPP, if transparency color is 0x04 or higher, then no transparency
  • With 4 BPP, if transparency color is 0x10 or higher, then no transparency

For images without transparency it is common to use a value of 0xFF, though any value above the threshold are equally valid.

Image body #

The image body is a string of pixels whose value reference a color in the palette.

  • With 1 BPP, each 1-bit pixel targets palette color at index 0x0 - 0x1
  • With 2 BPP, each 2-bit pixel targets palette color at index 0x0 - 0x3
  • With 4 BPP, each 4-bit pixel targets palette color at index 0x0 - 0xF

Therefore, a 2x2 pixel image with 2-BPP that uses all 4 colors from the palette could be represented by:

hex         0x1b
binary  00011011

Using the 2-BPP color palette example from above, then the image would look like this:

Examples #

Example: 1-BPP #

4x4 pixels image with 1-BPP:

  • header: 7 bytes
  • body: 2 bytes
  • total: 9 bytes
     ┌► header
0x21 ┤ ─► magic number (marker that signals that this is an image)
0x01 ┤ ─► bits per pixel (BPP, either 0x01, 0x02, or 0x04)
0x04 ┤ ┬► image width, 16 bit little-endian
0x00 ┤ ┘
0xFF ┤ ─► transparency color
0x24 ┘ ─► 1 byte color palette (2 colors)
     ┌► image body
0xC3 ┤ ─► row 1 & row 2
0x9B ┘ ─► row 3 & row 4

Example: 2-BPP #

4x4 pixels image with 2-BPP:

  • header: 9 bytes
  • body: 4 bytes
  • total: 13 bytes
     ┌► header
0x21 ┤ ─► magic number (marker that signals that this is an image)
0x02 ┤ ─► bits per pixel (BPP, either 0x01, 0x02, or 0x04)
0x04 ┤ ┬► image width, 16 bit little-endian
0x00 ┤ ┘
0xFF ┤ ─► transparency color
0x2B ┤ ┬► 2 bytes color palette (4 colors)
0x5A ┘ ┘
     ┌► image body
0xEC ┤ ─► row 1
0xAF ┤ ─► row 2
0x50 ┤ ─► row 3
0x91 ┘ ─► row 4

Example: 4-BPP #

4x4 pixels image with 4-BPP:

  • header: 13 bytes
  • body: 8 bytes
  • total: 21 bytes
     ┌► header
0x21 ┤ ─► magic number (marker that signals that this is an image)
0x04 ┤ ─► bits per pixel (BPP, either 0x01, 0x02, or 0x04)
0x04 ┤ ┬► image width, 16 bit little-endian
0x00 ┤ ┘
0x01 ┤ ─► transparency color
0x01 ┤ ┬► 8 bytes color palette (16 colors)
0x23 ┤ ┤
0x45 ┤ ┤
0x67 ┤ ┤
0x89 ┤ ┤
0xAB ┤ ┤
0xCD ┤ ┤
0xEF ┘ ┘
          ┌► image body
0x01 0x23 ┤ ─► row 1
0x45 0x67 ┤ ─► row 2
0x89 0xAB ┤ ─► row 3
0xCD 0xEF ┘ ─► row 4

⬅️ ROM ➡️ Screenshot