Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторный практикум «Основы разработки приложений Windows» книга 2.DOC
Скачиваний:
91
Добавлен:
10.05.2014
Размер:
827.9 Кб
Скачать

5. Вывод растровых изображений

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

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

Процедура вывода растрового изображения

Имеется несколько возможностей хранения исходных растровых изображений:

  • в файлах с расширением .BMP, создаваемых обычно с помощью того или иного графического редактора, например пакетаCorelDrawотCorelCorporation, встроенной в Windows программыPaintили одного из универсальных редакторов ресурсов, входящих в пакеты сред программирования Borland C++,VisualC++ и др.; файл можно также получить путем сканирования фотографии с переводом результата в формат .BMP;

  • в файле ресурсов в виде таблиц чисел, которые можно получить с помощью того же редактора ресурсов;

  • непосредственно в полях данных приложения в виде массивов целых чисел.

Обычно используется первый вариант. Если исходное изображение хранится в файле .BMP, то загрузить его в память можно двумя способами. Первый требует использования файла ресурсов, в котором должно быть предложение, описывающее файл с изображением:

pict BITMAP "apple.bmp"

На имя этого ресурса (pictв данном примере) программа будет ссылаться при загрузке изображения в память. Как известно, при компиляции проекта, в который входит файл ресурсов, фактически выполняются две операции компиляции: исходного текста программы с образованием объектного файла с расширением .OBJ, и файла ресурсов с образованием второго промежуточного файла с расширением .RES. Этот файл содержит изображение практически в том же виде, что и исходный файл .BMP. Далее файлы .OBJи .RESобрабатываются компоновщиком, который объединяет файлы .OBJи .RESи создает загрузочный файл .EXE, готовый к выполнению. Ресурсы (не только изображения, но и описание диалогов, меню, текстовых строк и проч.) сохраняются в файле .EXEв специальном формате, понятном редактору ресурсов. Это дает возможность редактировать ресурсы в файле .EXE, не имея исходного текста программы.

Для того чтобы изображение можно было вывести на экран, оно должно находиться не в файле, а в памяти. Загрузка изображения-ресурса из файла .EXEв память осуществляется в программе вызовом функцииLoadImage(). После этого программа может при­ступить к процедуре вывода изображения в окно. Отметим, что в этом случае для выполнения программы файл .BMPуже не нужен; изображение хранится в загрузочном файле, который в силу этого может иметь значительный размер.

Другой способ загрузки изображения в память не требует наличия файла ресурсов; загрузка изображения осуществляется той же функцией LoadImage()непосредственно из файла .BMP. Однако в этом случае приложение может выполняться, только если ему доступны все необходимые файлы с рисунками, поскольку в загрузочном файле рисунков нет. Легко сообразить, что именно такая методика используется в программах, позволяющих просматривать рисунки, хранящиеся на дисках. Оба описанных способа схематически изображены на рис. 5.1.

Рис. 5.1. Загрузка растрового изображения в память: а – с помощью файла ресурсов, б –непосредственно из файла .BMP

Область памяти, куда загружается изображение, должна иметь особую организацию, совместимую с представлением на экране окна приложения. Такая память называется совместимой (compatible), и функцияLoadImage(), загружая изображение из файла, одновременно создает область совместимой памяти соответствующего изображению размера. После этого нам остается только скопировать изображение из совместимой памяти в окно приложения, для чего предусмотрена функцияBitBlt()(отBitblocktransfer, блочная передача битов). Эта функция отличается высокой эффективностью, обеспечивая быстрый вывод на экран даже больших изображений. Как правило, копирование изображения из совместимой памяти в окно осуществляется в ответ на сообщениеWM_PAINT, поскольку только в этом случае обеспечивается правильное восстановление содержимого окна после его затирания.

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

Таким образом, для вывода на экран (точнее, в окно приложения) растрового изображения в памяти должны иметься три объекта:

  • совместимая память, в которой находится изображение;

  • обычный контекст устройства, посредством которого мы обращаемся к окну и выводим в него те или иные графические элементы;

  • совместимый контекст, связанный с совместимой памятью, посредством которого мы обращаемся к этой памяти и забираем из нее находящееся в ней изображение.

Все эти объекты схематически изображены на рис. 5.2 вместе с функциями Windows, служащими для создания этих объектов или работы с ними.

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

HBITMAP hBitmap = (HBITMAP)LoagImage

(hInstance, "pict", IMAGE_BITMAP, 0,0,0);

Здесь hInstance– дескриптор экземпляра приложения, передаваемый в программы через первый параметр функцииWinMain(), аpict– имя нашего ресурса в файле ресурсов. Последний параметр функции предназначен для указания флагов загрузки, которые в данном случае не нужны, а два параметра перед ним позволяют задать размеры создаваемой совместимой памяти. При нулевых значениях этих двух параметров выделяется столько памяти, сколько требуется для хранения изображения.

Рис. 5.2. Процедура вывода растрового изображения

Функция LoadImage()позволяет загружать не только растровые изображения, но также курсоры и пиктограммы. Поскольку дескрипторы этих графических объектов принадлежат к разным типам данных (HBITMAP,HCURSORиHICON), возвращаемое функцией значение следует преобразовать в тип загружаемого объекта. В нашем случае это типHBITMAP.

Во втором варианте, когда файл ресурсов отсутствует, и изображение загружается непосредственно из файла .BMP, функцияLoadImage()используется в следующем формате:

HBITMAP hBitmap = (HBITMAP)LoagImage

(NULL,"apple.bmp", IMAGE_BITMAP, 0,0, LR_LOADFROMFILE);

Здесь вместо дескриптора экземпляра приложения указывается NULL, а вместо имени ресурса – имя самого файла с изображением. Кроме того, необходимо указать флагLR_LOADFROMFILE, определяющий загрузку из файла. Как и ранее, возвращаемое значение следует явно преобразовать в типHBITMAP.

Для работы с совместимой памятью необходимо иметь совместимый контекст устройства. Он создается с помощью функции CreateCompatibleDC():

HDC hdcMem = CreateCompatibleDC(hdc):

Обычно совместимый контекст создается в функции OnCre­ate(); необходимый для этого контекст окнаhdcв этом случае может быть получен с помощью функцииGetDC().

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

Выбор дескриптора совместимой памяти в совместимый контекст осуществляется вызовом макроса SelectBitmap()(или обобщенной функцииSelectObject()):

SelectBitmap(hdcMem,hBitmap);

Собственно вывод изображения в окно приложения осуществляется, как уже отмечалось, функцией BiBlt(), вызов которой в общем виде можно записать следующим образом:

BitBlt(hdc,x,y,w,h,hdcMem,x0,y0,ROP);

Параметры hdcиhdcMemпредставляют собой дескрипторы контекстов приемника и источника копируемого изображения. В данном случае мы копируем из совместимой памяти (дескрипторhdcMem) в окно приложения (дескрипторhdc).

Параметры xиyзадают положение копии в окне-приемнике (от начала рабочей области окна), а параметрыwиh– размер копируемой части изображения. Еслиwилиhменьше размеров изображения, в окно скопируется только его часть. Параметрыx0иy0определяют координаты начальной точки копирования в изображении-источнике. Наиболее естественно положитьx0=y0=0, чтобы скопировать изображение целиком от самого его начала, но можно и вырезать из исходного изображения любую прямоугольную область.

Функция BitBlt()позволяет не только выводить в окна приложения нарисованные заранее растровые изображения, но и закрашивать область копирования, а также выполнять над битами изображения и битами области копирования ряд логических операций (НЕ, ИЛИ, И и ряд более сложных). С их помощью можно, в частности, стирать выведенное ранее изображение. Вид операции, выполняемой над изображением (вид растровой операции), определяется значением последнего параметраROPфункцииBitBlt(). При выводе в окно статических изображений используется операция простого копирования и параметрROPимеет значениеSRCCOPY(sourcecopy, копирование источника). При выводе движущихся изображений, когда перед выводом изображения на новое место надо сначала стереть старое изображение, используются и другие растровые операции.

Функция BitBlt()требует указания размеров изображения. Для получения характеристик графических объектов Windows предусмотрена функцияGetObject(), которая возвращает информацию о запрошенном объекте в соответствующую этому объекту структуру. Для объекта-растра используется структура типаBITMAP. ЭлементbmWidthэтой структуры принимает значение ширины изображения, а элементbmHeight– его высоты. Эти значения можно затем использовать при вызове функцииBitBlt():

BITMAPbm;//Переменная для характеристик объекта

HBITMAPhBitmap=(HBITMAP)LoadImage(...);//Загрузка растра

GetObject(hBitmap,sizeof(BITMAP),&bm);//Получение

//характеристик объекта

BitBlt(hdc,10,20,bm.bmWidth,bm.bmHeight,hdcMem,0,0,SRCCOPY);

В приведенном примере все изображение копируется в окно со сдвигом от начала окна на 10 пикселов по горизонтали и 20 по вертикали.