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

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

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

// пусть файл с битмапом уже открыт и его хендл = hFile

union {

BIMAPCOREHEADER bmch;

BITMAPINFOHEADER bmih;

} bmh;

DWORD dwSizeHeader;

memset (&bmh, 0, sizeof (bmh));

if (_lread (hFile, &bmh, sizeof (DWORD)) == sizeof (DWORD)) {

dwSizeHeader = bmh.bmih.biSize - sizeof (DWORD);

if (_lread (hFile, &bmh.bmih.biWidth, dwSizeHeader) == dwSizeHeader) {

// заголовок успешно прочитан, все неопределенные поля обнулены if (bmh.bmih.biSize == sizeof (BITMAPCOREHEADER)) {

// OS/2 битмап, анализируем структуру bmh.bmch

} else {

// Windows битмап, анализируем структуру bmh.bmih}}}

Такой прием позволяет считывать битмапы как формата OS/2, так и формата Windows. С некоторым усложнением он может быть в дальнейшем распространен и на более новые форматы битмапов, появившиеся в Windows–95 и Windows NT 4.0.

Коротко познакомимся с остальными полями структуры BITMAPINFOHEADER: Поля biWidth и biHeight задают размеры битмапа. Похоже, что максимальный размер в 32 767 x 32 767 пикселей показался разработчикам Windows слишком скромным, поэтому для задания размеров используются двойные слова со знаком (до 2 147 483 647 x 2 147 483 647 пикселей). Мне, например, битмап, превышающий 30 тысяч пикселей в ширину или высоту, пока еще не встречался.

Поля biPlanes и biBitCount используются так же, как и в заголовке битмапа OS/2, и имеют такие же значения: biPlanes всегда 1, а biBitCount может быть 1, 4, 8 или 24. Аналогично OS/2, если поле biBitCount имеет значение 24, то таблица определения цветов (палитра) пропущена.

Поле biCompression используется, если битмап представлен в сжатом виде, и в этом случае поле biSizeImage указывает реальный размер изображения в байтах. Если используется несжатый формат битмапа, то допустимо указание 0. Вместо чисел, естественно, используются символы BI_RGB (0), BI_RLE4 (1) или BI_RLE8 (2), в зависимости от используемого алгоритма сжатия (RLE–4 или RLE–8), либо несжатый битмап (BI_RGB). Подробнее об алгоритмах сжатия и анализе сжатых битмапов можно узнать из стандартной документации, например, из сопровождающей компиляторы системы помощи.

Поля biXPelsPerMeter и biYPelsPerMeter указывают на рекомендуемые характеристики устройства, на котором будет отображаться битмап. Они могут использоваться, например, для выбора наиболее адекватного битмапа, если предусмотрено несколько вариантов для разных разрешений. Обычно эти поля задают равными 0. Однако, если создаваемый битмап будет отображаться на каком–либо отличном от дисплея устройстве, то эти поля целесообразно задать соответствующими характеристикам устройства, равно как и размер самого битмапа определять исходя из разрешающей способности устройства. Далее такой битмап может легко обрабатываться программами верстки, которые, обнаружив ненулевое значение этих полей, включат его в макет сразу с такими размерами, как требуется.

При этом возникает небольшой нюанс, связанный с тем, что разрешение устройства возвращается функцией GetDeviceCaps в точках на дюйм, а нам требуется задавать в виде числа точек на метр. Возникает необходимость определить соотношение дюйма и метра. Когда я попробовал иметь дело с величиной 25.4 мм/дюйм, то с удивлением обнаружил, что битмап в макете отображается с некоторой погрешностью. Пришлось экспериментально вычислять значение дюйма, принятое в Microsoft (?!); оказалось, что наиболее точный результат дает величина 25.397 мм/дюйм. Фрагмент программы выглядит примерно так:

LPBITMAPINFOHEADER lpbmih = ...; // получаем указатель на BITMAPINFOHEADER

HDC hDC = ...; // контекст устройства вывода

// при вычислениях можно обойтись длинными целыми вместо плавающей запятой,

// пока разрешающая способность устройства не превышает 4294 точек на дюйм,

// а в ближайшем будущем так и будет.

lpbmih->biXPelsPerMeter = (LONG) (

(GetDeviceCaps (hDC, LOGPIXELSX) * 1000000UL) / 25397UL);

В принципе можно вычислить эти величины и другим способом, например так:

lpbmih->biXPelsPerMeter = (LONG) (

(GetDeviceCaps (hDC, HORZRES) * 1000UL) / GetDeviceCaps (hDC, HORZSIZE));

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

Поле biClrUsed задает количество цветов, задаваемых таблицей определения цветов. Это число может быть меньше, чем число возможных цветов. Если этого поля нет, или его значение 0, то таблица содержит 2, 16 или 256 записей, смотря по количеству бит, отведенных на один пиксель (biBitCount).

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

Информация об используемых битмапом цветах размещается сразу после заголовка битмапа в виде массива от 2 до 256 записей типа RGBQUAD или пропущена вовсе, если битмап представлен в истинных цветах. Структура RGBQUAD отличается от RGBTRIPLE только тем, что она дополнена неиспользуемым байтом до границы двойного слова6.

Аналогично формату OS/2 вводится дополнительная объединяющая структура BITMAPINFO, по смыслу эквивалентная структуре BITMAPCOREINFO.

typedef struct tagBITMAPINFO {

BITMAPINFOHEADER bmiHeader;

RGBQUAD bmiColors[1];

} BITMAPINFO;

Полный размер структуры BITMAPINFO можно определить исходя из размера заголовка (обязательно надо брать значение поля biSize, а не sizeof (BITMAPIFOHEADER)) и размера палитры, вычисляемого с учетом поля biClrUsed:

UINT uSizeDibInfo;

LPBITMAPINFOHEADER lpbmih;

uSizeDibInfo = lpbmih->biSize + (

lpbmih->biClrUsed ? lpbmih->biClrUsed : (

lpbmih->biBitCount > 8 ? 0 : (1

) * sizeof (RGBQUAD);

Теоретически, этот фрагмент кода лишь относительно корректен — поле biClrUsed может отсутствовать в структуре BITMAPINFOHEADER. По идее надо сначала проверить значение поля biSize, и только если поле biClrUsed присутствует в структуре, использовать его значение. Однако этот фрагмент может оказаться совершенно корректным, если осуществлять загрузку заголовка битмапа в специально выделенную для этого структуру BITMAPINFOHEADER, с предварительным обнулением всех полей (примерно так, как в примере на странице 56).

Следует еще раз напомнить, что битмапы с неполным заголовком — современными системами не поддерживаются, так что в принципе не будет ошибки, если посчитать заголовок присутствующим полностью. В то же время битмапы с неполной палитрой — почти типичный случай; например обои Windows–95 часто представлены именно в таком виде, поэтому учитывать возможность задания поля biClrUsed необходимо.

Иногда бывает удобно воспользоваться собственным заменителем структуры BITMAPINFO:

struct {

BITMAPINFOHEADER bmiHeader;

RGBQUAD bmiColors[ 256 + 3 ];

} bitmapheader;

В этой структуре резервируется достаточное пространство для удержания заголовка битмапа и палитры плюс еще некоторая информация (3 дополнительные записи RGBQUAD = 12 байт), о которой будет рассказано ниже, в разделе «Формат Win32 (Windows NT 3.x)».

Определение размера области данных для хранения изображения осуществляется точно также, как и в случае OS/2, за небольшой оговоркой — полученный размер является максимальным. Если используются сжатые битмапы (biCompression равно BI_RLE4 или BI_RLE8), то реальное изображение может оказаться существенно меньшим. Вообще говоря, определение размера сжатого изображения возможно только после того, как это изображение полностью построено — так как возможность сжатия данных и степень сжатия очень сильно зависят от характера самих данных. Таким образом, при выделении пространства под вновь создаваемые битмапы стоит выделять максимально необходимый объем пространства, а при сохранении в сжатом виде этот размер вам вернет GDI, так как собственно сжатие осуществляется именно им.

DWORD dwSizeImage;

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

dwSizeImage = ( (lpbmih->biWidth * lpbmih->biBitCount + 31) >> 3) & ~3L;

dwSizeImage *= lpbmih->biHeight;

Формат Win32 (Windows NT 3.x)

При расширении возможностей битмапов, реализованных в Win32 API (ранние версии Windows–95, Windows NT 3.x) удалось обойтись без изменения размера заголовка битмапа; изменения коснулись только способов задания некоторых полей и описания цветов. Всего можно перечислить несколько новшеств:

перечисление строк развертки как снизу–вверх, так и сверху–вниз;

добавление двух новых цветовых форматов: 16 и 32 бита на пиксель (так называемые HiColor);

в случае форматов 16 и 32 бита на пиксель новый способ описания цветов — вместо палитры задаются маски цветов.

Рассмотрим эти новшества подробнее.

Во–первых, для того, что бы разобраться в том, какой порядок перечисления строк развертки используется, надо обратить внимание на поле biHeight. Если строки развертки перечисляются сверху–вниз, то это поле будет представлено отрицательной величиной. В связи с этим при определении размеров изображения необходимо использовать абсолютную величину поля biHeight.

DWORD dwSizeImage;

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

dwSizeImage = ( (lpbmih->biWidth * lpbmih->biBitCount + 31) >> 3) & ~3L;

dwSizeImage *= abs (lpbmih->biHeight); // 1

Во–вторых, новые цветовые форматы (16 и 32 бита на пиксель) первоначально (Windows NT 3.x) требовали нескольких одновременных изменений в битмапе:

палитра отсутствует, так как изображение сохраняется практически в истинных цветах (даже 16 бит на пиксель дает возможность описать 65 536 разных цветов);

вместо палитры записываются три двойных слова, представляющего соответственно маски красной, зеленой и синей компонент (эти маски позволяют GDI разобраться, какие биты в 16ти или 32х битовом номере цвета передают соответствующую компоненту цвета);

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

Все три изменения осуществлялись одновременно и были обязательны для HiColor битмапа. Однако по мере развития в этот формат были внесены некоторые изменения. Так, существенно упрощенный GDI в Windows–95 потребовал задания фиксированных масок цветов, работать как в Windows NT с произвольными масками было чересчур сложно7.

В Windows–95 разрешено применять следующие маски цветов:

Формат

Красный

Зеленый

Синий

16 бит/пиксель, 5–5–5 (32 768 цветов):

0x00007C00L

0x000003E0L

0x0000001FL

16 бит/пиксель, 5–6–5 (65 536 цветов) 8:

0x0000F800L

0x000007E0L

0x0000001FL

32 бит/пиксель, 8–8–8 (16 777 216 цветов):

0x00FF0000L

0x0000FF00L

0x000000FFL

Таким образом для 16ти и 32х битовых битмапов появились стандартные маски цветов, которые будут использоваться по умолчанию, если в самом битмапе эти маски не определены; в этом случае поле biCompression задается равным BI_RGB, а не BI_BITFIELDS. Теперь режим BI_BITFIELDS не обязательно должен устанавливаться для 16ти и 32х битовых битмапов, он используется только в том случае, если заголовок битмапа содержит маски.

Если маски присутствуют, то они перечисляются сразу за заголовком битмапа (BITMAPINFOHEADER) в приведенном в таблице порядке — красный, зеленый и синий цвета.

Кроме того, в случае 16ти, 24х или 32х бит на пиксель и режима BI_RGB появилась возможность задавать палитру (поле biClrUsed должно быть ненулевым — палитра для максимально допустимого числа цветов в этих форматах чересчур громоздка). Смысл включения палитры теперь связан не с необходимостью задавать соответствие номеров цветов реальным цветам, а с возможностью оптимизировать процесс отображения битмапа, задавая рекомендуемую для него палитру. Это реально может иметь место при воспроизведении HiColor или TrueColor битмапов на устройствах, поддерживающих палитру — для повышения качества цветопередачи такому устройству целесообразно назначить палитру, оптимизированную для этого битмапа. Если этого не сделать, то все множество цветов битмапа будет приводится к той палитре, которая уже используется устройством — скорее всего это будет системная палитра.

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

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

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

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