Analyses Profondes

Le format BMP expliqué : le format d'image le plus simple de Windows

koboshiCo-founder
·13 min de lecture
Le format BMP expliqué : le format d'image le plus simple de Windows
Résumé

Présent dans Windows depuis 1990, BMP stocke des pixels bruts avec des en-têtes minimaux, sans compression ni canal alpha. Cet article parcourt le format, du BITMAPFILEHEADER de 14 octets aux contextes où on le croise encore, comme les systèmes embarqués et l'imagerie médicale.

Ouvrez un fichier BMP dans un éditeur hexadécimal. Les quatorze premiers octets ressemblent à ceci :

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

C'est l'intégralité du BITMAPFILEHEADER. 42 4D est la signature « BM » en ASCII. Les quatre octets suivants donnent la taille du fichier — 46 00 00 00 correspond en little-endian à 70. Les quatre octets suivants sont réservés et toujours à zéro. Les quatre derniers octets indiquent le décalage vers les données pixel — 36 00 00 00 vaut 54, donc le tableau de pixels commence à l'octet 54.

Aucun marqueur de compression, aucun profil colorimétrique, aucun canal alpha. Juste une signature, une taille et un décalage. BMP est exactement ce que son nom suggère : une carte de bits.

Qu'est-ce que BMP, concrètement

BMP signifie Bitmap, ou plus formellement Device Independent Bitmap (DIB). Microsoft l'a introduit avec Windows 3.0 en 1990 pour stocker des images matricielles sans les lier à un périphérique d'affichage précis. Avant DIB, Windows utilisait des Device Dependent Bitmaps (DDB) dont le format de pixel dépendait de la carte graphique installée. Un DDB enregistré sur une machine pouvait être illisible sur une autre.

BMP a résolu ce problème en stockant suffisamment de métadonnées pour que n'importe quel décodeur puisse reconstruire l'image : largeur, hauteur, profondeur de couleur, palette, type de compression et tableau de pixels brut. Le système d'exploitation lit l'en-tête, alloue un tampon et copie les pixels en mémoire. Pour les images 24 bits non compressées, les données pixel sont généralement des triplets RGB écrits de bas en haut, ligne par ligne, alignées sur une frontière de quatre octets.

Cette simplicité a fait de BMP le format d'image par défaut de Windows pendant plus d'une décennie. Paintbrush, le moteur de fond d'écran Windows, les premiers scanners et d'innombrables outils internes géraient tous le BMP nativement.

La structure du fichier

Un fichier BMP se compose de quatre parties disposées les unes après les autres :

BITMAPFILEHEADER   (14 bytes)
BITMAPINFOHEADER   (40 bytes for the classic version)
Color Table        (optional, for indexed color modes)
Pixel Data         (the actual image)

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 signature n'est pas toujours « BM ». Windows prend également en charge « BA », « CI », « CP », « IC » et « PT » pour les variantes curseur et icône, mais en pratique chaque BMP que vous ouvrirez commence par « BM ».

BITMAPINFOHEADER (40 bytes, BITMAPINFOHEADER type)

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)

Les versions ultérieures de Windows ont ajouté des en-têtes plus volumineux — 52, 56, 108 et 124 octets — pour prendre en charge les masques alpha, les espaces colorimétriques et les profils ICC. La version de 40 octets reste la plus courante.

La hauteur indique le sens de lecture

Si le champ de hauteur est positif, l'image est stockée de bas en haut. La ligne 0 dans le fichier correspond à la ligne du bas de l'image. Si le champ est négatif, l'image est stockée de haut en bas. C'est l'une des particularités de BMP — la plupart des autres formats stockent de haut en bas par défaut.

La table de couleurs

Pour les profondeurs de 1, 4 ou 8 bits, BMP utilise une palette indexée. Chaque entrée de palette fait quatre octets : bleu, vert, rouge et un octet alpha réservé qui est presque toujours ignoré. Un BMP à 256 couleurs dispose d'une table de couleurs de 1 024 octets immédiatement après l'en-tête. Les données pixel qui suivent ne sont pas des couleurs — ce sont des index dans cette table.

L'alignement des lignes de pixels

Chaque ligne de balayage doit être un multiple de quatre octets. Une image 24 bits de 5 pixels de large nécessite 15 octets par ligne, arrondis à 16. Ces octets de remplissage supplémentaires sont de l'espace gaspillé, une autre petite raison pour laquelle BMP est inefficace.

Ci-dessous, un exemple complet pour un BMP 24 bits non compressé 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)

Le paysage des formats en 1990

BMP n'est pas apparu dans le vide. En 1990, plusieurs formats d'image concurrençaient déjà :

FormatCompressionProfondeur de couleurTransparenceRisque de brevetUsage typique
GIFLZW256 couleurs max1 bitOui (LZW)Graphiques web
JPEGDCT + Huffman24 bitsAucuneQuasi nonPhotographies
TIFFMultiples optionnellesJusqu'à 48 bitsOuiOptionnelImpression, numérisation
PCXRLEJusqu'à 24 bitsAucuneNonJeux DOS, clip art
PICTRLEJusqu'à 32 bitsOuiNonMac OS classique
BMPAucune ou RLEJusqu'à 32 bitsAucuneNonFond d'écran Windows, icônes

GIF était déjà le format par défaut du web, mais son brevet LZW rendait l'usage commercial risqué. JPEG était conçu pour les photographies et supprimait des données de manière irréversible. TIFF était puissant mais surdimensionné — écrire un lecteur TIFF universel était un projet en soi. PCX disparaissait avec le DOS.

L'argument de BMP était la simplicité. Il n'était ni plus petit, ni plus rapide, ni plus capable que les autres. C'était simplement le format que Windows comprenait sans bibliothèque supplémentaire.

Pourquoi BMP a fonctionné

BMP avait de réels avantages dans son contexte :

Zéro complexité de décodage. Un BMP 24 bits non compressé peut être affiché en lisant un en-tête de taille fixe et en copiant les pixels directement dans un framebuffer. Pas de tables Huffman, pas de machine à états DEFLATE, pas de passes progressives. Cela en faisait un choix idéal pour les systèmes embarqués dotés d'un CPU limité.

Aucune contrainte de brevet. Contrairement au LZW de GIF, la compression BMP était soit absente, soit RLE, toutes deux libres de droits. Cela comptait pour les outils open source et les logiciels commerciaux qui voulaient éviter les licences GIF d'Unisys.

Intégration directe à Windows. L'API Win32 disposait de LoadBitmap, BitBlt et StretchBlt construits autour des sections DIB. Un développeur pouvait charger un BMP en mémoire et l'afficher à l'écran en quelques lignes de C.

Disposition mémoire prévisible. Parce que les pixels BMP non compressés correspondent directement à la mémoire d'écran, les moteurs de jeu et les outils graphiques utilisaient BMP comme format d'échange de textures dans les années 1990. Il suffisait de mapper le fichier en mémoire et de traiter le décalage pixel comme un tampon brut.

Les limites de BMP

Les forces de BMP étaient aussi ses faiblesses. Le format n'a pas évolué avec le reste de l'industrie.

Aucune compression efficace. Les BMP non compressés sont énormes. Une image 1920 × 1080 en 24 bits fait 5,93 Mo. La même image en JPEG qualité 90 fait environ 300–500 Ko. À mesure que les vitesses internet et les coûts de stockage devenaient des contraintes, BMP est devenu difficile à justifier.

La compression RLE est faible. BMP prend en charge RLE8 et RLE4, mais RLE n'aide que les images avec de grandes zones uniformes. Les photographies et les dégradés se compressent mal. Les BMP encodés RLE sont rares en pratique.

Aucune vraie transparence. Le BMP standard n'a pas de canal alpha. La variante 32 bits inclut un octet alpha, mais de nombreux outils l'ignorent ou le traitent comme réservé. Pour les graphiques web et les sprites de jeu, cela rendait BMP inutile comparé à PNG.

Pas d'animation, pas de métadonnées, pas de gestion colorimétrique. BMP stocke des pixels et peu d'autre chose. Pas d'EXIF, pas de support de profil ICC dans l'en-tête d'origine, pas d'images animées. À mesure que les workflows devenaient plus sophistiqués, BMP restait primitif.

Stockage de bas en haut. L'ordre de lignes par défaut de bas en haut embrouille les décodeurs et fait perdre des cycles de conversion. C'est un petit détail qui ajoute de la friction sans aucun bénéfice.

Les formats qui ont remplacé BMP

Les limites de BMP ont directement façonné ce qui est venu ensuite.

PNG (1996) a résolu le problème de transparence et de compression. Il offrait une compression sans perte, un alpha 8 bits et une spécification plus simple que TIFF. PNG a remplacé BMP presque partout sur le web et dans les applications multiplateformes.

JPEG (1992) a résolu le problème des photographies. Sa compression avec perte basée sur DCT rendait les photographies 10 à 20 fois plus petites qu'un BMP non compressé. Pour toute image en tons continus, JPEG est devenu le format par défaut.

WebP (2010) a ajouté modes avec et sans perte, animation et alpha dans un seul conteneur. Un WebP sans perte est typiquement 20 à 30 % plus petit que PNG, qui lui-même bat BMP par une large marge.

HEIC/HEIF (2013) a apporté la compression basée sur HEVC aux images fixes. Il obtient des tailles de fichier plus petites que JPEG avec une meilleure qualité, prend en charge l'alpha et les cartes de profondeur, et est désormais le format par défaut sur les appareils Apple. Quand un iPhone enregistre une photo, c'est généralement en HEIC.

Chacun de ces formats existe parce que BMP a cessé d'être assez bon pour un cas d'usage spécifique.

Où BMP est encore utilisé

BMP n'est pas mort. Il a simplement été relégué à des niches où sa simplicité vaut plus que son inefficacité.

Internes de Windows. L'écran de démarrage Windows, les boîtes de dialogue héritées et certaines ressources système utilisent encore BMP. L'API Win32 GDI attend des données DIB, et réécrire ces chemins de code ne vaut pas le temps de Microsoft.

Systèmes embarqués et microcontrôleurs. Un petit écran LCD sur un Arduino ou un STM32 n'a pas la RAM ni le CPU pour décoder du PNG. Un BMP 16 bits non compressé peut être copié directement dans le framebuffer avec presque aucun code.

Imagerie médicale et scientifique. Certains visualiseurs DICOM legacy et équipements de laboratoire exportent en BMP parce que chaque système peut l'ouvrir. La simplicité du format réduit le risque d'interopérabilité, ce qui compte dans des environnements réglementés.

Rétro-ingénierie et éducation. BMP reste l'un des meilleurs formats pour enseigner la structure des fichiers image. Les en-têtes sont petits, la disposition des pixels est évidente, et on peut construire un décodeur fonctionnel en une après-midi.

Héritage du développement de jeux. Les anciens moteurs de jeu et outils de textures utilisaient BMP comme format intermédiaire. Certaines communautés de modding travaillent encore avec des ressources BMP parce que les outils ont été construits autour.

Détecter BMP en lisant la signature

Ne faites pas confiance à l'extension .bmp. Lisez les deux premiers octets.

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)

Ou simplement :

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

L'avenir de BMP

BMP est un format figé. La spécification de base n'a pas changé de manière significative depuis l'ère de Windows 95. C'est à la fois une limitation et une garantie : un BMP écrit en 1995 s'ouvre encore correctement aujourd'hui.

Le format ne gagnera pas de nouvelles fonctionnalités. Il n'aura pas de meilleure compression, de gestion alpha correcte ni de support d'animation. Personne n'investit dans BMP parce que personne n'a besoin d'un meilleur BMP. PNG, WebP, AVIF et HEIC ont déjà remporté chaque contexte où l'efficacité compte.

Mais BMP continue d'exister là où il est déjà ancré : les internes de Windows, les écrans embarqués, l'équipement médical legacy et les salles de classe. Il n'est ni glamour ni efficace, mais il est impossible à supprimer parce que trop de systèmes savent le lire.

Si vous héritez de fichiers BMP legacy qui doivent fonctionner sur des appareils modernes, la conversion est la solution la plus pratique. Pour les photographies, convertir en JPEG ou HEIC fait gagner de l'espace. Pour les graphiques avec transparence, PNG ou WebP sont les bonnes cibles. Et quand vous devez faire le pont avec l'écosystème Apple, convertir du HEIC vers quelque chose de universellement lisible est la première étape.

Notre convertisseur HEIC vers JPG fonctionne entièrement dans le navigateur — le fichier ne quitte jamais votre appareil. Pour une sortie sans perte avec transparence, utilisez HEIC vers PNG. Pour des tailles optimisées pour le web, HEIC vers WebP vous donne des fichiers plus petits avec un support navigateur large.

BMP a enseigné à l'industrie une leçon précieuse : un format n'a pas besoin d'être le meilleur pour être partout. Il suffit qu'il soit assez simple pour que tout le monde l'implémente, et assez ancré pour que personne n'ose le retirer.

Plus d'articles à lire