BMP/DIB image file format encoding and decoding utilities using binary structures.

This module provides coders for the classic Windows BMP container:

  • bitmapFileHeader — the 14-byte BITMAPFILEHEADER (signature + sizes + pixel offset)
  • bitmapInfoHeader — the 40-byte BITMAPINFOHEADER (the most common DIB header)
  • bmp — a full file coder for uncompressed (BI_RGB) BITMAPINFOHEADER images without a colour palette, i.e. 16/24/32 bpp.

Design notes

  • DIB variants: only BITMAPINFOHEADER (size = 40) is shipped. V4/V5 and the OS/2 BITMAPCOREHEADER are intentionally out of scope — read the size field from bitmapFileHeader and dispatch externally if you need them.
  • Pixel-data sizing: the file-level coder derives the pixel buffer length from the DIB's width/height/bpp via rowStride * |height|, ignoring the (frequently-zero) imageSize field. Use rowStride / pixelDataSize for stride math when composing your own coders.
  • Top-down images: a negative height is preserved verbatim. We never flip rows for you — pixel orientation is the caller's responsibility.
  • Palette: ≤ 8bpp images require a colour table between the DIB header and the pixel data; that path is not yet covered by bmp. Use the sub-coders to compose it yourself.
  • Endianness: every BMP integer is little-endian.

Examples

Round-trip a tiny 2×2 24bpp BMP

import { assertEquals } from "@std/assert";
import { bmp } from "@binstruct/bmp";

const coder = bmp();
const image = {
  file: {
    signature: "BM",
    fileSize: 70,
    reserved1: 0,
    reserved2: 0,
    pixelOffset: 54,
  },
  dib: {
    size: 40,
    width: 2,
    height: 2,
    planes: 1,
    bpp: 24,
    compression: 0,
    imageSize: 16,
    xPixelsPerMeter: 2835,
    yPixelsPerMeter: 2835,
    colorsUsed: 0,
    importantColors: 0,
  },
  // 2 rows × stride 8 = 16 bytes of BGR pixels with 2 bytes padding per row.
  // deno-fmt-ignore
  pixelData: new Uint8Array([
    0x00, 0x00, 0xff,  0xff, 0x00, 0x00,  0x00, 0x00,
    0x00, 0xff, 0x00,  0xff, 0xff, 0xff,  0x00, 0x00,
  ]),
};

const buffer = new Uint8Array(image.file.fileSize);
const bytesWritten = coder.encode(image, buffer);
const [decoded, bytesRead] = coder.decode(buffer);

assertEquals(bytesWritten, 70);
assertEquals(bytesRead, 70);
assertEquals(decoded.file.signature, "BM");
assertEquals(decoded.dib.bpp, 24);
assertEquals(decoded.pixelData, image.pixelData);