.BMP FILE FORMAT (UN-LAMED) BY YSS (Text version - Right click to download)
.BMP FILE FORMAT (UN-LAMED) BY YSS
----------------------------------
This reference text is all copyright material, but this internet version
can be distributed freely to anyone. All material has been tested.
Compressed .BMPs not discussed. All values are 'hex' unless not obvious.
Any incomplete understanding of an offset description, see comments below.
OFFS. BYTES
ADDR. USED
^ ^
0000 2 42 4D -> ASCII 'BM'= .BMP ID
0002 4 File size (4 Byte LO-HI)
0006 4 Reserved. Set to 0
000A 4 Offset to where actual bitmap starts
000E 4 Offset from here to RGB index tbl (should be 40 decimal always??)
0012 4 This bitmap's Pixel width (must be rounded to 4 byte boundary)
0016 4 '' '' '' height
001A 2 # of planes. Always set to 1.
001C 2 # of bits/pixel. Values: 1,4,8,16,24 decimal ONLY?? (see 0036)
001E 2 Compression. 0=not cpx'd. 1=256 color cpx'd. 2=16 color cpx'd
0022 4 Byte size of bitmap image
0026 4 Horizontal resolution (pixels/meter)
002A 4 Vertical '' '' ''
002E 4 # of 4 byte entries in RGB index tbl. 0=max # of entries used
0032 4 # of important colors in index tbl. 0=all colors important
0036 ?? RGB index color tbl stored as 4 bytes blu-grn-red-0.
Stored in order of importance. Most important colors first.
If # of bits/pixel = 24 -> $ tbl doesn't exist and bitmap
immediately follows, starting at this 0036. (001C=bits/pixel).
The # of 4 byte indexes is in [002E], unless [002E]=0, in which
case there will be the maximum # of colors allowed by 001C.
Bitmap follows immediately after this tbl. Offset start found at
[000A] (see above). Lenght in [0022]. So..
[000A] [22] Start of bitmap.
. Bitmap stored in scan lines, from left to right, starting from
. bottom, going upwards.
.
(NOTE FOR BEGINNERS: Note how there are three columns in the memory map
list. The first column is named 'OFFS. ADDR.' and it has a bunch of
hexadecimal numbers below it. The second column is named 'BYTES USED' and
has some numbers as well. Here are the meanings:
'OFFS. ADDR.' means "offset address" and that column is an offset (a number
to be added) to the address in memory of the bitmap itself, if you load it
someway into memory from a file. What that means is that offset 0000 is the
very first byte of the file. Offset 0002 is the THIRD byte of the file, and
so on..
'BYTES USED' is the number of bytes one has to read starting at that very
offset (in lo-hi format) in order to get an actual useful value for that
entry. Hang in there, you'll figure it out in time.)
COMMENTS
--------
This .BMP format description is not a thorough study of the .BMP format, since
that wasn't intended. It's merely a translation into a real programmer's
logical understanding of whatever those microsoft "brains" tried to say in the
"official documentation" on the format itself. Take a look at it yourself
and you'll know exactly what we mean.
Ah the process of thought...
Here's an estimate on the offset values' meanings according to observations.
Some of the estimates were observed directly from .BMP files, while others
from the "translation" itself. No guarantees can be made since this format
isn't our stuff:
0006 (RESERVED) can be ignored. Absolute waste of space.
000E (Offset from here to RGB index tbl) may be ignored, since it seems to be
40 decimal always, -> 28 00 00 00
** this value seems to hold true, and as far as our study went it
did, but watch out for it. If you'll be writing serious
graphics viewers, plan on using it.
0012 (Pixel width) = number of pixels on a scan line of this bitmap.
The actual value to be used has to be calculated to the nearest next 4
byte boundary, because one scan line won't immediately follow the other
within the file. This is reasonable, since a variety of pixel packing
formats were needed. Example:
If value in [0012] = 2962 decimal, ->
value to use in my read routine = 2964. Why? ->
2962/4 = 740.5, and 740*4 = 2960, which is 2 bytes behind,
and we need the NEXT nearest byte boundary. Therefore,
add 4 to result of 740*4, -> 2964.
One 8086 machine language approach can be:
XOR BH,BH
MOV AX,0B92 ->2962 decimal
SHR AX,1
RCL BH,1 (OR RCR)
SHR AX,1
RCL BH,1
SHL AX,1
SHL AX,1
TEST BH,BH
JE A:
ADD AX,0004
A:
At this point, AX has the usable pixel width value.
(Note how there's no instruction/parameter indenting
and how it's all CAPITALS. See XMPL0012.COM)
0016 (Pixel height)= number of scan lines in this bitmap.
001A (# of planes) can be ignored. Always 1, -> 01 00 00 00 (That's what
the official document says anyway)
001C (# of bits/pixel): For the possible values 1,4,8,16,24 :
1 = 2 colors, foreground/b'ground -> 01 00
4 = 16 '' -> 04 00
8 = 256 '' (2^8) -> 08 00
16 = 65536 '' -> 10 00
if 24 -> no RGB index tbl used. -> 18 00
What a great idea, to use TWO BYTES to store either a 1, a 4, an 8,
a 16 or a 24 ONLY!! Brilliant!
001E (Compression) is 0 if the bitmap isn't compressed, -> 00 00.
1 = RLE8 -> 01 00
2 = RLE4 -> 02 00
They have 2 compression methods, which they call RLE8 and RLE4. Don't
let the fancy letters fool you. They're pretty simple.
These compression formats won't be discussed here.
0022 (Byte size of bitmap image):
If a bitmap image is 70 pixels wide by 40 pixels high, ->
it occupies 70*40 pixels -> 2800 pixels.
If it's a 4 bits/pixel image, that is, a 16 color image (2^4),
-> it only occupies half the bytes, since 2 pixels will be fitted
on a single byte. Therefore, a 1400 would be stored in this offset,
so 1400 decimal goes as -> 78 05.
If pixels are 8 bits long -> for the same image of 70x40 pixels,
2800 bytes are used, so the value 2800 decimal goes here (F0 0A).
0026 and 002A (Horizontal and vertical resolution in pixels/meter,
respectively) can be ignored, unless one's doing professional scientific
graphics, in which case one wouldn't be using this ridiculous format
anyway.
0032 (# of important colors in index tbl)
Important colors are those that have the highest precedence on the
bitmap, in a manner that by lacking the other not-so important colors
the bitmap may still be dithered to display an acceptable image.
No comments.
0036 (Actual RGB index tbl):
RGB index tbl has the values to be loaded into VGA's palette regs to
get the right mixes stored blu-green-red, and a 0. Ex:
for RGB values R=141 G=12 B=58, an index entry would be
3A 0C 8D 00
For 256 color values -which is what we tested upon- the bytes, being
supposed to have values to be written directly into the DAC's color
registers needed to be divided by 64 decimal before being actually
output to the registers to get useful results. This is an increased
level of precision for color values, but they never mentioned the fact
in any of the format descriptions we read. That's the kind of stuff
you just have to guess.
The pixel values in the bitmap will be actual indexes into this RGB
table, of course (VGA programmers know this).
** If there are 24 bits/pixel, that is, if offset 001C has a value of
18 00 (24 decimal) -> this offset (0036) will be the actual start
of the bitmap itself.
** If RGB index tbl exists, ->
it will have a byte size of 4 times the value in offset 002E,
unless the value in 002E is 0.
If the value in 002E is 0 -> there will be a maximum # of entries
according to the value in 001C:
001C = 1 -> 2 RGB entries (8 bytes, since each entry is 4 bytes)
= 4 -> 16 '' '' (64 bytes)
= 8 -> 256 '' '' (1024 bytes)
=16 -> 65536
and of course, if = 24 -> RGB index tbl non-existent, so
bitmap follows immediately at this same offset 0036.
Same thing put another way:
If RGB index tbl exists (that is, [001C] <> 24 decimal), ->
len of RGB index tbl = [002E]*4, unless [002E]=0, in which case,
'' '' '' '' = 2^[001C]*4
About the start of the actual bitmap:
------------------------------------
003E = start of bitmap in case of a 24 bits/pixel bitmap
** The actual bitmap follows the RGB index tbl, if any. If there's no such
table, which is the case ONLY in case of 24 bits/pixel, then the start
is offset 003E.
000A appears to have the start of the actual bitmap in any case, so it can be
looked up to see where the bitmap will start. It's byte length is in
offset 0022 which can be seen as redundant, since nothing else follows
the bitmap. The length could be easily calculated from
len = file length - bitmap start.
Bottom line on .BMP: "Redundancy, repetition, logic..??
Buy, reproduce, obey.. WASTE". Dilbert comics are SO right.
Otherwise it's a "viable" graphics storage format :) .
Yss1989-,sdD+J.
pixelrat@hotmail.com