Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Использование промежуточного DDB при работе с DIB

 

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

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

Основа способа проста:

сначала надо загрузить DIB (обычно в виде «Packed DIB»)

преобразовать DIB в DDB с помощью функции CreateDIBitmap

выполнить требуемые операции над DDB (см. «Работа с зависимым от устройства битмапом», стр. 45)

осуществить обратное преобразование DDB в DIB с помощью функции GetDIBits

Первая операция — загрузка DIB — уже подробно рассмотрена в разделе «Загрузка независимых от устройства битмапов.», на ней останавливаться сейчас не будем. Вторая операция позволяет получить хендл DDB (HBITMAP), который можно использовать для выполнения требуемых операций над битмапом. Так, например, такой битмап может быть выбран в совместимый контекст устройства или использован для создания кисти и т.д.

Следует отметить, что определяя свойства преобразования DIB в DDB надо правильно определить цель такого преобразования. Если вы планируете выполнить редактирование DIB, то важно не испортить хранимое изображение; часто может быть целесообразно назначить цветовое разрешение DDB достаточно высоким, скажем TrueColor, даже если он реально будет отображаться на устройстве, имеющем существенно меньшее цветовое разрешение. Либо воспользоваться DIB–секциями, которые также возвращают HBITMAP. Однако еще чаще встречается другой вариант — преобразование DIB в DDB выполняется для ускорения процесса вывода. Так, например, если битмап применяется для закраски фона окна (в качестве «обоев»), то особую важность приобретает скорость вывода, в то время как качество цветопередачи должно только лишь соответствовать возможностям аппаратуры и применяемому режиму.

 

Преобразование DIB в DDB

 

Для этого надо воспользоваться функцией:

HBITMAP CreateDIBitmap (hDC, lpDibInfoHdr, dwInit, lpImage, lpDibInfo, nColorUse);

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

Параметр hDC задает контекст устройства, с которым будет совместим создаваемый битмап.

Параметр lpDibInfoHdr является указателем на структуру BITMAPINFOHEADER (BITMAPCOREHEADER), а lpDibInfo — на структуру BITMAPINFO (BITMAPCOREINFO). Так как BITMAPINFO начинается с заголовка BITMAPINFOHEADER, то оба указателя обычно одинаковы.

Параметр dwInit указывает, надо ли осуществлять инициализацию изображения обычного битмапа данными изображения DIB. Если надо, то он должен быть равен CBM_INIT, иначе 0. Нулевое значение dwInit применяется только если битмап создается в несколько приемов: сначала создается битмап как объект GDI, а затем на него переносится изображение.

Параметр lpImage указывает на данные изображения DIB, а nColorUse задает тип таблицы определения цветов.

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

int SetDIBits (hDC, hBmp, nStartScan, nCountScan, lpImage, lpDibInfo, nColorUse);

Параметр hDC задает контекст устройства, а hBmp — обычный битмап, который инициализируется этой функцией. Надо следить, что бы данный битмап не был выбран в контекст устройства в момент вызова функции SetDIBits.

Параметры nStartScan и nCountScan задают переносимую за одну операцию полосу независимого от устройства битмапа. С помощью этих параметров можно разбить перенос одного большого битмапа на несколько операций, аналогично функции SetDIBitsToDevice.

Параметр lpImage указывает на буфер данных, lpDibInfo является указателем на структуру BITMAPINFO, содержащую заголовок и таблицу определения цветов, а nColorUse указывает на тип применяемой таблицы определения цветов (обычно DIB_RGB_COLORS).

Функция возвращает число перенесенных этой операцией строк развертки.

Использовать зависимый от устройства битмап вместо DIB имеет смысл при многократном отображении битмапа, например, если битмап отображается в окне: в этом случае перерисовка будет осуществляться при обработке каждого сообщения WM_PAINT. Типичный пример использования зависимого битмапа для отображения приведен ниже. В этом примере предполагается, что:

в созданном окне будет отображаться битмап, находящийся в файле с именем C:\TEST\MY.BMP

используются распаковщики сообщений из windowsx.h

для загрузки битмапа из файла применяется функция LoadDIBfromFile, приведенная на странице 52, а для освобождения занятых им ресурсов — функция FreeDIB (см. страницу 53)

Загрузка битмапа осуществляется однократно при создании окна (при обработке сообщения WM_CREATE, в примере — в функции Cls_OnCreate), тогда же DIB преобразуется в зависимый от устройства и, так как он больше не нужен, уничтожается. Хендл зависимого от устройства битмапа сохраняется в структуре описания окна, в двойном слове со смещением 0 (см. функции GetWindowLong и SetWindowLong).

Далее, при необходимости перерисовать битмап (сообщение WM_PAINT, функция–обработчик Cls_OnPaint) зависимый от устройства битмап отображается с помощью функции BitBlt.

Когда окно закрывается (сообщение WM_DESTROY, функция Cls_OnDestroy) находящийся в памяти зависимый от устройства битмап уничтожается, так как все занятые ресурсы GDI должны быть обязательно освобождены.

// включаемые файлы и описание структур см. в примере на странице 52

HBITMAP ConvertDIBtoDDB (LP_DIB lpDib)

{HDC hdc;

HBITMAP hbmp;

// для преобразования DIB в обычный битмап нужен контекст устройства,

// на котором будет осуществляться отображение (окно, дисплей, принтер)

hdc = GetWindowDC (NULL); // используем контекст всего дисплея

// создаем зависимый битмап и запоминаем его хендл

hbmp = CreateDIBitmap (

hdc, lpDib->lpDibHdr, CBM_INIT, lpDib->lpImage,

 (LPBITMAPINFO) (lpDib->lpDibHdr), DIB_RGB_COLORS);

ReleaseDC (NULL, hdc); // освобождаем контекст дисплея

return hbmp;}

BOOL Cls_OnCreate (HWND hwnd, LPCREATESTRUCT lpCreateStruct)

{_DIB dib;

// загружаем битмап из файла

if (LoadDIBfromFile (&dib, "C:\\TEST\\MY.BMP")) {

// создаем зависимый битмап и запоминаем его хендл

// предположим, что при регистрации класса окон мы зарезервировали

// 4 байта в структуре описания окна; там мы сохраним хендл DDB,

// который будет отображаться в окне.

SetWindowLong (hwnd, 0, (LONG)ConvertDIBtoDDB (&dib));

FreeDIB (&dib); // освобождаем память, занятую DIB}

return TRUE;}

void Cls_OnPaint (HWND hwnd)

{PAINTSTRUCT ps;

BITMAP bmp;

HBITMAP hBmp;

BeginPaint (hwnd, &ps);

// получаем хендл битмапа и узнаем его характеристики

hBmp = (HBITMAP)GetWindowLong (hwnd, 0);

GetObject (hBmp, sizeof (bmp), &bmp);

// создаем совместимый контекст и выбираем в него битмап

hCDC = CreateCompatibleDC (ps.hdc);

SelectBitmap (hCDC, hBmp);

// отображаем битмап в окне

BitBlt (ps.hdc, 0,0, bmp.bmWidth,bmp.bmHeight, hCDC, 0,0, SRCCOPY);

// удаляем совместимый контекст (битмап при этом сохранится)

DeleteDC (hCDC);

EndPaint (hwnd, &ps);}

void Cls_OnDestroy (HWND hwnd)

{HBITMAP hBmp;

// получаем хендл битмапа

hBmp = (HBITMAP)GetWindowLong (hwnd, 0);

if (hBmp) {

// если битмап существует, удаляем его

DeleteBitmap (hBmp);

SetWindowLong (hwnd, 0, 0L);}}


Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...