Open formats: FBM: Flat bitmap
Last modified on Thu, 22nd Mar 2007 at 13:10 GMT by zipplet1. FBM: Flat Bitmap specification, 22nd March 2007 (version 2.2)
----------------------------------------------------------------
Copyright (c) Michael Nixon (Zipplet) 2004 - 2007.
web: http://www.zipplet.co.uk/, http://www.zipplet.org/
email: zipplet@zipplet.co.uk
1. Changes
----------
Changes since v2.1
------------------
- Made the specification a lot simpler to avoid loader bloat.
- Widened some fields to longints
Changes since v2
----------------
- Changed the size of the identification string to 256 bytes. As you probably
know if you are a delphi programmer, shortstrings are 256 bytes not 255.
- Changed the example (about using the extended info value) to say $100 instead
of $FF for the size of a delphi shortstring.
2. What is it
-------------
Flat bitmap (FBM) is a file format, designed to store various kinds of bitmap
data. It is designed to be more space efficient than BMP (windows bitmap), but
faster to read/decode than PNG (portable network graphic), while still having a
decent feature set.
It stores 32bpp image data with (24bpp with alpha channel) with a variety
of encoding methods to help with compression of the file. Images can be stored
palettised to further improve compression.
3. Why use it
-------------
I designed this file format for use with games, because its easy to write a
loader, and its very fast to decode in comparision to PNG. It is likely that
noone will make use of this format except me, but I document it incase people
want to write add-ons for my games or use it in their own programs.
4. Basic file structure
-----------------------
The FBM file starts with an identification string, which can be used to
detect/verify the file as being in the FBM format. A header follows, which
describes the resource stored in the file. The remainder of the file is the data.
All types shown are types used in the Delphi programming language.
+-------------+-------------+--------------------------------------------------+
| Bytes | Type | Description |
+-------------+-------------+--------------------------------------------------+
| 4 | chars | identifier |
+-------------+-------------+--------------------------------------------------+
| 4 | longint | width of resource, pixels |
+-------------+-------------+--------------------------------------------------+
| 4 | longint | height of resource, pixels |
+-------------+-------------+--------------------------------------------------+
| 1 | byte | bits per palette entry |
+-------------+-------------+--------------------------------------------------+
| 4 | longint | number of palette entries stored, if not flat |
+-------------+-------------+--------------------------------------------------+
| 4*pal | n/a | palette entries |
+-------------+-------------+--------------------------------------------------+
| 1 | byte | image encoding |
+-------------+-------------+--------------------------------------------------+
| 4 | longint | number of bytes to skip for extended info |
+-------------+-------------+--------------------------------------------------+
| n/a | n/a | image data in the described format |
+-------------+-------------+--------------------------------------------------+
5. Detailed breakdown of header
-------------------------------
identifier:
-----------
This is a string of 4 bytes, which as ASCII equal 'FBM2'.
width of resource, pixels:
--------------------------
This is the width of the resource stored, in pixels. 0 is an illegal value for
this item, any other value is OK.
Height of resource, pixels:
---------------------------
This is the height of the resource stored, in pixels. 0 is an illegal value for
this item, any other value is OK.
bits per palette entry:
-----------------------
This is the number of bits allowed for palette entries. In other words, the
number of palettes allowed. For example, specifying 8 here gives you 256 palette
entries maximum, however the image can still be stored in 24 bit colour - just
you are limited to using 256 different colours! This value does NOT at all
describe the colour format. Don't get confused...
To store an image without a palette, set this value to 0.
number of palette entries stored, if not flat:
----------------------------------------------
The number of used palette entries. For example, if an image with an 8-bit
palette uses 0-240 entries, this value will be set to 240, and only 240 entries
are stored in the file. This is more space efficient.
palette entries:
----------------
Each palette entry. numpal+1 entries are stored here. For example, if the
palette entries value says "10", there are 11 (0-10) entries here.
NOTE: 0 (zero) entries are stored if the bits per palette entry field is
set to 0.
image encoding mode
-------------------
NOTE: this field is also used to specify encodings.
$00: No encoding
----------------
(self explanatory)
$01: Planar data order
----------------------
Data is stored as planes in B, G, R, A alpha order. So, instead of:
BGRA BGRA BGRA BGRA
we store:
BBBB GGGG RRRR AAAA
$02: Planar data order with delta encoding
------------------------------------------
Data is stored as planes in B, G, R, A alpha order with delta encoding.
So, instead of:
BGRA BGRA BGRA BGRA
we store:
BBBB GGGG RRRR AAAA
The delta encoding format is quite simple to parse. Begin with the current
value as 0. To get the next plane value, read a byte from the file and add
it to the current value. The current value must be an unsigned byte, so
overflows wrap around ($F0+$10 = $00 not $100).
Generating the delta encoding format:
old := 0;
for each new byte to encode do
val := new - old;
if val < 0 then val := 256 - abs(val);
old := new;
outputbyte(val);
next
The purpose of delta encoding is to make the data easier to compress with
an algorithym such as deflate.
number of bytes to skip for extended info:
------------------------------------------
Usually this is $00, meaning that the image data follows. The point of this
dword is to allow you to add your own tags to the file without it breaking the
file loader. For example, you could set this dword to $100 and store a delphi
shortstring immediately after it, with the authors name. You may store anything
you want in the space you declare with this dword.
image data in the described format:
-----------------------------------
This is the raw image data in the format described. It may or may not be
paletted, and it may or may not be compressed/encoded.