BMP

(от ) — формат хранения растровых изображений, разработанный компанией Microsoft.
Файлы формата BMP могут иметь расширения .bmp, .dib и .rle.

С форматом BMP работает огромное количество программ, так как его поддержка интегрирована в операционные системы Windows и OS/2. Кроме того, данные этого формата включаются в двоичные файлы ресурсов RES и в PE-файлы.

В данном формате можно хранить только однослойные растры. На каждый пиксель в разных файлах может приходиться разное количество бит (глубина цвета). Microsoft предлагает битности 1, 2, 4, 8, 16, 24, 32, 48 и 64. В битностях 8 и ниже цвет указывается индексом из таблицы цветов (палитры), а при бо́льших — непосредственным значением. Цвет же в любом случае можно задать только в цветовой модели RGB (как при непосредственном указании в пикселе, так и в таблице цветов), но в битностях 16 и 32 можно получить Grayscale с глубиной до 16 и 32 бит, соответственно. Частичная прозрачность реализована альфа-каналом битностей от 16 бит и выше.

В большинстве случаев пиксели хранятся в виде относительно простого двумерного массива. Для битностей 4 и 8 доступно сжатие алгоритмом RLE, которое может уменьшить их размер. Формат BMP также поддерживает встраивание данных в форматах JPEG и PNG. Но последнее скорее больше предназначено не для компактного хранения, а для обхода ограничений архитектуры GDI, которая не предусматривает прямую работу с изображениями отличных от BMP форматов.

В последних версиях формата BMP также появились возможности по управлению цветом. В частности, можно указывать конечные точки, производить гамма-коррекцию и встраивать цветовые профили ICC.

DIB и DDB 
При использовании формата DIB (, аппаратно-независимый растр) программист может получить доступ ко всем элементам структур, описывающих изображение, при помощи обычного указателя.
Но эти данные не используются для непосредственного управления экраном, так как они всегда хранятся в системной памяти, а не в специализированной видеопамяти.
Формат пикселя в оперативной памяти может отличаться от того формата, который должен заноситься в видеопамять для индикации точки такого же цвета.
Например, в DIB-формате может использоваться 24 бита для задания пикселя, а графический адаптер в этот момент может работать в режиме HiColor с цветовой глубиной 16 бит.
При этом ярко-красная точка в аппаратно-независимом формате будет задаваться тремя байтами 0000FF16, а в видеопамяти — словом F80016.
При копировании картинки на экран система будет тратить дополнительное время на преобразование кодов цвета из 24-битного формата в формат видеобуфера.

Формат DDB (, аппаратно-зависимый растр) всегда содержит цветовые коды, совпадающие с кодами видеобуфера, но храниться он может как в системной, так и в видеопамяти.
В обоих случаях он содержит только коды цвета в том формате, который обеспечит пересылку изображения из ОЗУ в видеопамять при помощи простого копирования.

Внутреннее строение 

Официальную информацию по формату BMP можно найти в MSDN или справке Microsoft Windows SDK (может идти в комплекте с некоторыми IDE).
В файле WinGDI.h от компании Microsoft есть все объявления на языке C++, которые касаются данного формата.
В данную статью же не были включены объявления типов, так как от этого она может быть слишком громоздкой.
К тому же официальные объявления некоторые разработчики могут посчитать неудобными и поэтому их востребованность сомнительна.
Если вам потребуются оригинальные имена констант, структур, типов и их полей, то они все есть в тексте данной статьи.

Максимальный размер неделимых ячеек (исключая поля битовых структур): 32 бита и поэтому формат можно классифицировать как 32-битный.
Исключением могут быть 64-битные пиксели, но значения их каналов можно обрабатывать и 16-битными словами.
Порядок байт в 16-битных и 32-битных ячейках повсюду от младшего к старшему (little-endian).
Целые числа записываются в прямом коде, со знаком — в дополнительном.
Если сравнивать с аппаратными архитектурами, то порядок байт и формат чисел соответствует x86.

В данной статье для указания типов используются имена типов WinAPI как в документации Microsoft.
Кроме специфических (описаны отдельно в тексте статьи) можно встретить четыре числовых типа:
 BYTE — 8-битное беззнаковое целое.
 WORD — 16-битное беззнаковое целое.
 DWORD — 32-битное беззнаковое целое.
 LONG — 32-битное целое со знаком.

В формате Windows Bitmap под структурами понимается блок с идущими подряд ячейками различного фиксированного размера, у которых есть условные имена (есть во многих языках программирования), а не что-то сложнее (например, поток команд произвольного размера).

У некоторых элементов формата указана версия Windows, начиная с которой он поддерживается.
Речь идёт в первую очередь об основных библиотеках WinAPI таких как gdi32.dll, shell32.dll, user32.dll и kernel32.dll.
Другие компоненты операционной системы (например, GDI+, .NET, DirectX) могут иметь другие более широкие возможности.

Общая структура 
Данные в формате BMP состоят из трёх основных блоков различного размера:

 Заголовок из структуры BITMAPFILEHEADER и блока BITMAPINFO. Последний содержит:
 Информационные поля.
 Битовые маски для извлечения значений цветовых каналов (опциональные).
 Таблица цветов (опциональная).
 Цветовой профиль (опциональный).
 Пиксельные данные.

При хранении в файле все заголовки идут с самого первого байта.
Пиксельные данные могут находиться на произвольной позиции в файле (она указывается в поле OffBits структуры BITMAPFILEHEADER), в том числе и в удалении от заголовков.
Опциональный цветовой профиль появился в версии 5 и он также может свободно располагаться, но его позиция указывается от начала BITMAPINFO (в поле ProfileData).

В оперативной памяти (например, при взаимодействии с WinAPI-функциями GDI) из заголовков исключается структура BITMAPFILEHEADER.
При этом Microsoft рекомендует располагать цветовой профиль сразу за заголовками в едином блоке.
Пиксельные данные могут иметь произвольное расположение в памяти и их адрес указывается в параметрах процедур.
В любом случае рекомендуется в памяти все блоки содержать по адресам кратным четырём: в заголовках присутствуют 32-битные ячейки, а к пиксельным данным такое требование указано в документации.
Это требование справедливо только для оперативной памяти: при хранении в файле его придерживаться не обязательно.

BITMAPFILEHEADER 
BITMAPFILEHEADER — 14-байтная структура, которая располагается в самом начале файла.
Обратите внимание на то, что с самого начала структуры сбивается выравнивание ячеек.
Если для вас оно важно, то в оперативной памяти данный заголовок располагайте по чётным адресам, которые не кратны четырём (тогда 32-битные ячейки попадут на выравненные позиции).

Сигнатура формата при просмотре содержимого файла текстом в двоичном режиме выглядит как пара ASCII-символов «BM».

BITMAPINFO 
BITMAPINFO в файле идёт сразу за BITMAPFILEHEADER.
Адрес этого блока в памяти напрямую также передаётся некоторым функциям WinAPI (например, SetDIBitsToDevice или CreateDIBitmap).
Кроме этого, этот же блок используется в форматах значков и курсоров Windows, но в данной статье этот момент не рассматривается (см. отдельные описания этих форматов).
Данная структура является основной и описательной в формате BMP и поэтому когда просто упомянуто имя поля, то речь идёт о поле в данной структуре.

Блок BITMAPINFO состоит из трёх частей:
 Структура с информационными полями.
 Битовые маски для извлечения значений цветовых каналов (присутствуют не всегда).
 Таблица цветов (присутствует не всегда).

Про битовые маски и таблицу цветов смотрите ниже в отдельных разделах.
Здесь далее пойдёт описание структуры с информационными полями.

В момент написания данной статьи структура с информационными полями имела четыре версии: CORE, 3, 4 и 5 (обозначения версий приведены условные в рамках данной статьи для краткости).
Для каждой версии Microsoft объявила четыре отдельные структуры с разными именами полей.
В данной статье при упоминании поля, которое присутствует в нескольких структурах, берётся общая для всех структур часть в конце имени (например, BitCount вместо bcBitCount, biBitCount, bV4BitCount или bV5BitCount).
Версию структуры можно определить по первой 32-битной ячейке (WinAPI-тип DWORD), которая содержит её размер в байтах (беззнаковым целым).
Версия CORE отличается от всех своей компактностью и использованием исключительно 16-битных беззнаковых полей.
Остальные три содержат идентичные ячейки, к которым в каждой новой версии добавлялись новые.

Ниже представлена обзорная таблица по информационным структурам:

Из-за идентичности полей в версиях 3, 4 и 5 может показаться, что полем Size можно регулировать количество полей, убирая неиспользуемые.
В действительности это не корректно, так как здесь размер играет роль версии (в версии CORE хоть и тоже идентичные поля, но другого размера и типа).
Никто не гарантирует, что вам не могут попасться заголовки меньших или больших размеров с другим набором полей.
Тем не менее, Adobe Photoshop может при сохранении файлов BMP записывать структуры информационных полей с размерами 52 и 56 байт.
По сути это урезанная 4-я версия, которая содержат только битовые маски каналов (56 байт — версия с альфа-каналом).

16-битные информационные поля (версия CORE) 
Обратите внимание на то, что здесь поля ширины и высоты содержат беззнаковые целые, в то время как 32-битные структуры хранят значения со знаком.

32-битные информационные поля (версии 3, 4 и 5) 
В таблице ниже поля представлены обзорно.
Подробную информацию вы можете найти в разделах далее.

Битность изображения (поле BitCount) 
Поле BitCount содержит количество бит, которое приходится на каждый пиксель.
Если там указано отличное от нуля значение, то это и есть реальная битность.
Нулевое же содержимое поля BitCount указывается если пиксели хранятся в формате JPEG или PNG.
Тогда действительная битность будет определяться уже этими форматами.
Битности чисто BMP формата представлены в таблице ниже:

Примечания к таблице:
1. В колонке «BITMAPINFO» указана поддержка битностей только со стороны Microsoft.
2. Windows CE 1.0 и 1.01 поддерживает только битности 1 и 2.
3. GDI+ версии 1.0 16-битные цветовые каналы умеет только считывать, сразу переводя их в 8-битные.

В битностях 8 и ниже цвет пикселя указывается индексом в таблице цветов, в высших: непосредственным значением в цветовой модели RGB.
Альфа-канал опционально может быть добавлен в битностях 16 и 32.
В битности 64 он присутствует перманентно.

В таблице представлены только битности, которые документировала корпорация Microsoft.
Сам формат не содержит никаких принципиальных ограничений на использование каких-либо не упомянутых здесь битностей.

1-битные BMP-файлы с чисто чёрным (сброшенный бит) и белым (установленный бит) цветами называют монохромными.
Такие файлы обычно используются в качестве масок для других растров.
Возможно вам постоянно попадались на глаза именно такие 1-битные растры.
В действительности формат Windows Bitmap не накладывает никаких ограничений на то, какие цвета будут использоваться для каждого из значений бит.

Вы можете также встретить следующие названия битностей: CGA для двух бит, EGA для четырёх, HiColor (HighColor) для 16 бит, TrueColor для 24 и 32 бит с полупрозрачностью, DeepColor для больших битностей и возможно другие.
Эти названия появились в период развития цветных растровых дисплеев и относятся больше к их глубине цвета.
К моменту написания данной статьи (2014 год) такие названия уже давно не используются из-за сильного распространения 24-битных устройств (вместо этого просто указывается глубина цвета в битах или их количество).
А BMP-файлы в меньшей битности сохраняются в большей степени не для отображения на CGA или EGA-устройствах, а для компактности по сравнению с 24-битными и 32-битными форматами если используется малое количество цветов.

Поле Compression 
Для каждой группы битностей используются отдельные ограниченные значения Compression, но в совокупности их значения уникальны.
Microsoft документировала следующие значения (в таблице указаны имена констант от этой корпорации):

Таблица цветов 
Таблица цветов является частью блока BITMAPINFO и может использоваться в двух случаях:
 Она обязательно присутствует при битностях 8 и ниже, в которых цвет пикселей задаётся индексом ячейки из неё.
 При битностях 8 и выше, в которых цвет указывается непосредственным значением, таблица присутствует если используется заголовок не CORE-версии, у которого поле ClrUsed содержит ненулевое значение. Здесь она задействуется уже для оптимизации цветов при работе с использующими палитры устройствами (как именно производится оптимизация в документации не сказано).

Позиция таблицы цветов указывается от его начала блока BITMAPINFO.
По умолчанию она идёт сразу за информационной структурой (её беззнаковый размер в байтах можно прочитать из первого 32-битного поля).
Но между структурой с полями и цветовой таблицей могут идти четырёхбайтные битовые маски для извлечения цветовых каналов (касается только битностей 16 и 32).
Они там находятся только если используется информационная структура 3-й версии (Size = 40) и поле Compression содержит 3 (BI_BITFIELDS) или 6 (BI_ALPHABITFIELDS).
Тогда к размеру информационных полей нужно прибавить 12 (при значении BI_BITFIELDS) или 16 байт (если указано BI_ALPHABITFIELDS).
Получается 6 вариантов расположения таблицы:

Количество ячеек в таблице определяется по полям BitCount и ClrUsed.
При битностях 8 и ниже максимальное количество ячеек в таблице принимается за 2битность: 2 в однобитном растре, 4 в двухбитном, 16 в 4-битном и 256 в 8-битном.
В данных битностях таблица всегда содержит это максимальное количество ячеек если используется заголовок версии CORE (Size = 12) или если в других версиях поле ClrUsed содержит 0.
Во всех остальных случаях, независимо от битности, в таблице находится столько же ячеек, сколько указано в поле ClrUsed.

Сама же таблица представляет собой одномерный массив, который может содержать ячейки трёх типов:
 32-битная структура RGBQUAD. Применяется если в BITMAPINFO использована информационная структура версии 3, 4 или 5. В самой же структуре RGBQUAD указывается цвет в модели RGB в четырёх байтовых ячейках (все имеют WinAPI-тип BYTE): rgbBlue (синий), rgbGreen (зелёный), rgbRed (красный) и rgbReserved (зарезервирована и должна быть обнулена).
 24-битная структура RGBTRIPLE. Применяется если BITMAPINFO начинается со структуры BITMAPCOREHEADER. RGBTRIPLE состоит из трёх байтовых ячеек (WinAPI-тип BYTE), в которых указывается цвет в модели RGB: rgbtBlue (синий), rgbtGreen (зелёный) и rgbtRed (красный).
 16-битные индексы цветов (беззнаковые целые числа) в текущей логической палитре контекста устройства (системные объекты Windows GDI). Этот вид доступен только во время выполнения приложения. Формат BMP не поддерживает явное указание, что используется такая таблица и поэтому приложение само извещает WinAPI-функции об этом в специальных параметрах (как правило константой DIB_PAL_COLORS).

Во всей таблице могут быть задействованы не все ячейки и в поле ClrImportant помещается количество ячеек от начала таблицы до последней используемой (включая её саму).
Содержимое 0 поля ClrImportant указывает на то, что используется вся таблица.
Задействованные ячейки лучше размещать в самом начале таблицы и рекомендуется при этом отсортировать их по убыванию степени важности (на случай если придётся уменьшить их количество).

Маски для извлечения значений цветовых каналов 
Если битность изображения 16 или 32, то могут быть указаны 32-битные маски для извлечения цветовых каналов.
Это связано с тем, что 16 не кратно трём и поэтому биты могут быть распределены разными способами.
В 32-битных изображениях из-за удобства используют 8-битные каналы и поэтому поддержка для них может показаться избыточной.
В действительности здесь маска даёт возможность включить/отключить альфа-канал или установить удобный вам порядок следования компонент, а не только регулировать их разрешение.
При применении масок ячейка пикселя считывается целиком как соответствующее машинное слово в little-endian.

Наличие битовых масок зависит от версии информационных полей структуры BITMAPINFO и поля Compression в ней.
Для версии CORE произвольные маски указать нельзя, так как там отсутствует поле Compression и отдельные поля масок.
В остальных версиях цветовые маски задействуются если Compression содержит 3 (BI_BITFIELDS).
Маска альфа-канала используется всегда в версиях 4 и 5.
Так как Windows CE не поддерживает эти две версии, в которых для неё есть специальное поле, для третьей версии было введено значение 6 (BI_ALPHABITFIELDS) поля Compression, которое добавляет сразу цветовые маски и маску альфа-канала (поддерживается начиная с Windows CE .NET 4.0).

Положение битовых масок фиксировано независимо от версии заголовка: 36h во всём файле или 28h от начала блока BITMAPINFO.
В версиях 4 и 5 на этом месте располагаются предназначенные специально для них поля.
В версии же 3 битовые маски должны располагаться сразу за информационными полями и таким образом они точно попадают на позиции соответствующих полей в старших версиях.
Обратите внимание на то, что в третьей версии при наличии масок сдвигается таблица цветов на 12 или 16 байт вперёд, располагаясь сразу за ними.
4-байтные маски цветов следуют в порядке красная, зелёная, синяя.
Маска альфа-канала располагается уже за ними.

В документации Microsoft к битовым маскам применяется только одно обязательное требование: каждая маска должна быть непрерывной.
Про случай пересечения масок там сказано, что желательно этого не делать.
Microsoft также говорит о том, что не обязательно задействовать все биты пикселя.
Какие-либо требования к содержимому неиспользуемых бит отсутствуют.

Обратите внимание на то, что никто не гарантирует, что могут быть использованы маски шире 8 бит.
И ничего не сказано про случай, когда у какого-либо канала будет нулевая маска (например, когда он действительно не используется).
Здесь возможна ситуация когда нулевые маски будут у всех компонентов и останется один альфа-канал (который при этом может занять все биты).
Нулевую маску цветового канала можно трактовать двумя способами: его значение принимается за ноль или же при прорисовке пиксели этого канала не затрагиваются.
Если взять первый вариант интерпретации с единственным альфа-каналом, то альфа-канал по сути будет задавать степень зачернения пикселя.
Кроме неопределённых вариантов есть также и интересный.
Так как пересечения не запрещены, то можно все каналы выставить на одну позицию и тем самым получить Grayscale.

Некоторое ПО имеет ограниченный набор поддерживаемых битовых масок.
В таблице ниже приведены доступные варианты в таких ограниченных средах:

Примечания к таблице:
(a) Эти наборы используются по умолчанию в битностях 16 и 32, если маски для извлечения цветов не заданы.
(b) Данный набор масок по своей сути реализует 16-битный Grayscale.

Пиксельные данные 
В файле положение пиксельных данных можно узнать из поля OffBits структуры BITMAPFILEHEADER.
Во время выполнения приложение хранит адрес пиксельных данных там, где удобней.
В документации Microsoft также упоминаются так называемые упакованные (англ. packed) битмапы, которые указываются одним адресом блока BITMAPINFO.
У таких битмапов пиксельные данные следуют сразу за заголовком (включая помимо информационных полей битовые маски и таблицу цветов).

Размер пиксельных данных в байтах записывается в поле SizeImage структуры BITMAPINFO.
Туда записываются именно «сырой» размер того непрерывного блока, который содержит данные для формирования пикселей (независимо от формата), а не какой-нибудь распакованный.
По умолчанию это поле обязательно должно содержать актуальное значение, так как по нему можно точно узнать сколько именно байт нужно считать из файла для получения пикселей.
Тем не менее, допустимо содержать в этом поле ноль при хранении пикселей двумерными массивами (когда поле Compression содержит значение 0 (BI_RGB), 3 (BI_BITFIELDS) или 6 (BI_ALPHABITFIELDS)).
Тогда размер пикселей при необходимости можно относительно быстро рассчитать исходя из битности, ширины и высоты растра.

В формате Windows Bitmap доступно три способа хранения пикселей (см. также раздел «Поле Compression» данной статьи):
 Двумерный массив.
 RLE (только для битностей 4 и 8).
 В форматах JPEG или PNG.

В подразделах далее отдельно описан каждый из них.

Указание цвета и значения альфа-канала 
Для указания цвета при хранении в формате BMP независимо от способа задания используются только беззнаковые целые числа.
Сам же цвет пикселя может задаваться двумя способами:
 Индексом в таблице цветов (при битностях 8 и ниже).
 Непосредственным значением в цветовой модели RGB (при битностях выше 8).
Второй целесообразно использовать когда набор цветов довольно большой или непредсказуем (например, во время обработки изображения).
Первый же способ обеспечивает как компактную компоновку при малом наборе цветов, так и некоторое удобство в управлении используемыми цветами (достаточно изменить значение цвета в палитре).
В самой таблице цветов указываются или 16-битные беззнаковые индексы в системной палитре (см. раздел «Таблица цветов» в данной статье), или же в RGB как в пикселе, но исключительно 8-битными значениями каналов.

Индекс в таблице цветов — это номер ячейки в ней от начала таблицы (используется непрерывная нумерация начиная с нуля).
Для каждой битности максимальный индекс принципиально ограничен значением 2битность − 1.
В действительности же он ограничен ещё и количеством элементов в таблице (подробности в разделе «Таблица цветов» данной статьи).
Microsoft не документировала поведение в случае когда указывается индекс за пределами таблицы, но GDI в этом случае берёт чёрный цвет.

В битностях выше 8 цвет пикселя указывается непосредственно в цветовой модели RGB: отдельно указывается уровень красного цвета, зелёного и синего.
Нулевое значение любого из каналов означает полное отсутствие соответствующего оттенка, а максимальное: полное его присутствие.
Разрешение же значений каналов переменное и в каждой битности оно своё (конкретные значения смотрите в разделе про хранение пикселей в двумерном массиве этой статьи).
При этом в битностях 16 и 32 может быть задано не только произвольное разрешение, но и индивидуальное для каждого канала (например, 5 бит для красной и синей, но 6 бит для зелёной).
Несмотря на большое количество вариантов задания разрешения значений, в документации Microsoft не сказано как производить изменение разрешения значения.
Из-за этого у разных производителей программного обеспечения могут получаться различные результаты при смене битности.

При непосредственном задании цвета пикселя кроме значений RGB формат Windows Bitmap опционально позволяет ещё задать значения альфа-канала.
В плане битности и кодировании значений он идентичен цветовым каналам: у него произвольная битность и используются беззнаковые целые.
Что же касается сопоставления значений, то ноль соответствует полной прозрачности, а максимальное доступное число — полной заполненности.

Двумерный массив 
В двумерном массиве можно хранить пиксели любой битности.
При таком способе хранения поле Compression содержит значение 0 (BI_RGB), 3 (BI_BITFIELDS) или 6 (BI_ALPHABITFIELDS).
Если используется заголовок версии CORE, то пиксели в любом случае хранятся только двумерным массивом.

В данной компоновке пиксели растра записываются однопиксельными горизонтальными полосками, которые Microsoft в своей документации часто называет «scans» (в русском языке наиболее близкое слово: строки).
В памяти эти ряды записываются по-порядку, но при положительном Height: начиная с самого нижнего (), а при отрицательном: с самого верхнего ().
Внутри каждого горизонтального ряда пиксели записываются строго только от левого к правому.
Пиксели меньше 8 бит размещаются в байтах, заполняя биты от старших к младшим, в результате чего шестнадцатиричные/двоичные числовые значения пикселей более похожи на выводимое изображение.
Если битность 16 или 32, то обработка осуществляется цельными машинными словами аналогичного размера с порядком бит от младшего к старшему (little-endian).
Ряды, независимо от размера ячеек, обязательно должны дополняться нулями до кратного четырём байтам размера.
Из-за этого, при некратной ширине изображения, в конце рядов могут оказываться неиспользуемые биты или целые байты.
Но благодаря гарантированной кратности размера ряда, обработку можно производить 8-, 16- или 32-битными машинными словами, по выбору.
И у Microsoft ещё прослеживается следующая тенденция в битностях больше 8: компонент Blue (синий цвет) размещается в младших битах/первых байтах, Green (зелёный) в последующих, а Red (красный) старше/дальше всех, и если есть альфа-канал, то он находится в самых старших битах/последних байтах.

Диаграмма ниже отображает расположение пикселей в битностях меньше 8:

В битностях 16 и 32 пиксели обрабатываются машинными словами аналогичного размера (предполагается порядок байт little-endian), которым применяются битовые маски каналов.
Если индивидуальные битовые маски не заданы, то структура будет следующая.
При 16 бит на каждый канал отводится по 5 бит.
Синий располагается в младших битах (маска 001F16), зелёный на позиции 5 (маска 03E016), красный: начиная с 10-го бита (маска 7C0016), а старший оставшийся бит 15 не используется.
Если используется битность 32, то по умолчанию на каждый канал отводится уже по байту (8 бит).
Компоненты располагаются аналогично: синий в младших битах (маска 0000:00FF16), зелёный начиная с бита 8 (маска 0000:FF0016), красный начинается с бита 16 (маска 00FF:000016), а старший байт не используется (он используется в качестве альфа-канала только если прямо это показать).
Так как предполагается чтение в порядке байта little-endian, то если читать значения из памяти по-байтово, они будут располагать в таком же порядке (синий будет идти первым).

При битности 24 на каждый канал приходится по байту, а в битностях 48 и 64: по 16-битному машинному слову.
Во всех трёх случаях в памяти цветовые компоненты идут в порядке: синий, зелёный, красный.
В 64-битных BMP за цветами дополнительно следует 16-битный альфа-канал.
Если захотите 64-битный пиксель обработать цельным машинным словом, то в little-endian синий окажется в младших 16 битах, а альфа-канал: в старших.
Зелёный, соответственно, будет рядом к красным, а синий — рядом с альфа.
И можно заметить что в 24 битах формат пикселя соответствует структуре RGBTRIPLE из таблицы цветов.

RLE 
Применение RLE компанией Microsoft документировано только для битностей 4 и 8.
При её использовании в BITMAPINFO поле Compression должно содержать 2 (BI_RLE4) при битности 4 или 1 (BI_RLE8) с восьмибитными пикселями.
Высота растра при этом должна быть указана положительным числом.

В формате Windows Bitmap RLE-кодирование можно сравнить с прорисовкой простыми командами.
Прорисовка начинается с левого нижнего пикселя (будьте внимательней: в растрах в целом привычней может быть верхний левый) и осуществляется вправо и вверх.
Пиксели за пределами размера растра не прорисовываются (об этом в документации не сказано, но GDI проявляет такое поведение).
Инструкции RLE позволяют прерывать прорисовку горизонтали, всего изображения, а также перемещать курсор прорисовки на другую позицию.
В результате некоторые пиксели могут оказаться не зарисованными.
Документация явно не предусматривает цвета для незарисованных пикселей, в результате чего трактовка может варьироваться: пропущенные пиксели либо остаются прозрачными, либо приобретают цвет с индексом 0.
Если делать первое допущение, то можно говорить о том, что 4- и 8-битные режимы благодаря RLE косвенно поддерживают прозрачность, но такое поведение не гарантировано.

Формирование изображения при RLE-кодировании осуществляется командами.
Каждая команда обязательно должна начинаться с чётного адреса (выравнена на 16-битную границу).
Существует пять команд, которые определяются парой байт:

Когда достигается правый край горизонтали, то на следующую перевод не производится.
Поэтому нужно специально вставлять команду окончания ряда.
И как видно из таблицы, набор команд не позволяют двигаться вниз или вернуться назад в горизонтали.
Поэтому можно прекращать прорисовку если будет достигнут верхний край.

Встраивание данных в форматах JPEG и PNG 
Начиная с версий Windows 98/ME и 2000/XP системные функции позволяют хранить пиксели в форматах JPEG и PNG.
Про степень поддержки этих двух форматов системой ничего не известно.

Для встраивания JPEG или PNG нужно в BITMAPINFO обнулить поле BitCount, а в Compression указать значение 4 (BI_JPEG) или 5 (PI_PNG).
Значение поля SizeImage в данном случае будет равно размеру JPEG или PNG-файла, который встраивается на место пиксельных данных как есть.
Ширина же с высотой в заголовке указываются уже для раскодированного изображения.
Про знак поля Height именно для этого случая в документации напрямую ничего не сказано, но судя по всему нужно записывать отрицательное значение.

Разрешение изображения 
Для сопоставления безразмерных пикселей с материальными размерами используются поля XPelsPerMeter и YPelsPerMeter.
В этих полях целым числом указывается сколько в данном изображении пикселей приходится на один линейный метр, отдельно по горизонтали (XPelsPerMeter) и вертикали (YPelsPerMeter).
Microsoft объявила эти два поля числовым типом со знаком, но в документации ничего не сказано про отрицательные значения.
Про значение ноль также ничего не сказано, но логичней его принимать за неопределённое разрешение, когда оно неизвестно или не имеет значения.

Разрешение часто указывается с привязкой не к метрическим размерностям, а в точках на дюйм (DPI/PPI).
Для перевода туда и обратно дюйм принимается равным 25,4 мм (английский дюйм).
Математические формулы для перевода пиксели/дюйм (PPI) в пиксели/метр (PPM) и наоборот:

 

 

Если интересует точный целочисленный перевод то выходят следующие выражения:

 PPM = (PPI * 5000 + 64) / 127

 PPI = (PPM * 127 + 2500) / 5000

После них округление будет произведено к ближайшему целому.
Если хотите округление вниз, то не прибавляйте половину делителя.
Если хотите вверх, то прибавляйте уменьшенный на единицу делитель.

Ниже представлены заранее вычисленные значения PPM для некоторых PPI/DPI:

 96 ppi ≈ 3780 ppm (для мониторов у Microsoft)
 72 ppi ≈ 2835 ppm (Apple для мониторов)
 150 dpi ≈ 5906 ppm
 300 dpi ≈ 11811 ppm
 600 dpi ≈ 23622 ppm

Цветовое пространство 
В информационных полях основным полем задающим цветовое пространство является поле CSType.
Допустимые его значения приведены в таблице ниже:

Microsoft объявила значения констант не числовыми значениями, а текстовыми из четырёх символов.
В данном случае коды символов формируют байты 32-битного значения (ASCII-код самого правого символа является младшим байтом, код самого левого — старшим).
При просмотре двоичного содержимого файла в виде текста такие значения в кодировке ASCII будут отображаться задом-наперёд (например, «KNIL», а не «LINK»).

Конечные точки и значение гаммы 
Формат Windows Bitmap позволяет производить цветокоррекцию указанием конечных точек для красного, зелёного и синего цветов, а также значений гаммы.
Для этого поле CSType должно содержать значение 0 (LCS_CALIBRATED_RGB).
Корректирующие же значения записываются в поля Endpoints, GammaRed, GammaGreen и GammaBlue (при других значениях CSType эти четыре поля игнорируются).

36-байтное поле EndPoints является структурой CIEXYZTRIPLE, которая состоит из трёх полей ciexyzRed (конечная точка красного), ciexyzGreen (точка зелёного) и ciexyzBlue (синяя).
Эти три поля в свою очередь также являются структурами CIEXYZ с тремя полями ciexyzX, ciexyzY и ciexyzZ типа FXPT2DOT30.
PXPT2DOT30 — это 32-битное беззнаковое число с фиксированной запятой, у которого 2 старших бита отводятся под целую часть, а 30 младших — под дробную.

Значение гаммы записывается в соответствующие поля для каждого цветового канала отдельно: GammaRed (красный), GammaGreen (зелёный) и GammaBlue (синий).
В объявлении информационных структур Microsoft указала у данных полей тип DWORD.
В это же время в файле WinGDI.h есть более подходящее объявление типа FXPT16DOT16 (на основе типа long), который представляет собой 32-битное беззнаковое число с дробной частью в младших 16 битах и целой — в 16 старших.
Следует отметить, что в MSDN на страницах про структуры BITMAPV4HEADER и BITMAPV5HEADER только это и сказано.
В статье же про структуру LOGCOLORSPACE сказано, что у неё в аналогичных полях должны быть обнулены старший и младший байт (по сути вместо формата 16.16 используется формат 8.8, который располагается в середине 32-битной ячейки).

Ниже приведены значения указанных выше четырёх полей в соответствии с цветовым пространством sRGB:

Цветовой профиль 
В файле BMP при необходимости может быть указан цветовой профиль как непосредственным включением, так и ссылкой на другой файл.
Профили появились в пятой версии BMP, и пока только здесь есть специальные для них поля.
Поддерживаются же цветовые профили только в формате ICC.

При использовании цветовых профилей в первую очередь нужно указать следующие значения поля CSType:

 4C494E4B16 (PROFILE_LINKED) — если используется профиль в другом файле.
 4D42454416 (PROFILE_EMBEDDED) — если профиль непосредственно встраивается в BMP.

В любом случае в поле ProfileData указывается смещение профиля в байтах от начала блока BITMAPINFO.
Если профиль встроенный, то в ProfileSize нужно указать его размер в байтах (если он подключаемый, то это поле должно быть обнулено).
Независимо от варианта, Microsoft рекомендует размещать профиль при хранении в файле за пиксельными данными, а в оперативной памяти при взаимодействии с WinAPI-функциями: сразу за заголовком.

Формат ICC в своём заголовке использует преимущественно 32-битные или кратные этому размеру ячейки.
Исходя из этого, если профиль непосредственно включается в BMP, то в оперативной памяти его рекомендуется хранить по кратному четырём байтам адресу.

Когда профиль внешний, то вместо его содержимого в BMP размещается текстовая строка с путём к файлу.
Он обязательно должен быть в однобайтовой кодировке Windows 1252 (стандартная кодировка для западноевропейских языков) и заканчиваться нулевым байтом.
Про разделители компонентов пути в документации ничего не сказано и поэтому скорее всего можно использовать как левые слэши «\», так и «правые» «/».
Путь же может быть как относительным, так и полным и сетевым.
И так как в указании пути используется однобайтовая кодировка, то эту строку в оперативной памяти выравнивать не обязательно.

Предпочтения при рендеринге 
Предпочтения при рендеринге () были введены Международным концорциумом по цвету (International Color Consortium) и определяют приоритеты в случае когда при переходе из цветового подпространства, поддерживаемого одним устройством (), в подпространство другого, в изображении использованы цвета, отсутствующие в целевом.
Также есть определение от ICC, которое определяется предпочтения при рендеринге как стиль сопоставления цветовых значений из одного описателя изображения в другое (оригинал на английском языке: «style of mapping colour values from one image description to another»).
Корпорация Microsoft включила в формат BMP специальное поле Intent, которое может принимать значения полностью по спецификации ICC.
Поэтому за подробной информации обращайтесь к документации консорциума, последнюю версию которой можно скачать с сайта color.org.
У Microsoft же эти предпочтения коротко описаны в статье «Rendering Intents» на MSDN.

Предпочтение указывается в поле Intent блока BITMAPINFO и доступны только с 5-й версией информационных полей.
Значения же могут быть следующими:

Microsoft для данной характеристики объявила как минимум три набора констант, которые отличаются своими значениями и используются в разных местах.
Здесь они приведены на случай если вам нужно будет быстро их сопоставить.
Значения констант с префиксом «INTENT_» полностью совпадают с теми значениями, которые используются в файлах профилей ICC.
Константы с префиксом «DMICM_» объявлены в файле WinGDI.h для структуры DEVMODE.
Константы «LCS_GM_», которые используются в BMP, объявлены там же и предназначены в первую очередь для структуры LOGCOLORSPACE.
Есть также названия для свойств принтеров.
Они аналогичны тем, что в колонке «Название Microsoft», но с «Graphics» и «Pictures».

За значение по умолчанию, которое в первую очередь подходит для фотографий и картинок, можно принимать 4 (LCS_GM_IMAGES).
В таком качестве его рекомендует как Microsoft, так и ICC.

Пример программы на C 
Следующая программа открывает 24 битный BMP файл в окне XWindow, глубина цвета должна составлять 32 бита, на меньшей цветопередаче не работает, так как это усложняет пример:

/* Компилируется строкой: cc -o xtest xtest.c -I/usr/X11R6/include -L/usr/X11R6/lib -lX11 -lm  */
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <math.h>
#include "bitmap.h" /* Здесь определения заголовков BMP как было описано выше в этой статье (структуры должны быть упакованы на 2 байта!) */

static XImage *CreateImageFromBuffer(Display*, unsigned char *, int, int);

main(int argc, char *argv[])
{
    Display *dis;
    Window win;/* Наше окно */
    XEvent event;/* События */
    GC gc;/* Графический контекст */

    XImage *image;
    int  n, width, height, fd, size;
    unsigned char *data;
    BITMAPFILEHEADER bmp;
    BITMAPINFOHEADER inf;
    char* buf;

    if (argc < 2) {
	perror("use: xtest file.bmp\n");
	exit(1);
    }

  if ((fd = open(argv[1], O_RDONLY)) == -1) {
        printf("Error open bitmap\n");
        exit(1);
    }

  read(fd, &bmp, sizeof(BITMAPFILEHEADER));
  read(fd, &inf,sizeof(BITMAPINFOHEADER));

  width = inf.biWidth;
  height = inf.biHeight;

    if ((dis = XOpenDisplay(getenv("DISPLAY"))) == NULL) {
	printf("Can't connect X server:%s\n", strerror(errno));
	exit(1);
    }

    win = XCreateSimpleWindow(dis, RootWindow(dis, DefaultScreen(dis)), 0, 0, width, height, 5,
                   BlackPixel(dis, DefaultScreen(dis)), WhitePixel(dis, DefaultScreen(dis)));

    XSetStandardProperties(dis, win, argv[1], argv[0], None, argv, argc, NULL);
    gc = DefaultGC(dis, DefaultScreen(dis));

 /* Иногда в структуре это место не заполнено */
    if(inf.biSizeImage == 0)  {
    /* Вычислим размер */
     size = width * 3 + width % 4;
     size = size * height;
    } else {
      size = inf.biSizeImage;
     }
    
    buf = malloc(size);
    if(buf == NULL) {
	perror("malloc");
	exit(1);
    }
    printf("size =%d байтов выделено\n", size);

     /* Сместимся на начало самого изображения */
    lseek(fd, bmp.bfOffBits, SEEK_SET);

    /* Читаем в буфер */
    n = read(fd, buf, size);
    printf("size =%d байт прочитано\n", n);

   image = CreateImageFromBuffer(dis, buf, width, height);

   /* Удалим буфер - он нам больше не нужен */
   free(buf);

    XMapWindow(dis, win);
    XSelectInput(dis, win, ExposureMask | KeyPressMask);
    while (1) {
	XNextEvent(dis, &event);
	if (event.xany.window == win) {
	    switch (event.type) {
	    case Expose:
		XPutImage(dis, win, gc, image, 0, 0, 0, 0, image->width, image->height);
		break;

	    case KeyPress:
		if (XLookupKeysym(&event.xkey, 0) == XK_q) {
		    XDestroyImage(image);
		    XCloseDisplay(dis);
    	    	    close(fd);
		    exit(EXIT_SUCCESS);
		}
		break;

	    default:
		break;
	    }
	}
    }
}

/* Создает Ximage из файла BMP, так как изображение BMP хранится первернутым
 * и зеркальным-в цикле это исправляется */ 
XImage *CreateImageFromBuffer(Display * dis, unsigned char *buf, int width,  int height)
{
    int depth, screen;
    XImage *img = NULL;
    int i, j;
    int numBmpBytes;
    size_t numImgBytes;
    int32_t *imgBuf;
    int ind = 0;
    int line;
    int temp;
    int ih, iw; /* Номера строки и столбца для отражения  */
    int new_ind; /* Новый индекс */

    screen = DefaultScreen(dis);
    depth = DefaultDepth(dis, screen);
    temp = width * 3;
    line = temp + width % 4; /* Длина строки с учетом выравнивания */
    numImgBytes = (4 * (width * height));
    imgBuf = malloc(numImgBytes);

    /* Размер, отведенный на BMP в файле с учетом выравнивания */
    numBmpBytes = line * height;
    for (i = 0; i < numBmpBytes; i++) {
	unsigned int r, g, b;

	/* Пропускаем padding */
	if (i >= temp && (i % line) >= temp)
	    continue;
	
	b = buf[i];
	i++;
	g = buf[i];
	i++;
	r = buf[i];

	
	/* Вычисляем новый индекс для отражения по вертикали */
	iw = ind % width;
	ih = ind / width;
	new_ind = iw + (height - ih - 1) * width;
	
	imgBuf[new_ind] = (r | g << 8 | b << 16) << 8;
	ind++;
    }

    img = XCreateImage(dis, CopyFromParent, depth, ZPixmap, 0, (char *) imgBuf, width, height, 32, 0);
    XInitImage(img);

    /* Порядок битов и байтов на PC должен быть таким */
    img->byte_order = MSBFirst;

    img->bitmap_bit_order = MSBFirst;
    return img;
}

См. также 
 ICO (формат файлов) — родственный формат от Microsoft для хранения значков и курсоров мыши.

Примечания

Литература

Microsoft (MSDN и SDK) 
Microsoft Windows SDK — комплект для разработчиков, который включает в себя справку и включаемые файлы на языке C++.
По теме данной статьи актуальны файлы WinGDI.h и Icm.h, из которых были взяты в первую очередь значения констант.
Последнюю версию данного комплекта можно бесплатно скачать с сайта Microsoft (в данной статье использовались версии 6.0 и 7.1).

У Microsoft нет отдельной специальной документации именно по формату BMP.
Но его структуры и прочие элементы описаны в рамках подсистемы GDI.
Это описание есть в справке, которая включается в вышеупомянутое SDK, а также на MSDN.
Причём в последнем она присутствует для разных платформ и независимо в справке по Visual Studio.
В большинстве случаев там представлена идентичная информация, но в некоторых местах может быть немного больше фактов (например, в справке SDK больше информации о поддержке Windows).

Основная информацию находится в справке по GDI, которая относится к платформам Windows 9x и NT.
Ссылки на страницы этого раздела, которые относятся только к формату, а не к WinAPI-функциям работы с ним:
 «Bitmap Classifications» — описание аппаратно-зависимых и аппаратно-независимых битмапов.
 «Bitmap Storage» — общее описание формата файла BMP.
 «Bitmap Header Types» — обзор по версиям заголовков BMP.
 «Bitmap Compression» — описание RLE-кодирования.
 «Bitmap Structures» — раздел с описаниями структур с полями. Для удобства прямые ссылки на ключевые:
 BITMAPFILEHEADER
 BITMAPCOREHEADER
 BITMAPINFOHEADER
 BITMAPV4HEADER
 BITMAPV5HEADER

У платформ Windows Compact 2013 (CE 6.0) и Mobile 6.5 есть только описания трёх структур, но применительно к данным платформам:
 BITMAPFILEHEADER
 BITMAPCOREHEADER
 BITMAPINFOHEADER

Ссылки на другие страницы из MSDN, которые относятся к формату BMP:
 «Image Pixel Format Constants» — константы форматов пикселей GDI+.
 «PixelFormat Enumeration» — описание значений перечисляемого типа PixelFormat для .NET Framework 1.1 (самая ранняя версия).
 «Using Structures in WCS 1.0» — про используемые в управлении цветом в Windows структуры.
 «Rendering Intents» — описание предпочтений при рендеринге.

Другие 
В спецификации ICC по управлению цветом можно найти информацию о цветовых профилях (в том числе о формате файлов ICC), а также о предпочтениях рендеринга.
Данную спецификацию можно скачать с официального сайта концорциума color.org.
В момент написания статьи последней версией была 4.3 (декабрь 2010).
Прямая ссылки на PDF с сайта ICC:
 Specification ICC.1:2010 (Profile version 4.3.0.0) «Image technology colour management — Architecture, profile format, and data structure».
 Errata к спецификации (обнаруженные ошибки и опечатки; опубликованы 24 сентября 2013 года).

Графические форматы