Skip to content
AZ Tools

BMP / DIB Inspector

Open a .bmp or .dib in your browser: header version, bit depth, row order, compression, colour masks, palette, and where every byte of the file goes.

How to use

  1. Drop a .bmp or .dib file onto the box. It is read in this tab; nothing is uploaded.
  2. Start at the overview: the real dimensions, the bit depth, which DIB header version the file uses, and whether the rows are bottom-up or top-down.
  3. Read the findings. Each one names a specific thing about this file — a top-down row order, a gap before the pixels, a fourth byte that is not alpha, a declared size that does not match the real one.
  4. Compare the two previews. The left one is decoded from the header on this page; the right one is your browser's own decoder on the same bytes. If they differ, the file is relying on something one of them does not implement.
  5. Open the channel masks and the byte layout when you are debugging a decoder: the masks say whether a 16-bit file is 5-5-5 or 5-6-5, and the layout says where the header, palette, gap, pixels and trailing bytes each start.

About this tool

Show

Reads a BMP the way a decoder has to, straight out of the bytes and entirely in your browser. The 14-byte file header gives the declared file size, the two reserved words and bfOffBits — the offset of the pixel array, which is authoritative: the gap between the end of the palette and the pixels is legal, real files contain one, and a reader that assumes the pixels follow the palette reads garbage. The DIB header then identifies its own version by its size, and only the fields that version defines are read: 12 is a BITMAPCOREHEADER with unsigned 16-bit dimensions, three-byte palette entries and no compression field at all; 40 is the familiar BITMAPINFOHEADER; 52 and 56 are the undocumented V2 and V3 headers that fold the RGB and RGBA masks into the header itself; 108 adds a colour space and gamma; 124 adds a rendering intent and an ICC profile. A negative biHeight means the rows are stored top-down and the real height is its absolute value, which is exactly why a naive reader shows the picture upside down; rows are padded to a multiple of four bytes, and the stride and the padding per row are spelled out because that is where hand-written decoders go wrong. For BI_BITFIELDS the red, green, blue and alpha masks are decoded into a bit position and a width, since a 16-bit BMP is 5-5-5 or 5-6-5 depending on nothing else in the file. For BI_JPEG and BI_PNG the pixel array is an entire file of another format, so it is identified and named rather than read as scanlines. The uncompressed depths — 1, 4, 8, 16, 24 and 32 — and both run-length encodings are decoded here, honouring the masks, the palette and the row order, and the same bytes are handed to your browser's own BMP decoder so the two sit side by side; a disagreement between them is the interesting case, not a bug in the page. What it cannot tell you is whether a 32-bit file's fourth byte was meant as alpha: a plain 40-byte BI_RGB file has no alpha by the letter of the spec, most writers put one there anyway, and that ambiguity is reported as an ambiguity rather than guessed at.

Frequently asked questions

Why does my BMP come out upside down?

Because bottom-up is the default. A BMP stores the last row of the image first unless biHeight is negative, in which case the rows run top-down and the real height is the absolute value of the field. Almost every image format stores rows top-down, so a decoder written from habit rather than from the spec produces a vertically mirrored picture on the common case and a correct one on the rare case. This page reports the stored value and the sign separately, so you can see which kind of file you have before you go looking through your own code.

What is the gap between the palette and the pixel array for?

Nothing, usually — it is slack that a writer left behind, and it is entirely legal because the pixel array is located by bfOffBits in the file header and not by adding up the sizes of everything before it. Some writers align the pixel array to a disk sector, some reserve room for a palette they never filled in, and some simply leave the space a previous edit vacated. A reader that computes the offset itself instead of trusting bfOffBits will start reading a few bytes early or late and produce a diagonally skewed image, which is the classic symptom.

Is the fourth byte of a 32-bit BMP an alpha channel?

By the letter of the specification, not in a plain BI_RGB file: the byte is documented as unused padding, and the format only gains a real alpha channel through an alpha mask under BI_BITFIELDS or BI_ALPHABITFIELDS, or through a V4 or V5 header that names one. In practice most writers store alpha there anyway, and most readers ignore it — Pillow, for one, reads such a file back as plain RGB. The result is a file that looks correct in one program and either black or invisible in another, and there is no way to settle it from the bytes alone. This page tells you which of the two cases you have rather than guessing.

How do I tell whether a 16-bit BMP is 5-5-5 or 5-6-5?

Only from the channel masks. Both pack a pixel into two bytes, both declare 16 bits per pixel, and nothing else in the header distinguishes them; the red, green and blue masks say which bits belong to which channel, and the green mask is five bits wide in one and six in the other. A 16-bit BI_RGB file with no mask block at all is 5-5-5 by default. This page decodes each mask into the position of its lowest set bit and how many contiguous bits it covers, which is the form you actually need when writing a shift-and-scale in a decoder.

What are BI_RLE8 and BI_RLE4, and does anything still write them?

They are simple run-length encodings for 8-bit and 4-bit paletted images: a byte pair is either a run of one colour or an escape, and the escapes cover end-of-line, end-of-bitmap and a delta that jumps the cursor by an x and a y offset and leaves everything it skipped undefined. They were meant for the era when a bitmap on a floppy was worth compressing, and they still turn up in old Windows resources and in files produced by legacy tooling. Both are decoded here, and the number of delta escapes and how many pixels they left unwritten are reported, since those pixels are the part where readers visibly differ.

Does the file get uploaded anywhere?

No. The file is read with the browser's File API and parsed by JavaScript in this page, and the previews are drawn on a canvas in the same tab. There is no server-side component to send anything to. That matters for this kind of tool more than most: a bitmap you are inspecting is often a screenshot, a scan or an asset from something you are not free to hand to a web service. You can disconnect from the network after the page has loaded and everything on it still works.

Related tools