Análisis Profundos

BMP explicado: el formato de imagen más simple de Windows

koboshiCo-founder
·12 min de lectura
BMP explicado: el formato de imagen más simple de Windows
Resumen

BMP forma parte de Windows desde 1990. Almacena píxeles raw con cabeceras mínimas, sin compresión ni canal alpha. Este artículo repasa el formato desde el BITMAPFILEHEADER de 14 bytes hasta los ámbitos en los que todavía aparece, como sistemas embebidos e imagenología médica.

Si abres un archivo BMP en un editor hexadecimal, los primeros catorce bytes se ven así:

42 4D 46 00 00 00 00 00 00 00 36 00 00 00

Esa es la BITMAPFILEHEADER completa. 42 4D es la firma "BM" en ASCII. Los cuatro bytes siguientes indican el tamaño del archivo: 46 00 00 00 equivale en little-endian a 70. Los cuatro bytes posteriores están reservados y siempre son cero. Los últimos cuatro bytes son el desplazamiento hacia los datos de píxeles: 36 00 00 00 es 54, así que la matriz de píxeles comienza en el byte 54.

Sin marcador de compresión, sin perfil de color, sin canal alpha. Solo una firma, un tamaño y un desplazamiento. BMP es, como indica su nombre, un mapa de bits directo.

Qué es BMP

BMP significa Bitmap, o más formalmente Device Independent Bitmap (DIB). Microsoft lo introdujo con Windows 3.0 en 1990 para almacenar imágenes raster sin depender de un dispositivo de pantalla concreto. Antes del DIB, Windows usaba Device Dependent Bitmaps (DDB), cuyo formato de píxel dependía de la tarjeta gráfica instalada. Un DDB guardado en una máquina podía resultar ilegible en otra.

BMP resolvió ese problema almacenando los metadatos necesarios para que cualquier decodificador reconstruyera la imagen: ancho, alto, profundidad de bits, paleta de colores, tipo de compresión y la matriz de píxeles raw. El sistema operativo lee la cabecera, reserva un búfer y copia los píxeles en memoria. En imágenes de 24 bits sin comprimir, los datos de píxeles suelen ser tripletes RGB escritos de abajo hacia arriba, fila por fila, rellenados hasta alcanzar un límite de cuatro bytes.

Esa simplicidad convirtió a BMP en el formato de imagen predeterminado de Windows durante más de una década. Paintbrush, el motor de fondos de pantalla de Windows, los escáneres tempranos e incontables herramientas internas lo usaban de forma nativa.

La estructura del archivo

Un archivo BMP tiene cuatro partes dispuestas en secuencia:

BITMAPFILEHEADER   (14 bytes)
BITMAPINFOHEADER   (40 bytes para la versión clásica)
Color Table        (opcional, para modos de color indexado)
Pixel Data         (la imagen propiamente dicha)

BITMAPFILEHEADER (14 bytes)

Bytes 0-1:   Signature    "BM" (0x42 0x4D)
Bytes 2-5:   FileSize     (uint32, little-endian)
Bytes 6-9:   Reserved     (always 0)
Bytes 10-13: Offset       (uint32, offset to pixel data from file start)

La firma no siempre es "BM". Windows también admite "BA", "CI", "CP", "IC" y "PT" para variantes de cursor e icono, pero en la práctica cualquier BMP que abras comenzará con "BM".

BITMAPINFOHEADER (40 bytes, tipo BITMAPINFOHEADER)

Bytes 0-3:   HeaderSize        (40)
Bytes 4-7:   Width             (int32, pixels)
Bytes 8-11:  Height            (int32, pixels; negative means top-down)
Bytes 12-13: Planes            (1)
Bytes 14-15: BitCount          (1, 4, 8, 16, 24, or 32)
Bytes 16-19: Compression       (0 = none, 1 = RLE8, 2 = RLE4, 3 = bitfields)
Bytes 20-23: ImageSize         (0 if uncompressed)
Bytes 24-27: XpixelsPerMeter   (physical resolution)
Bytes 28-31: YpixelsPerMeter   (physical resolution)
Bytes 32-35: ColorsUsed        (0 means 2^BitCount)
Bytes 36-39: ColorsImportant   (0 means all)

Versiones posteriores de Windows añadieron cabeceras mayores — 52, 56, 108 y 124 bytes — para soportar máscaras alpha, espacios de color y perfiles ICC. La versión de 40 bytes sigue siendo la más habitual.

La altura indica la dirección

Si el campo de altura es positivo, la imagen se almacena de abajo hacia arriba. La fila 0 del archivo corresponde a la fila inferior de la imagen. Si el campo es negativo, la imagen se almacena de arriba hacia abajo. Esta es una de las peculiaridades de BMP: la mayoría de formatos almacenan de arriba hacia abajo por defecto.

La tabla de colores

Para profundidades de 1, 4 u 8 bits, BMP usa una paleta indexada. Cada entrada ocupa cuatro bytes: azul, verde, rojo y un byte alpha reservado que casi siempre se ignora. Un BMP de 256 colores tiene una tabla de 1,024 bytes inmediatamente después de la cabecera. Los datos de píxeles que siguen no son colores: son índices dentro de esa tabla.

Relleno de las filas de píxeles

Cada línea de escaneo debe ocupar un múltiplo de cuatro bytes. Una imagen de 24 bits con 5 píxeles de ancho necesita 15 bytes por fila, que se redondean a 16. Esos bytes de relleno son espacio desperdiciado, otra pequeña razón por la que BMP resulta ineficiente.

A continuación, un ejemplo completo de un BMP de 24 bits sin comprimir de 2 × 2:

Offset 0x00: 42 4D 46 00 00 00 00 00 00 00 36 00 00 00  -- BITMAPFILEHEADER
Offset 0x0E: 28 00 00 00 02 00 00 00 02 00 00 00 01 00 18 00  -- BITMAPINFOHEADER
Offset 0x22: 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00
Offset 0x32: 00 00 00 00 00 00 00 00
Offset 0x36: FF 00 00 00 FF 00 00 00 FF  -- bottom row: red, green, blue (with padding)
Offset 0x3F: 00 FF FF 00 FF FF 00 00 00  -- top row: cyan, magenta, yellow (with padding)

El panorama de formatos en 1990

BMP no apareció en un vacío. Para 1990, varios formatos de imagen ya competían por atención:

FormatoCompresiónProfundidad de colorTransparenciaRiesgo de patenteUso típico
GIFLZWMáximo 256 colores1 bitSí (LZW)Gráficos web
JPEGDCT + Huffman24 bitsNingunaMayormente noFotografías
TIFFMúltiple opcionalHasta 48 bitsOpcionalImpresión, escaneo
PCXRLEHasta 24 bitsNingunaNoJuegos DOS, clip art
PICTRLEHasta 32 bitsNoMac OS clásico
BMPNinguna o RLEHasta 32 bitsNingunaNoFondos de Windows, iconos

GIF ya era el predeterminado en la web, pero su patente LZW hacía arriesgado su uso comercial. JPEG fue diseñado para fotografías y descartaba datos de forma irreversible. TIFF era potente pero sobreingenierizado: escribir un lector TIFF universal era un proyecto en sí mismo. PCX estaba desapareciendo junto con DOS.

La propuesta de BMP era la simplicidad. No era más pequeño, más rápido ni más capaz que los demás. Era simplemente el formato que Windows entendía sin bibliotecas adicionales.

Por qué funcionaba BMP

BMP tenía ventajas reales en su contexto:

Cero complejidad de decodificación. Un BMP de 24 bits sin comprimir puede renderizarse leyendo una cabecera de tamaño fijo y copiando píxeles directamente a un framebuffer. Sin tablas Huffman, sin máquina de estados DEFLATE, sin pasadas progresivas. Esto lo hacía ideal para sistemas embebidos con CPU limitada.

Sin cargas de patente. A diferencia del LZW de GIF, la compresión de BMP era inexistente o RLE, ambas libres de patentes. Eso importaba para herramientas de código abierto y software comercial que quería evitar la licencia de GIF de Unisys.

Integración directa con Windows. La API de Win32 tenía LoadBitmap, BitBlt y StretchBlt construidos alrededor de secciones DIB. Un desarrollador podía cargar un BMP en memoria y blitearlo a la pantalla en pocas líneas de C.

Disposición de memoria predecible. Como los píxeles de un BMP sin comprimir se mapean directamente a la memoria de pantalla, los motores de juegos y herramientas gráficas lo usaban como formato de intercambio de texturas en los años 90. Podías mapear el archivo en memoria y tratar el desplazamiento de píxeles como un búfer raw.

Donde BMP quedó rezagado

Las fortalezas de BMP eran también sus debilidades. El formato no evolucionó al ritmo del resto de la industria.

Sin compresión efectiva. Los BMP sin comprimir son enormes. Una imagen de 1920 × 1080 a 24 bits ocupa 5.93 MB. La misma imagen como JPEG calidad 90 ronda los 300–500 KB. A medida que la velocidad de internet y el costo del almacenamiento se convirtieron en restricciones, BMP dejó de ser viable.

La compresión RLE es débil. BMP admite codificación run-length RLE8 y RLE4, pero RLE solo ayuda en imágenes con grandes áreas uniformes. Las fotografías y los degradados se comprimen mal. Los BMP con RLE son raros en la práctica.

Sin transparencia real. El BMP estándar no tiene canal alpha. La variante de 32 bits incluye un byte alpha, pero muchas herramientas lo ignoran o lo tratan como reservado. Para gráficos web y sprites de juegos, esto hacía que BMP fuera inútil comparado con PNG.

Sin animación, sin metadatos, sin gestión de color. BMP almacena píxeles y poco más. Sin EXIF, sin soporte de perfil ICC en la cabecera original, sin fotogramas de animación. A medida que los flujos de trabajo se sofisticaron, BMP se quedó primitivo.

Almacenamiento de abajo hacia arriba. El orden de filas de abajo hacia arriba por defecto confunde a los decodificadores y desperdicia ciclos en conversión. Es un detalle que añade fricción sin ningún beneficio.

Los formatos que reemplazaron a BMP

Las limitaciones de BMP moldearon directamente lo que vino después.

PNG (1996) resolvió el problema de transparencia y compresión. Ofrecía compresión sin pérdida, alpha de 8 bits y una especificación más simple que TIFF. PNG reemplazó a BMP casi en todas partes en la web y en aplicaciones multiplataforma.

JPEG (1992) resolvió el problema de las fotografías. Su compresión con pérdida basada en DCT hacía las fotografías 10–20× más pequeñas que un BMP sin comprimir. Para cualquier imagen de tono continuo, JPEG se convirtió en el predeterminado.

WebP (2010) añadió modos con y sin pérdida, animación y alpha en un solo contenedor. Un WebP sin pérdida suele ser 20–30% más pequeño que PNG, que ya supera a BMP por un margen enorme.

HEIC/HEIF (2013) trajo compresión basada en HEVC a imágenes fijas. Logra tamaños más pequeños que JPEG con mejor calidad, soporta alpha y mapas de profundidad, y ahora es el predeterminado en dispositivos Apple. Cuando un iPhone guarda una foto, suele ser HEIC.

Cada uno de estos formatos existe porque BMP dejó de ser lo suficientemente bueno para un caso de uso concreto.

Dónde sigue apareciendo BMP

BMP no ha desaparecido. Simplemente ha sido relegado a nichos donde su simplicidad vale más que su ineficiencia.

Internos de Windows. La pantalla de arranque de Windows, diálogos heredados y algunos recursos del sistema aún usan BMP. La API GDI de Win32 espera datos DIB, y reescribir esas rutinas no vale el esfuerzo para Microsoft.

Sistemas embebidos y microcontroladores. Una pequeña LCD en un Arduino o STM32 no tiene la RAM ni la CPU para decodificar PNG. Un BMP de 16 bits sin comprimir puede copiarse directamente al framebuffer con casi ningún código.

Imagenología médica y científica. Algunos visores DICOM heredados y equipos de laboratorio exportan BMP porque todo sistema puede abrirlo. La simplicidad del formato reduce el riesgo de interoperabilidad, lo cual importa en entornos regulados.

Ingeniería inversa y educación. BMP sigue siendo uno de los mejores formatos para enseñar la estructura de archivos de imagen. Las cabeceras son pequeñas, la disposición de píxeles es obvia y puedes construir un decodificador funcional en una tarde.

Legado del desarrollo de juegos. Los motores de juegos antiguos y las herramientas de texturas usaban BMP como formato intermedio. Algunas comunidades de modding aún trabajan con recursos BMP porque las herramientas fueron construidas alrededor de él.

Detectar BMP leyendo la firma

No confíes en la extensión .bmp. Lee los primeros dos bytes.

TypeScript

async function isBmp(file: File): Promise<boolean> {
  const buffer = await file.slice(0, 2).arrayBuffer()
  const bytes = new Uint8Array(buffer)
  return bytes.length === 2 && bytes[0] === 0x42 && bytes[1] === 0x4d
}

Python

def is_bmp(path: str) -> bool:
    with open(path, "rb") as f:
        return f.read(2) == b"BM"

Go

func isBmp(path string) bool {
	f, err := os.Open(path)
	if err != nil {
		return false
	}
	defer f.Close()

	buf := make([]byte, 2)
	if _, err := f.Read(buf); err != nil {
		return false
	}
	return bytes.Equal(buf, []byte("BM"))
}

PHP

function isBmp(string $path): bool {
    $header = file_get_contents($path, false, null, 0, 2);
    return $header === "BM";
}

ImageMagick CLI

magick identify -verbose image.bmp | grep "Format:"
# Format: BMP (Microsoft Windows bitmap image)

O simplemente:

file image.bmp
# image.bmp: PC bitmap, Windows 3.x format, 1920 x 1080 x 24

El futuro de BMP

BMP es un formato acabado. La especificación central no ha cambiado de forma significativa desde la era de Windows 95. Eso es tanto una limitación como una garantía: un BMP escrito en 1995 todavía se abre correctamente hoy.

No ganará nuevas características. No tendrá mejor compresión, manejo adecuado de alpha ni soporte de animación. Nadie está invirtiendo en BMP porque nadie necesita un BMP mejor. PNG, WebP, AVIF y HEIC ya ganaron en todos los contextos donde la eficiencia importa.

Pero BMP perdurará en los ámbitos en los que ya está presente: internos de Windows, pantallas embebidas, equipos médicos heredados y aulas. No es elegante ni eficiente, pero resulta imposible de eliminar porque demasiados sistemas saben leerlo.

Si acabas heredando archivos BMP que necesitas usar en dispositivos actuales, lo más práctico es convertirlos. Para fotografías, convertir a JPEG o HEIC ahorra espacio. Para gráficos con transparencia, PNG o WebP son el objetivo correcto. Y cuando necesitas conectar con el ecosistema de Apple, convertir HEIC a algo universalmente legible es el primer paso.

Nuestro convertidor de HEIC a JPG funciona completamente en el navegador: el archivo nunca sale de tu dispositivo. Para obtener una salida sin pérdida con transparencia, usa HEIC a PNG. Si prefieres tamaños optimizados para la web, HEIC a WebP ofrece archivos más pequeños con amplio soporte en navegadores.

BMP le enseñó a la industria una lección valiosa: un formato no tiene que ser el mejor para estar en todas partes. Solo tiene que ser lo suficientemente simple para que todos lo implementen, y lo suficientemente arraigado para que nadie se atreva a eliminarlo.

Más publicaciones del blog para leer