Zeroes and Ones - портал высоких технологий - Формат BMP ( Часть 1 )
Новости
Главная
Software
Hardware
Mobile
Наши новости
Техника
Электроника
Программирование
Delphi
HTML / CSS
*NIX
Дополнительно
О нас
Контакты
Последние новости

 


Опросы

Я за процессоры:



Популярное


Реклама


Партнеры
Формат BMP ( Часть 1 )
Автор Albinos_X   
12.05.2007 г.
 Эта статья про то, что собой представляет графический формат BMP. Хоть это и один из простых форматов, но из-за того, что существует много вариаций этого формата, то не все моменты очевидны.
Введение
Формат BMP (от слов BitMaP - битовая карта, или, говоря по-русски, битовый массив) является одной из форм представления растровой графики. Проще говоря, изображение представляется в виде матрицы прямоугольных точек, где каждая точка характеризуется тремя параметрами - x координатой, y координатой и цветом. Формат BMP разрабатывался изначально двумя корпорациями Intel и Microsoft, и в то время был одинаков для обеих операционных систем Intel OS/2 Warp и Microsoft Windows 2.x. Однако далее фирма Microsoft расширила формат, расширив структуры (при этом сохранив как обратную, так и прямую совместимость для несжатых разновидностей) и добавив поддержку компрессии. Добавилась поддержка сжатия без потерь PNG и RLE, а также сжатие с потерями JPEG. Казалось бы, JPEG и BMP, совместили несовместимое, однако это только на первый взгляд. На самом деле формат BMP – является родным не только для операционных систем Windows и OS/2, но и для различных аппаратных устройств (имеется ввиду его аппаратная версия DDB - будет описана далее). Родным в том смысле, что все операции графического ввода – вывода на экран (принтер и на некоторые другие устройства) в конечном итоге осуществляются посредством него (в том или ином его виде). Так вот, поскольку современные принтеры поддерживают прямой вывод изображений в форматах PNG и JPEG на устройство, и была введена их поддержка. Тем самым, обеспечив аппаратный вывод в рамках единого формата. Под вывод BitMaP-в, оптимизируется архитектура большинства видеоадаптеров. Для чтения и вывода в ОС Windows, предусмотрено много специальных функций и структур API (библиотека gdi32.dll и gdiplus.dll), которые помогают производить все необходимые операции на достаточно высоком логическом уровне. Delphi – еще более упрощает работу предоставляя нам класс надстройку над API - TBitMap, который здесь рассматриваться не будет поскольку хорошо описан во многих источниках. В заключение к разделу хочется развеять одну неопределенность. Windows поддерживает работу с тремя битмапоподобными форматами *.bmp, *.rle, *.dib. *.rle – это сжатый битмап (как это следует из названия в формате RLE), полностью совместимый с bmp. *.dib – битмап версий Windows более чем 3.0. *.bmp – изначально предполагался быть совместимым с Windows 2.x, в последствии вероятно от этого отказались и сделали его мультиформатным. Данные форматы внутренне ни чем не друг от друга не отличаются (т.е. являются, по сути, псевдонимами *.bmp) и были введены для явного указания формата сжатия.
Осознали значимость этого формата, теперь приступим к делу.
 
Аппаратно-зависимые и аппаратно-независимые битовые карты (Device-Dependenent and Device-Independent bitmap - DDB и DIB)
Аппаратно-зависимые или DDB битмапы используются windows для хранения изображений в памяти различных графических устройств (в частности в видеопамяти). Фактически такой битмап представляет собой урезанную версию аппаратно-независимого. Его данные формируются таким образом, чтобы соответствовать конкретному графическому режиму, кроме того, такой битмап содержит упрощенный заголовок. Например, для старого 16 цветного EGA/VGA видеоадаптера, такой битмап будет представлять собой 3 цветовые матрицы (для каждого из цветов), аппаратно-независимый битмап будет содержать всего одну матрицу разрядностью 4бита на пиксель.
Поскольку структура DDB битмапа меняется в зависимости от устройства к устройству, то он, как правило, создается прямо в памяти и не сохраняется в файл. Для сохранения в файл DDB конвертируется в DIB (т.е. аппаратно-независимый). В настоящее время графические ускорители оптимизируются под работу с DIB – универсальность в ущерб производительности (на самом деле эти потери незначительны). DDB битмап далее не будет описываться. Часто в литературе говорят битмап а подразумевают DIB (и наоборот) это не является грубой ошибкой.

Структура формата
Перед описанием структуры уточню, что структура битмапа в оперативной памяти повторяет файловую структуру, и все что верно для файла верно и для его образа в памяти, но неверно для DDB. Все структуры (записи) взяты из windows.pas с измененными именами, константы взяты из заголовочных файлов Borland C++ windows.h, wingdi.h.
Файл всегда состоит из трех частей.
1) Файловый заголовок – всегда структура TBitMapFileHeader – это единственная общая структура для всех типов и версии.
2) Затем для Windows версии 2.x и OS/2 идет структура (запись) TBitmapCoreInfo. Для всех остальных версий это TBitmapInfo
3) Массив данных – структура которого весьма разнообразна.

Теперь подробнее о каждой.

В начале стоит заголовок файла (TBitMapFileHeader). Он описан следующим образом:

TBitMapFileHeader = packed record
bfType: Word;
bfSize: DWORD;
bfReserved1: Word;
bfReserved2: Word;
bfOffBits: DWORD;
end;

bfType - два символа определяющие тип файла. Могут быть следующие варианты:
‘BM’ - Windows 3.1x, 95, NT, …
‘BA’ - OS/2 Bitmap Array, Windows 2.x
‘CI’ - OS/2 Color Icon
‘CP’ - OS/2 Color Pointer
‘IC’ - OS/2 Icon
‘PT’ - OS/2 Pointer

Программисты Windows – вероятно встречали только ‘BM’ (от слова BitMap, как вы уже, наверное, догадались). Не смотря на это, я полагаю, будет не лишним проверять, что за битмап нам передали (чтоб потом “не радовать” пользователя неожиданными ошибками при чтении правильных, с точки зрения, формата битмапов).
bfSize - это размер самого файла в байтах. В идеале все программы для того, чтобы убедиться, что перед ними действительно правильный bmp, должны, проверить, что bfType содержит "BM" (без кавычек), а, во-вторых, что bfSize равен действительному размеру файла. Хотя далеко не все программы используют это значение, оно должно быть верным, так как – это позволит нам убедиться в том, что файл был скопирован (или скачен) целиком.
bfReserved1 и bfReserved2 зарезервированы и должны быть нулями. Эти значение тоже желательно проверить, ведь в будущем они могут быть использованы для расширения формата. Естественно, что ваша программа не сможет их (такие файлы) прочитать, поэтому, узнав о ненулевых значениях можно правильно проинформировать пользователя, тем самым сэкономить его время.
bfOffBits - это один из самых важных полей в этой структуре. Он показывает, где начинается сам битовый массив относительно начала файла, который и описывает картинку. Несмотря на то, что это значение можно определить по концу таблицы цветов, рекомендуется использовать именно это значение, для совместимости с возможными новыми вариациями формата.
Для Windows версии 2.x и OS/2 идет структура (запись) TBitmapCoreInfo

TBitmapCoreInfo = record
bmciHeader: TBitmapCoreHeader;
bmciColors: array[0..0] of TRGBTriple;
Reserved : array[0..0] of Char;
End;
Где TBitmapCoreHeader = packed record
bcSize : DWORD;
bcWidth : Word;
bcHeight : Word;
bcPlanes : Word;
bcBitCount: Word;
end;


а bmciColors - цветовая палитра в формате

TRGBTRiple = packed record
rgbtBlue : Byte;
rgbtGreen: Byte;
rgbtRed : Byte;
end;


array[0..0] – не следует понимать буквально, просто количество цветов может быть различным
Размер заголовка TBitmapCoreHeader хранится в bcSize и для OS/2 1.x совпадает с приведенным выше и равен 12 байтам - $0Ch. Для OS/2 2.x он занимает 15 байт? (вероятно в источнике ошибка – там указано 240 байт т.е. $F0h, вероятно имелось ввиду $0Fh – поскольку данная структура не содержит ни таблицы цветов, ни самих данных).
В Windows 3.x, 95, NT возможны две версии измененной TBitmapCoreHeader. Первая TBitmapInfoHeader структура занимает 40 байт - $28h, вторая TBitmapV4Header – занимает 108 байт – $6Ch (будут описаны ниже). И, наконец, для Windows 98/Me, Windows 2000/XP – это TBitmapV5Header размером 124 байта – $7Сh (также будет описана ниже). Все размеры я указал не ради порядка, а для правильной идентификации версии, поскольку форматом не предусмотрено ни одного поля идентифицирующего версию. Чтоб не напугать новичков обилием версий замечу, что для чтения подавляющего большинства битмапов достаточно знать и использовать один лишь TBitmapInfoHeader, при этом все современные приложения правильно и корректно будут производить с ним все допустимые операции.
Все структуры являются расширением первой TBitmapCoreInfo – поэтому в последующих структурах будут описаны только новые поля.
bcWidth и bcHeight – ширина и высота изображения в пикселях. В последующих структурах это будут уже двойные слова (из-за этого и нет полной совместимостей новых структур с TBitmapCoreHeader). Значение bcHeight (для версий Windows 3.x, 95, NT) может быть отрицательным. В этом случае модуль bcHeight определяет действительную высоту, а строки изображения читаются в обратном порядке, т.е. сверху вниз (обычно снизу вверх). Кроме того, такие изображения всегда несжатые (т.е. BI_RGB или BI_BITFIELDS).
bcPlanes - задает количество плоскостей или цветовых слоев (помните я упоминал что DDB – могут иметь 3 цветовые плоскости например R G B или C M Y– связанные с особенностями графического устройства). Сохраняемая версия битмапа т.е. DIB поддерживает пока одну общую для всех цветов плоскость, разрядность цвета этой плоскости задается bcBitCount. Попытки установить значения отличные от единицы вызывают ошибку при передаче структуры api функциям.
bcBitCount – определяет разрядность цвета. Допустимы следующие варианты
0 – изображение только PNG и BMP допустимо только версии Windows 98/Me, Windows 2000/XP
1монохромное изображение (поддерживается всеми версиями). Каждый пиксель представлен одним битом данных, т.е. один байт содержит информацию о цвете 8 последовательно идущих пикселей. Цвет первого пикселя определяется состоянием старшего бита первого байта (и так далее), если его значение равно единице, то цвет пикселя будет определяться первой записью таблицы цветов (считается от нуля). Вообще значение цвета определяется по RGB (для BI_RGB версии) составляющим, таблицы цветов, по индексу.
416-ти цветное изображение. Каждый пиксель представлен 4 битами (поддерживается всеми версиями).
8изображения с количеством цветов до 256. 1 байт – 1 пиксель (поддерживается всеми версиями)
16 – поддерживается не менее чем Windows 95, и является достаточно редким. Количество цветов зависит от версии Windows и выбранного формата сжатия и может быть как 2 в 16 либо 2 в 15 степени. Это самый запутанный вариант. Начнем с того, что он беспалитровый, то есть каждые два байта (одно слово WORD) в растре однозначно определяют один пиксель. Но вот что получается: битов-то 16, а компонентов цветов - 3 (Красный, Зеленый, Синий). А 16 никак на 3 делиться не хочет. Поэтому здесь есть две варианта. Первый - использовать не 16, а 15 битов, тогда на каждую компоненту цвета выходит по 5 бит. Таким образом, мы можем использовать максимум 2 в 15 = 32768 цветов, и получается тройка R-G-B = 5-5-5. Но тогда за зря теряется целый бит из 16. Но так уж случилось, что наши глаза среди всех цветов лучше воспринимают зеленый цвет, поэтому и решили этот один бит отдавать на зеленую компоненту, то есть тогда получается тройка R-G-B = 5-6-5, и теперь мы может использовать 2 в 16 = 65536 цветов. Но что самое неприятное, что используют оба варианта. В MSDN предлагают для того, чтобы различать, сколько же цветов используется, заполнять этим значением поле biClrUsed (будет описано ниже) из структуры BITMAPINFOHEADER. Чтобы выделить каждую компоненту надо использовать следующие маски. Для формата 5-5-5: $001Fh для синей компоненты, $03E0h для зеленой и $7C00h для красной. Для формата 5-6-5: $001Fh - синяя, $07E0h - зеленая и $F800h красная компоненты соответственно.
24 - а это самый простой формат. Количество цветов 2 в 24 степени. Здесь 3 байта определяют 3 компоненты цвета. То есть по компоненте на байт. Просто читаем по структуре RGBTRIPLE(для Windows версии 2.x и OS/2) и используем его поля rgbtBlue, rgbtGreen, rgbtRed. Они идут именно в таком порядке (поддерживается всеми версиями).
32 - Здесь 4 байта определяют 3 компоненты, т.е. по-прежнему количество цветов 2 в 24 степени. Но, правда, один байт не используется. Его можно отдать, например, для альфа-канала (прозрачности). Поддерживается не менее чем Windows 95.
На этом описание структур совместимых с Windows версии 2.x и OS/2 заканчиваем и переходим к современным.

Автор: Alexeis (С) ( http://forum.vingrad.ru/index.php?showuser=777&nickname=Alexeis )

Комментарии

Функция доступна только зарегистрированным пользователям.
Войдите под своей учетной записью или зарегистрируйтесь.

Powered by AkoComment 2.0!

 
2001-2007 Jey_k & Albinos_X
Мой ip проверка
ALLDAY.RU - портал обо всем интересном в дизайне