Работа с фрагментами изображений




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

ImageSize(X1, Y1, X2, Y2: Integer): Word;

Возвращает размер памяти в байтах, необходимый для сохранения прямоугольной области экрана. Прямоугольник определяется координатами левого верхнего (X1, Y1) и правого нижнего (X2, Y2) углов. Эта функция обычно используется совместно с процедурой GetMem. {451}

Записать изображение в буфер можно, используя процедуру

GetImage (Х1, Y1, Х2, Y2: Integer; VAR BitMap)

в которой параметры X1, Y1, X2, Y2 имеют то же значение, что и в ImageSize, а вместо бестипового параметра BitMap должна подставляться переменная-буфер, занимающая область памяти размера, необходимого для полного сохранения изображения (т.е. равного значению ImageSize). Отметим, что максимальный размер сохраняемого изображения не должен превышать 64K.

Процедура

PutImage(X1, Y1: Integer; VAR BitMap; Mode: Word)

восстанавливает изображение из буфера BitMap в прямоугольник, левый верхний угол которого определен координатами (X, Y). Обратите внимание на то, что в отличие от процедуры GetImage здесь нужна всего одна точка. Объясняется это тем, что в структуре BitMap первые два слова (четыре байта) содержат ширину и высоту в пикселах запомненного изображения. Наиболее интересным в этой процедуре является возможность определять режим вывода изображения: можно суммировать изображение на экране и изображение в буфере, можно уничтожать изображение, находящееся в определяемой области, можно инвертировать изображение, содержащееся в буфере. Эти операции задаются параметром Mode, для которого в модуле Graph определены константы, уже названные при описании процедуры SetWriteMode. Напишем их еще раз:

CONST

CopyPut =0; { операция MOV (замещение) }

XORPut =1; { операция XOR }

ORPut = 2; { операция OR }

ANDPut = 3; { операция AND }

NOTPut = 4; { операция NOT }

В фигурных скобках написаны операторы ассемблера, которыми реализуется соответствующий алгоритм.

Например, если в режиме ORPut на малиновый цвет изображения (номер 5, двоичная запись 0101) вывести бирюзовый (номер 3, 0011) из буфера, то результирующая картинка будет светло-серого цвета (номер 7, 0111). Из этих пяти режимов самым интересным является XOR, поскольку проведенные последовательно две операции XOR с одинаковым вторым аргументом оставляют первый из них без изменений. Это свойство операции XOR и используется в тех случаях, когда необходимо изобразить некий подвижный объект на сложном {452} фоне: два раза выведя один и тот же фрагмент в одно и то же место в режиме XOR, мы оставим фон неизменным. Фактически, мы таким образом экономим память ПЭВМ — не нужен буфер для запоминания участка фона, находившегося под новой картинкой (рис. 19.29).

USES Graph, CRT; { используются Graph и CRT } {$I initgraf.pas} { процедура инициализации } CONST r = 10; { радиус подвижного шарика } VAR X1, Y1, X2, Y2, sx, sy: Integer; { Переменные для ожи- } maxx, maxy, sxmove, symove: Integer; { вления фрагмента } Size: Word; { размер фрагмента } P: Pointer; { указатель на буфер } BEGIN GrInit; { инициализация графики } maxx:= GetMaxX; { максимальное поле экрана } maxy:= GetMaxY; X1:= maxx div 2 - r; { Координаты области экрана, } Y1 = maxy div 2 - r; {в которой будет нарисован } X2 = Х1 + 2*r; { шарик и которая и будет со- } Y2 = Y1 + 2*r; { храненным фрагментом } sx = Х1; sxmove:= 3; { Начальная точка движения и } sy:= Y1; symove:= -1; { шаг перемещения шарика } SetFillStyle(SolidFill, Red); { выбор типа заливки } PieSlice(X1+r,Y1+r, 0,360, r); { рисование шарика } Size:= ImageSize(X1,Y1,X2,Y2); { фрагмент в байтах } GetMem(P, Size); { размещение буфера } Getlmage(Х1, Y1, Х2, Y2, P^); { фрагмент -> в буфер } SetFillStyle(CloseDotFill, Blue); { тип заливки фона } Bar(50, 50, maxx-50, maxy-50); { фоновая картинка } repeat { Начинается движение шарика: } PutImage(sx, sy, P^, XORPut); { вывод шарика } Delay(12); { пауза для АТ/12МГц } Putlmage(sx, sy, P^, XORPut); { стирание шарика } {ограничения на движение шарика в пределах поля фона: } if (sx<50) or (sx>maxx-50-2*r) then sxmove:= -sxmove; if (sy<50) or (sy>maxy-50-2*r) then symove:= -symove; Inc(sx, sxmove); {Следующая точка появления } Inc(sy, symove); { шарика на экране } until KeyPressed; {... пока не нажата клавиша } FreeMem(Р, Size); { освобождение памяти буфера } CloseGraph { закрытие режима графики } END.

Рис. 19.29 {453}

В приведенном примере продемонстрирован алгоритм мультипликации, применяющий «битовые» методы (используется пересылка битовых массивов процедурами GetImage и PutImage). Скорость движения картинки сильно зависит от разрешения экрана и количества цветов: наибольшая — в режиме CGA 640x200 2 цвета (1 бит на пиксел), наименьшая — в режиме VGA 320x200 256 цветов (8 бит на пиксел). Возникают также некоторые сложности с синхронизацией перемещений и частоты вертикальной развертки монитора.

Обращаем внимание на стандартную связку:

Size:= ImageSize(Х1, Y1, Х2, Y2); { фрагмент в байтах }

GetMem(P, Size); { размещение буфера }

GetImage(Х1, Y1, Х2, Y2, P^); { фрагмент -> в буфер }

...

Putlmage(х, у, P^, xxxPut); { вывод фрагмента(ов) }

FreeMem(P, Size); { освобождение буфера }

организующую хранение динамического фрагмента через переменную P типа Pointer. В вызовах PutImage/GetImage указатель P должен быть разыменован. Динамический буфер для фрагментов всегда предпочтительнее, поскольку сам размер фрагмента зависит от многих условий, и их трудно удовлетворить, используя для буфера статическую структуру.



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2022-11-01 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: