.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