47952 (597372), страница 16

Файл №597372 47952 (Основы графического вывода) 16 страница47952 (597372) страница 162016-07-30СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 16)

return lpDib->uDibFlags ? TRUE : FALSE;}

Следует обратить внимание на то, что в этой процедуре основная часть кода выполняет проверки или связана с несколько избыточным описанием структуры _DIB; в частных случаях вся процедура может свестись к выполнению 3х–4х функций.

По сути близкий к этому случай может быть связан с загрузкой независимых от устройства битмапов из ресурсов приложения. При рассмотрении зависимых от устройства битмапов было отмечено, что функция LoadBitmap, загружающая битмап из ресурсов приложения, возвращает зависимый от устройства битмап, предназначенный для воспроизведения на дисплее. Это может быть неудобно, если битмап должен отображаться, скажем, на принтере. По счастью в ресурсы приложения включается непосредственно независимый от устройства битмап, что позволяет получить к нему доступ с помощью функций FindResource и LoadResource. В результате вы получите указатель на блок памяти, содержащий целиком образ файла битмапа, включая структуру BITMAPFILEHEADER. Останется только вычислить адрес начала данных изображения и адрес информации о битмапе:

// включаемые заголовки и описание структуры _DIB - см. в предыдущем примере

BOOL LoadDIBfromResources (LP_DIB lpDib, HINSTANCE hInstance, LPSTR lpszResName)

{LPBITMAPFILEHEADER lpbmfh;

HRSRC hresDib;

// инициализируем возвращаемые данные:

lpDib->hglbDib = NULL;

lpDib->lpDibHdr = (LPBITMAPINFOHEADER)NULL;

lpDib->lpImage = (LPSTR)NULL;

lpDib->uDibFlags = 0;

// ищем нужный ресурс

hresDib = FindResource (hInstance, lpszResName, RT_BITMAP);

if (!hresDib) return FALSE;

// ресурс найден, получаем его хендл

lpDib->hglbDib = LoadResource (hInstance, hresDib);

if (! (lpDib->hglbDib)) return FALSE;

// получаем указатель на загруженный ресурс

lpbmfh = (LPBITMAPFILEHEADER)LockResource (lpDib->hglbDib);

if (lpbmfh != (LPBITMAPFILEHEADER)NULL) {

// заполняем остальные поля структуры _DIB:

lpDib->lpDibHdr = (LPBITMAPINFOHEADER) (lpbmfh + 1);

lpDib->lpImage = (char FAR*) (lpbmfh) + bmhf.bfOffBits;

lpDib->uDibFlags = DIB_RESOURCE;}

if (lpDib->uDibFlags == 0) {

#ifndef __NT__

FreeResource (lpDib->hglbDib);

#endif

lpDib->hglbDib = NULL;}

return lpDib->uDibFlags ? TRUE : FALSE;}

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

BOOL FreeDIB (LP_DIB lpDib)

{BOOL fResult = FALSE;

switch (lpDib->uDibFlags) {

case DIB_FILE:

if (lpDib->lpDibHdr) GlobalFreePtr (lpDib->lpDibHdr);

fResult = TRUE;

break;

case DIB_RESOURCE:

#ifndef __NT__

if (lpDib->hglbDib) {

UnlockResource (lpDib->hglbDib); // для NT не требуется

FreeResource (lpDib->hglbDib);

// для NT не требуется}

#endif

fResult = TRUE;

break;

default:

break;}

// инициализируем структуру _DIB:

lpDib->hglbDib = NULL;

lpDib->lpDibHdr = (LPBITMAPINFOHEADER)NULL;

lpDib->lpImage = (LPSTR)NULL;

lpDib->uDibFlags = 0;

return fResult;}

Заголовок независимого от устройства битмапа

Непосредственно после заголовка файла битмапа следует информация, описывающая характеристики битмапа — его размеры, количество цветов, используемую палитру, режим сжатия изображения и многое другое. Как уже было отмечено, информация о независимых от устройства битмапах условно делится на две структуры данных: 1) описание самого битмапа и 2) описание используемых битмапом цветов.

В разных версиях Windows были предусмотрены разные форматы описания битмапов, по счастью совместимые снизу–вверх. Имеет смысл обзорно ознакомиться с возможностями битмапов разных версий и изменениями, произошедшими в их описании.

Формат OS/2

В ранних версиях GDI для описания битмапов применялись структуры, совместимые с ранним форматом OS/2. Для описания информации о битмапе применялась структура BITMAPCOREHEADER, а для описания используемых цветов — палитры — массив структур RGBTRIPLE (он необязателен):

typedef struct tagBITMAPCOREHEADER {

DWORD bcSize;

short bcWidth;

short bcHeight;

WORD bcPlanes;

WORD bcBitCount;

} BITMAPCOREHEADER;

typedef struct tagRGBTRIPLE {

BYTE rgbtBlue;

BYTE rgbtGreen;

BYTE rgbtRed;

} RGBTRIPLE;

Сначала рассмотрим структуру BITMAPCOREHEADER, описывающую битмап:

Поле bcSize содержит размер этой структуры (sizeof (BITMAPCOREHEADER)), его значение должно быть равно 12. Поля bcWidth и bcHeight задают размеры данного битмапа. Так как для задания размеров используется целое число со знаком, то максимальный размер битмапа в этого формата равен 32767x32767 пикселей.

Поле bcPlanes указывает количество цветовых планов (плоскостей), используемых битмапом. Его значение для независимого от устройства битмапа всегда должно быть равно 1. Поле bcBitCount указывает количество бит, используемых для задания цвета пикселя. Возможно одно из следующих значений:

1 — монохромный битмап

4 — 16ти цветный битмап

8 — 256ти цветный битмап

24 — битмап в истинных цветах (TrueColor).

Все остальные значения для полей bcPlanes и bcBitCount являются недопустимыми. Если битмап имеет 2, 16 или 256 цветов, то непосредственно после структуры BITMAPCOREHEADER следует палитра (palette) — таблица определения цветов в виде массива из 2, 16 или 256 записей типа RGBTRIPLE. Считается, что изображение такого битмапа содержит логические номера цветов для каждого пикселя, а соответствие логического номера истинному цвету задается соответствующей записью в палитре. Каждая запись RGBTRIPLE задает интенсивности красной (red), зеленой (green) и синей (blue) компонент цвета пикселя, в виде числа от 0 до 255. Таким образом возможно описание 16 777 216 возможных цветов из которых строится палитра, используемая битмапом.

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

Часто для удобства вместо структур BITMAPCOREHEADER и массива записей RGBTRIPLE используют объединенную структуру BITMAPCOREINFO, которая просто описывает в качестве полей структуру BITMAPCOREHEADER и массив из одной записи RGBTRIPLE.

typedef struct _BITMAPCOREINFO {

BITMAPCOREHEADER bmciHeader;

RGBTRIPLE bmciColors[1];

} BITMAPCOREINFO;

Такая структура несколько упрощает доступ к описанию битмапа по указателю: при использовании BITMAPCOREHEADER и RGBTRIPLE необходимо манипулировать с двумя указателями, а при использовании BITMAPCOREINFO достаточно только одного — указывающего на начало заголовка. Например, вместо такого фрагмента кода:

LPBITMAPCOREHEADER lpbmch = ...; // считаем, что указатель на заголовок нам дан

LPRGBTRIPLE lprgbt;

lprgbt = (LPRGBTRIPLE) (lpbmch + 1); // получаем указатель на палитру

// для доступа к полям заголовка используем, например lpbmch->bcWidth

// для доступа к палитре используем, например lprgbt[i].rgbtRed;

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

LPBITMAPCOREINFO lpbmci = ...; // считаем, что указатель на заголовок нам дан

// для доступа к полям заголовка lpbmci->bmciHeader.bcWidth

// для доступа к палитре lpbmci->bmciColors[i].rgbtRed;

Однако использовать структуру BITMAPCOREINFO при загрузке битмапа не слишком удобно, так как ее полный размер может быть различным, смотря по количеству цветов битмапа (причем он может быть либо меньше, либо больше, чем sizeof (BITMAPCOREINFO) и заведомо не равен ему). Его можно вычислить как размер структуры BITMAPCOREHEADER (или значение поля bcSize) плюс размер таблицы определения цветов: нуль, если поле bcBitCount равно 24, или число цветов, умноженное на размер структуры RGBTRIPLE:

UINT uSizeCoreInfo;

LPBITMAPCOREHEADER lpbmch;

uSizeCoreInfo = lpbmch->bcSize + (

lpbmch->bcBitCount==24 ? 0 : (1

Непосредственно вслед за структурой BITMAPCOREINFO следуют собственно данные изображения. Их можно найти в DIB–файле как по значению поля bfOffBits заголовка файла BITMAPFILEHEADER, так и считывая их непосредственно после таблицы определения цветов. Анализируя заголовок битмапа можно определить и необходимый размер области для хранения изображения. Изображение хранится по строкам развертки, в каждой строке для задания цвета пикселя отводится bcBitCount последовательных бит. Полная длина строки выравнивается в сторону завышения до ближайшей границы, кратной двойному слову (в зависимых от устройства битмапах строка выравнивалась до четного размера, а в случае DIB — кратного четырем). Строки развертки перечисляются снизу–вверх. Для вычисления размера изображения можно воспользоваться таким фрагментом:

DWORD dwSizeImage;

LPBITMAPCOREHEADER lpbmch; // считаем, что указатель на заголовок нам дан

dwSizeImage = ( (lpbmch->bcWidth * lpbmch->bcBitCount + 31) >> 3) & ~3L;

dwSizeImage *= lpbmch->bcHeight;

В этом фрагменте выполняются следующие действия: сначала вычисляется длина строки развертки в битах (lpbmch->bcWidth * lpbmch->bcBitCount), далее нам надо получить эту длину в двойных словах (то есть деленную на 32) и округленную в большую сторону; затем пересчитать из двойных слов в байты — умножить на 4. Этот процесс можно несколько ускорить — пересчет в число двойных слов с округлением в большую сторону легко проделать по формуле (x + 31)/32, или, используя более быстрые операции, (x+31)>>5, так как 32 это 25. Далее надо умножить на 4, то есть ((x+31)>>5)*4 = ((x+31)>>5)<<2), или, в окончательном варианте, ((x+31)>>3)& (~3): так как при умножении на 4 (сдвиге влево на 2 бита), младшие 2 разряда будут обнулены, то заменяя деление с умножением на сдвиг вправо, мы должны сбросить два младших бита в 0.

Формат Windows

Достаточно быстро Microsoft решил расширить возможности битмапов, в связи с чем появилась новые версии структур, описывающих битмап: для описания заголовка BITMAPINFOHEADER и для описания палитры RGBQUAD:

typedef struct tagBITMAPINFOHEADER {

DWORD biSize;

LONG biWidth;

LONG biHeight;

WORD biPlanes;

WORD biBitCount;

DWORD biCompression;

DWORD biSizeImage;

LONG biXPelsPerMeter;

LONG biYPelsPerMeter;

DWORD biClrUsed;

DWORD biClrImportant;

} BITMAPINFOHEADER;

typedef struct tagRGBQUAD {

BYTE rgbBlue;

BYTE rgbGreen;

BYTE rgbRed;

BYTE rgbReserved;

} RGBQUAD;

Первое поле структуры BITMAPINFOHEADER — biSize совпадает по назначению и размеру с полем bcSize структуры BITMAPCOREHEADER. Это поле содержит размер структуры, описывающей данный заголовок. Таким образом, анализируя это поле, можно легко определить, какая версия заголовка используется. Однако здесь имеется один подводный камень — в некоторых ранних источниках времен Windows 3.x утверждается, что все поля этой структуры, начиная с поля biCompression, могут быть пропущены. Собственно в документации, сопровождающей компиляторы есть только одно косвенное упоминание об этом: там строго предупреждается, что для определения размера заголовка битмапа надо обязательно использовать поле biSize, а не sizeof (BITMAPINFOHEADER). Таким образом размер структуры BITMAPINFOHEADER может изменяться от 16 до 40 байт; но в любом случае он превышает размер структуры BITMAPCOIREHEADER (12 байт), что позволяет различать заголовки в разных форматах.

На практике мне только один раз встретился битмап с неполным заголовком. Следует заметить также, что в результате проверки оказалось, что все графические пакеты, с которыми я имел дело, отказываются воспринимать такой битмап и сообщают о неверном формате файла; аналогично реагируют на подобные битмапы и современные системы (проверено для Windows–95, Windows–98, Windows NT 4.0). Фактически можно с достаточной надежностью предполагать, что заголовок будет всегда полным. Такое допущение не принесет сколько–нибудь заметных ограничений в использовании битмапов, созданных другими приложениями. Однако в некоторых случаях можно учесть эту особенность практически без усложнения исходного текста; например, чтение заголовка можно представить таким образом:

Характеристики

Тип файла
Документ
Размер
4,85 Mb
Тип материала
Учебное заведение
Неизвестно

Список файлов книги

Свежие статьи
Популярно сейчас
Зачем заказывать выполнение своего задания, если оно уже было выполнено много много раз? Его можно просто купить или даже скачать бесплатно на СтудИзбе. Найдите нужный учебный материал у нас!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
7149
Авторов
на СтудИзбе
253
Средний доход
с одного платного файла
Обучение Подробнее