Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

System programming / Конспект лекций / Лекция 13 Представление графической информации

.doc
Скачиваний:
44
Добавлен:
08.05.2015
Размер:
57.86 Кб
Скачать

Лекция 13 Представление графической информации

Битовые образы.

Битовые или растровые образы (bitmap) представляют собой метод хранения графической информации в программах для Windows. Битовый образ – это цифровое представление изображения. Каждому пикселю (точке) изображения соответствует один или более бит битового образа, которые определяют цвет пикселя. Таким образом, если, например, нам необходимо запомнить монохромное (черно-белое) изображение, мы можем использовать только один бит (0-черный, 1-белый) для запоминания одной точки рисунка. Битовые образы имеют как достоинства, так и недостатки. К достоинствам можно отнести хорошую передачу изображения (именно они чаще всего используются для хранения фотографий, сложных рисунков), ограниченную только воспроизводящим оборудованием (видео картой и монитором) цветовую гамму. Существенными недостатками является большой объем памяти для хранения и сложные алгоритмы преобразования битовых образов при выводе на конкретное устройство отображения (масштабирование, соответствие реальной и доступной цветовых гамм и т.п.).

Битовые образы, не зависящие от устройства.

Формат DIB (device independent bitmap) содержит таблицу цветов, которая содержит информацию о преобразовании пикселей в RGB формат. Фактически, данный формат не является объектом GDI, однако является очень удобной формой для хранения и передачи изображения между программами и компьютерами. Каждому пользователю компьютера известен этот формат – это не что иное, как файл с расширением *.bmp. Приведем описание формата этого файла.

Файл *.bmp начинается с секции заголовка, определенной структурой BITMAPFILEHEADER. Эта структура имеет пять полей:

Поле

Размер

Описание

bfType

WORD

Байты «ВМ» для битовых образов

bfSize

DWORD

Общий размер файла

bfReserved1

WORD

Установлено в 0

bfReserved2

WORD

Установлено в 0

bfOffBits

DWORD

Смещение битового образа от начала файла

За этой информацией следует другой заголовок, определенный структурой BITMAPINFOHEADER. Структура имеет 11 полей.

Поле

Размер

Описание

biSize

DWORD

Размер структуры в байтах

biWidth

LONG

Ширина битового образа в пикселях

biHaight

LONG

Высота битового образа в пикселях

biPlanes

WORD

Установлено в 1

biBitCount

WORD

Число битов цвета на пиксель (1,4,8,24)

biCompression

DWORD

Схема компрессии (если нет – 0)

biSizeImage

DWORD

Размер битов битового образа в байтах (нужен только при компрессии)

biXPelsPerMeter

LONG

Разрешение в пикселях на метр по горизонтали

biYPelsPerMeter

LONG

Разрешение в пикселях на метр по вертикали

biClrUsed

DWORD

Число цветов, используемых в изображении

biClrImportant

DWORD

Число важных цветов в изображении

Приведенная структура может иметь различный размер, определяемый полем biSize. Первые 5 параметров являются обязательными. Остальные могут присутствовать в файле, могут и нет. Кроме этого, пользователь может добавлять свои оригинальные записи в конец структуры. Если biClrUsed установлено в ноль и число битов на пиксель равно 1,4,8, то сразу за данной структурой следует таблица цветов, состоящая из двух или более структур RGBQUAD (при 1 – две, при 4 – шестнадцать, и т.д. ), каждая из которых определяет значение цвета:

Поле

Размер

Описание

rgbBlue

BYTE

Интенсивность голубого

rgbGreen

BYTE

Интенсивность зеленого

rgbRed

BYTE

Интенсивность красного

rgbReserved

BYTE

Равно 0

Число структур RGBQUAD может быть напрямую задано в поле biClrUsed.

За таблицей цветов следует массив битов, определяющих битовый образ. Этот массив начинается с нижней строки пикселей. Каждая строка начинается с левого пикселя. Каждый пиксель представлен 1, 4, 8 или 24 битами. Во-первых трех случаях число, записанное в битовом образе определяет номер RGBQUAD- структуры в таблице цветов. В случае 24-х бит – это, фактически, и есть 3 байта RGB-представления цвета. В последнем случае таблица цветов может отсутствовать.

Для вывода битовых образов, не зависящих от устройства, существует несколько функции GDI. Первая из них позволяет копировать битовый образ в контекст устройства:

int SetDIBitsToDevice(

HDC hdc, // указатель на контекст устройства

int XDest, // x-координата верхнего левого угла

int YDest, // y-координата верхнего левого угла

DWORD dwWidth, // ширина выводимого изображения

DWORD dwHeight, // высота выводимого изображения

int XSrc, // x-координата отступа в изображении

int YSrc, // y-координата отступа на контексте

UINT uStartScan, // первая сканируемая линия изображения

UINT cScanLines, // число сканируемых линий

CONST VOID *lpvBits, // адрес битового образа

CONST BITMAPINFO *lpbmi, //адрес структуры BITMAPINFO

UINT fuColorUse // признак RGB или палитры

);

Следует заметить, что в функции используется структура BITMAPINFO, а не присутствующая в файле BITMAPINFOHEADER, которая определена в Windows как:

typedef struct tagBITMAPINFO {

BITMAPINFOHEADER bmiHeader; // Уже знакомая нам структура

RGBQUAD bmiColors[1]; // Таблица цветов

} BITMAPINFO;

Рассмотренная функция производит копирование битов в выбранный контекст. Другая функция, позволяет при этом масштабировать выводимое изображение, т.е. автоматически изменяет размер картинки до размеров области вывода:

int StretchDIBits(

HDC hdc, // указатель на контекст устройства

int XDest, // x-координата верхнего левого угла в контексте

int YDest, // y-координата верхнего левого угла в контексте

int nDestWidth, // ширина выводимого изображения в контексте

int nDestHeight,// высота выводимого изображения в контексте

int XSrc,//x-координата верхнего левого угла выводимой части изображения

int YSrc,//у-координата верхнего левого угла выводимой части изображения int nSrcWidth, // ширина выводимого изображения в битовом образе

int nSrcHeight, //высота выводимого изображения в битовом образе

CONST VOID *lpBits, // адрес битового образа

CONST BITMAPINFO *lpBitsInfo, // адрес структуры BITMAPINFO

UINT iUsage, // флаг использования цвета

DWORD dwRop // растровая операция

);

Флаг использования цвета определяет, есть ли в структуре BITMAPINFO таблица палитры (значение флага - DIB_PAL_COLORS) или в битовом образе содержится полная информация о цвете (DIB_RGB_COLORS). Последний параметр функции определяет код растровой операции. Наиболее часто используемые из них:

BLACKNESS Заполняет выбранную область приемника черным цветом

DSTINVERT Инвертирует выбранную область приемника

NOTSRCCOPY Копирует изображение с инверсией.

SRCCOPY Копирует изображение

WHITENESS Заполняет выбранную область приемника белым цветом

Битовые образы, зависящие от устройства.

Вид данного битового образа организован так, чтобы облегчить вывод графической информации (битов) на конкретное физическое устройство. Наиболее часто используемые форматы в этом случае – организация набора цветовых битов на пиксель или набора цветовых плоскостей.

В первом случае каждому пикселю на экране ставится в соответствие некоторое количество бит. Например, если монитор может отобразить 256 цветов, то используется 8 байт на один пиксель. Для каждой скан-линии (строки растра) первый байт представляет цвет самого левого пикселя, второй байт – следующего пикселя и т.д. Подобная организация видеопамяти, бала, например в CGA – мониторах.

Пример второго вида организации битовых образов – это EGA и VGA - мониторы, которые в большинстве стандартов поддерживают плоскостное представление изображения. Цветной битовый образ для 16-цветного VGA использует 4 цветовые плоскости для представления 16 цветов. Массив битов начинается с верхней скан-линии. Цветовые плоскости для каждой скан-линии хранятся последовательно: красная плоскость - первой, зеленая плоскость – второй, затем голубая плоскость и плоскость интенсивности. Каждая плоскость имеет свой адрес в оперативной памяти.

На основе вышеизложенного можно сделать вывод, что в каждом конкретном случае зависимый битовый образ организован по-разному. И если, программа создает сама битовый образ (например, на основе функций CreateBitmap, CreateBitmapInderect), то она должна сама определять тип, количество цветовых плоскостей. Формат данных функций следующий:

HBITMAP MyBitmap1, MyBitmap2;

BITMAP MyStruct;

MyBitmap1=CreateBitmap(nWidth, nHeight, cPlanes, cBitsPerPel, lpvBits);

MyBitmap2=CreateBitmapInderect(&MyStruct);

где nWidth – ширина создаваемого битового образа,

nHeight - высота создаваемого битового образа,

cPlanes - количество битовых плоскостей,

cBitsPerPel - число битов на один пиксель,

lpvBits - указатель на битовый образ.

Структура BITMAP содержит перечисленные данные непосредственно.

Однако, более легким вариантом является создание совместимого битового образа на основе контекста устройства. Это можно сделать при помощи функции:

HBITMAP MyBitmap;

MyBitmap = CreateCompatibleBitmap(hdc, xWidth,yHeght);

где hdc – описатель контекста устройства, остальные два параметра определяют ширину и высоту создаваемого битового образа. Созданный таким образом битовый образ будет иметь структуру, определяемую характеристиками устройства.

Теперь перейдем к вопросу вывода зависимого битового образа на конкретное устройство. Для данного вида графической информации не существует функций, осуществляющих непосредственный вывод в контекст устройства (подобных SetDIBitsToDevice и StretchDIBits для независимых битовых образов) на основе описателя битовых образов (HBITMAP). Для их вывода используется следующий механизм: Битовый образ, выбранный в одном контексте, может быть скопирован в другой контекст. Таким образом, в процессе участвуют два контекста: первый (обычный), в который необходимо скопировать битовый образ, и второй – в котором содержится изображение. Второй контекст, в данном случае, необходимо создать; создается он в памяти и не соответствует конкретному устройству вывода. Он так и называется – контекст памяти. Для того, чтобы дальнейшая работа по копированию битовых образов происходила без проблем, оба контекста должны быть совместимыми, или, говоря другими словами, контекст памяти необходимо создать на основе контекста устройства. Это делается при помощи следующей функции:

HDC hdcMem;

hdcMem = CreateCompatibleDC(hdc);

где hdc – описатель контекста, куда будет вестись вывод изображения.

Второй этап заключается в выборе битового образа в контекст памяти по тому же образу, каким любой объект GDI выбирается в контекст устройства:

SelectObject(hdcMem,MyBitmap);

И только после этого можно скопировать битовый образ в контекст устройства:

BitBlt(hdc, xDest, yDest, xWidth, yHeight, hdcMem, xSrc, ySrc, dwROP);

где xDest, yDest, xWidth, yHeight – определяют координаты прямоугольника на контексте устройства, в который осуществляется вывод изображения, xSrc, ySrc – определяют начальное положение угла источника, с которого начинается вывод, а dwROP – идентификатор знакомой нам растровой операции.

После окончания работы с контекстом памяти, его необходимо удалить:

DeleteDC(hdcMem);

Существует и аналог масштабируемого вывода для зависимых битовых образов:

StretchBlt(hdc, xDest, yDest, xDestWidth, yDestHeight, hdcMem, xSrc, ySrc, xDSrcWidth, ySrctHeight, dwROP),

в которой напрямую указываются размера выводимого изображения и размеры приемника.

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

Метафайлы

Метафайлы являются примером другого способа представления графической информации - векторного. В растровом изображении каждой точке некоторой области (листа бумаги, экрана монитора) соответствует некоторое число, определяющее цвет этой точки. В векторной графики существует некоторый набор примитивов (прямых линий, кривых, прямоугольников, закрашенных областей, текста и т.п.), которые задаются непосредственно в виде записей. Например, для точки необходимо хранить две координаты (х и у), для линии – информацию о двух конечных точках линии, для окружности – координаты центра и радиус. Данные записи составляют содержимое метафайла.

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

Поскольку метафайл описывает изображение в терминах команд графического вывода, изображение может быть промасштабировано без потери разрешения. С битовыми образами это невозможно: при увеличении битового образа биты будут просто повторяться горизонтально или вертикально, при уменьшении – выбрасываться на основе какого-либо алгоритма.

Метафайлы могут быть преобразованы в битовый образ без потери информации. Обратное преобразование практически невозможно в общем случае.

Для создания метафайла сначала создается контекст метафайла:

HDC hdcmf;

hdcmf = CreateMetaFile(“name.wmf”);

где “name.wmf” – имя файла на диске. Если данный параметр функции равен NULL, то метафайл создается в памяти.

После этого, вы можете рисовать на контексте метафайла точно так же, как и на контексте любого другого устройства. Например,

LineTo(hdcmf,20,20,80,80);

Rectandle(hdcmf, 10,10,50,60);

После закрытия метафайла

HMETAFILE hmf;

hmf = CloseMetaFile(hdcmf);

его в любой момент можно проиграть на любом другом контексте:

PlayMetaFile(hdc,hmf);

После окончания работы с метафайлом, его необходимо удалить из памяти:

DeleteMeteFile(hmf);

Данная функция удаляет метафайл из памяти. Если же этот метафайл был создан на диске, то выполнение данной функции приведет к тому, что из памяти он удалится, а на диске останется. Прочитать метафайл с диска можно при помощи функции:

hmf=GetMetaFile(“name.wmf”);