4.4.6 Заполнение областей экрана.

  Тщательное  обдумывание  позволяет  исключить  много  излишней
медлительности, которая свойственна  многим программам заполнения
областей  для графического экрана.  Когда заполнение основано  на
простых  вычислениях,  которые  действуют  по  очереди для каждой
точки,  то требуются расходующие много времени битовые  операции.
Более экономный код может определять все ли битовые позиции опре-
деленного  байта  видеобуфера должны иметь один и тот же  цвет  и
когда это условие выполняется, то этому байту присваивается зара-
нее  заготовленное  значение, которое устанавливает все  точки  в
правильный цвет. При этом  нет  необходимости  повторять операции
над  одним  и тем же байтом, каждый раз устанавливая биты  только
для одной из точек, информацию о которой содержит данный байт.
   В [4.3.4] объяснено как создать описание символа в виде матри-
цы  8*8  точек, имеющего требуемый Вам вид.  Хотя  такие  символы
могут выводиться только в  стандартные  символьные позиции, но их
использование  может существенно облегчить  заполнение  графиков.
Образец высвечивающий все 8*8 точек может быть выведен в интерва-
ле нескольких строк и столбцов, заполняя область намного быстрее,
чем это достигается при поточечной зарисовке.  Этот тип графичес-
ких символов может использоваться совместно с точечной  графикой.
Псевдографические символы могут  использоваться  также для вывода
вращающихся или колеблющихся объектов.

   Высокий уровень.

   Бейсик  предоставляет оператор PAINT для заполнения  замкнутой
фигуры произвольной формы.  Вам  необходимо  указать только точку
внутри области, а об остальном позаботится процедура.  Может быть
указан цвет палетты, которым  надо  заполнить  область, например,
PAINT  (100,110),2 заполняет область цветом 2 палетты.   Закраска
ведется начиная от указанной точки до тех пор, пока не встретятся
точки  с цветом, отличающимся от фонового.  Вы можете,  наоборот,
указать цвет границы и закраска  будет  продолжаться во всех нап-
равлениях,  пока не будут встречены точки указанного цвета.   При
такой закраске линии других  цветов,  находящиеся внутри границы,
могут  быть также закрашены.  Код цвета границы следует за  кодом
цвета заполнения, таким образом  PAINT  (100,180),2,3 закрашивает
область цветом 2 до линий цвета 3.  Отметим, однако, что эта про-
цедура не заполняет области,  находящиеся  "за  углом", т.е. если
вдоль   какой-либо  горизонтальной  или  вертикальной  траектории
встретилась точка, имеющая цвет границы, то все последующие точки
вдоль  этой  траектории не заполняются, даже  если  фигура  имеет
причудливую форму и эти точки  принадлежат внутренней части фигу-
ры.  В следующем примере выводятся две перекрывающихся рамки цве-
тами циан и магента, а затем  последняя  рамка  заполняется белым
цветом.   Сегменты  первой рамки, которые попадают в  закрашенную
область также заполняются белым.

100 LINE (50,70)-(270,130),1,B   'рисуем рамку цветом циан
110 LINE (100,30)-(220,170),2,B  'рисуем рамку цветом магента
120 PAINT (101,31),3,2           'заполняем вторую рамку белым


Помните, что команда  LINE  может  сама  заполнить рамку, если Вы
укажете в качестве параметра 'BF', а не 'B'. Смотрите [4.4.5].
   Оператор  PAINT  имеет "орнаментальные"  возможности,  которые
позволяют Вам заполнять  области  указанной  картинкой.  Элементы
орнамента, которые в режиме умеренного разрешения имеют размер  4
точки в ширину и 8 в высоту (8*8  для высокого разрешения) повто-
ряются  по всей указанной области.  Рисунок  описывается  набором
байтов, содержащих цепочку битов  для последовательных рядов эле-
мента  орнамента.  В режиме умеренного разрешения  цепочка  битов
10000011 описывает 4 точки,  первая из которых имеет цвет 2, сле-
дующие 2 - фоновый цвет, а последняя - цвет 3.  Эта цепочка соот-
ветствует числу 131 или &H83 (см.  приложение Б, в котором обсуж-
даются  битовые  операции в Бейсике).  Обращение этой  цепочки  в
11000010 даст 193 (&HC1).  Они  могут  быть  объединены в элемент
орнамента  шириной в 4 точки и высотой в 2 строкой  CHR$(&H83)  +
CHR$(&HC1). В такую строку  могут  включаться до 8 байтов, доводя
высоту  до 8 точек.  Такая строка используется в операторе  PAINT
вместо цвета. Вот вывод квадрата, заполненного описанным орнамен-
том:

100 LINE (100,110)-(150,150),1,B     'рисуем рамку
110 PAINT (125,125),CHR$(&H83)+CHR$(&HC1),1   'заполняем ее

Отметим,  что нерегулярности элемента орнамента могут приводить к
тому, что процедура  PAINT  завершается,  не  закончив заполнения
области.  Бейсик решает эту проблему указанием параметра фона для
оператора PAINT.  Если у  Вас  возникнут  проблемы, обращайтесь к
руководству по Бейсику за деталями.
   Оператор DRAW, позволяющий рисовать сложные линии, также может
заполнять области. Он обсуждается в [4.4.5].  "Текущая точка" (из
которой  будет  рисоваться следующий сегмент линии)  должна  быть
помещена внутрь области, ограниченной  границей указанного цвета.
В строку оператора DRAW надо поместить кодовую букву P, за  кото-
рой должен следовать код цвета закраски и код цвета границы.  Для
вывода  рамки  цветом 1 палетты, а затем ее заполнения  цветом  3
напишите  DRAW  "U10R10D10L10BH1P3,1".  Здесь  первые четыре кода
рисуют  границы  рамки, затем код 'BH' перемещает  текущую  точку
внутрь рамки, не рисуя линии, а затем код 'P' приводит к заполне-
нию  рамки.  Таким образом могут быть заполнены и  более  сложные
формы. Отметим,  что  необязательно  при перемещении точки внутрь
области отменять рисование линии вдоль этого пути. Однако, в этом
случае надо использовать для  этого  сегмента код цвета, отличный
от цвета заполняемой границы.
   Бейсик  имеет  также возможность  заполнения  областей  экрана
заранее подготовленным изображением. Изображение может быть любо-
го размера, может быть выведено в любой позиции экрана и хранится
в массиве. Обычно, изображение создается с помощью всех доступных
средств,  а затем запоминается в массиве оператором GET.   Массив
может быть помещен в  последовательный  файл [5.4.3], из которого
программа может загрузить его и вывести изображение. Оператор GET
перечисляет координаты  левого  верхнего  и  правого нижнего угла
рамки, содержащей изображение, причем сначала идет номер столбца,
а затем номер строки  для  каждой  пары  координат.  Затем должно
следовать  имя массива, которое не заключается в кавычки.  Напри-
мер, GET (80,40)-(120,60),ARRAY3 помещает  все точки, находящиеся


внутри указанной области в массив с именем ARRAY3.
Одномерные  массивы, как и все остальные, должны  быть  предвари-
тельно  описаны оператором DIM.  Массив может содержать  элементы
любой точности.  Для вычисления  требуемых  размеров массива надо
сначала определить сколько байтов потребуется для хранения  изоб-
ражения. Это можно вычислить по  формуле 4 + INT ((x*битовнаточку
+ 7)/8)* y.  Здесь "битовнаточку" равно 1 для высокого разрешения
и 2 - для умеренного  разрешения.  Буквы  x и y относятся к числу
точек вдоль горизонтальной и вертикальной сторон блока  изображе-
ния.  INT обозначает целую часть числа.  Наконец, надо определить
сколько  элементов  массива требуется для хранения данного  числа
байтов.  Каждый элемент занимает  2 байта в целом массиве, но 4 -
для  чисел  с обычной точностью и 8 - для чисел с двойной  точно-
стью.
   Для получения изображения  из  массива  и  вывода его на экран
используйте оператор PUT. Этот оператор требует только координаты
левого верхнего угла области  экрана,  в которую будет выводиться
изображение.   За  координатами должно быть указано имя  массива.
Например, PUT (40,30),ARRAY1 помещает  изображение, левый верхний
угол которого будет находиться в столбце 40 и строке 30. Оператор
PUT может иметь еще и необязательный параметр, определяющий цвет,
которым будет выводиться изображение.  Если этот параметр опущен,
то изображение будет выводиться  точно  в том виде, в котором оно
было  записано  оператором  GET.   Это  эквивалентно  записи  PUT
(40,30),ARRAY1,PSET.  В противном случае имеются некоторые другие
возможности. Если Вы вместо PSET укажете PRESET, то цвет 0 палет-
ты будет заменен на цвет 3 и наоборот, а цвет 1 палетты - на цвет
2 и наоборот.
   Имеются  еще три случая, использующие логические операции AND,
OR или XOR.  Как и PRESET эти  слова могут заменять PSET в приве-
денном примере. Обсуждение этих трех операций смотрите в приложе-
нии Б.  Каждая  операция  включает  сравнение  битов существующей
точки  на  экране с битами точки накладываемого  изображения.   В
режиме высокого разрешения, когда на точку отводится только 1 бит
операция простая. Но в режиме умеренного разрешения, в котором на
каждую точку отводится 2 бита, могут происходить различные транс-
формации цветов.
   AND устанавливает бит только если он был установлен и у  точки
экрана и у точки изображения (взятой из массива).  В режиме высо-
кого  разрешения это означает, что точка изображения появится  на
экране только если  соответствующая  точка экрана уже "включена".
Все остальные точки области будут выключены.  В режиме умеренного
разрешения  операция  производится  над  обоими  битами. Если для
точки  экрана  установка битов 01, а  для  соответствующей  точки
изображения - 10, то оба бита будут сброшены и точка экрана полу-
чит код 00, что соответствует фоновому цвету.
   OR  устанавливает  бит, если он был установлен либо для  точки
экрана, либо для точки изображения.  В черно-белом режиме OR нак-
ладывает  изображение  на существующее изображение на экране.   В
цветном режиме для определения эффекта Вы опять должны прибегнуть
к вычислениям. Комбинация кодов палетты 1(01) и 2(10) дает 3(11),
также как и комбинация 0(00) и 3(11).


   И, наконец, XOR устанавливает  бит,  если из двух сравниваемых
только  один был установлен.  Применение этой операции  для  чер-
но-белого экрана с массивом единиц дает негативное изображение (1
и 1 дает 0, а 1 и 0 - дает 1). В режиме умеренного разрешения эта
операция меняет все цвета. В  результате  получаем наложение двух
изображений.   Но  более важно, что при повторении этой  операции
экран принимает в точности такой же вид, который он имел первона-
чально.  При этом изображение стирается.  Эта техника полезна для
мультипликации, когда над изображением дважды производится опера-
ция XOR в одной позиции, затем в соседней и т.д.

   Низкий уровень.

   Имеется много подходов к написанию процедур заполнения  графи-
ческих объектов. Ни один из них  не является идеальным, поскольку
всегда  имеется конфликт между скоростью работы процедуры и слож-
ностью фигур, которые она может  обрабатывать.  Любая  процедура,
которая заполняет область точку за точкой будет медленной,  неза-
висимо от того, насколько элегантно она реализована.  Имейте вви-
ду,  что почти каждая модифицируемая точка  расположена в  байте,
все точки которого будут изменяться в тот же самый цвет.  Получе-
ние  доступа  к одному и тому же байту с  использованием  сложных
процедур требует существенно больше времени, чем установка целого
байта  за один доступ к ячейке видеобуфера.  Например, поточечная
очистка экрана требует на IBM PC нескольких  секунд при использо-
вании функции BIOS, в то время как прямой доступ в память  произ-
водит эту операцию мгновенно:

      MOV  AX,0B800H     ;ES указывает на буфер экрана
      MOV  ES,AX         ;
      MOV  CX,8192       ;заполняем все байты
      MOV  AX,0          ;в каждый байт пишем 0
      MOV  DI,0          ;DI поочередно указывает на все байты
REP   STOSW              ;повторяем запись 8192 раза

   Многие процедуры заполняют  по  одной  горизонтальной  строке,
проверяя на цвет границы справа и слева. Поскольку строки состоят
из смежных байтов данных, то  надо  поочередно брать байты из ви-
деобуфера  и проверять присутствует ли в них цвет границы.   Если
цвет границы отсутствует, то  можно  заменить  сразу весь байт на
цвет  заполнения.  В противном случае к данному байту применяется
поточечный подход.
   Имеется очень быстрый способ определения  присутствует ли гра-
ничный цвет в данном байте видеобуфера. Предположим, что процеду-
ра ищет цвет 1 палетты в режиме умеренного  разрешения с четырьмя
цветами. Этому цвету соответствует код 01, поэтому сначала запол-
ним весь байт этим кодом: 01010101. Затем используем операцию NOT
для обращения каждого бита, после чего байт примет вид  10101010.
Проделаем операцию  XOR  со  значением  взятым  из видеобуфера; в
результате получим байт, у которого оба бита, относящиеся к одной
точке равны 1 только для  точек,  имеющих  граничный цвет.  Затем
снова используем операцию NOT с тем, чтобы пара битов, относящих-
ся к точке граничного цвета имела  код 00. После этого используем
операцию  TEST для нахождения полей со значением 00.  Если  такое


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

   MOV  AL,ES:[BX]    ;берем байт из видеобуфера
   XOR  AL,10101010B  ;устанавливаем биты для цвета границы
   NOT  AL            ;обращаем биты
   TEST AL,11000000B  ;проверяем биты 7-6
   JZ   FOUND_BOUND   ;переход если граничный цвет
   TEST AL,00110000B  ;проверяем биты 5-4
   JZ   FOUND_BOUND   ;переход если граничный цвет
   TEST AL,00001100B  ;проверяем биты 3-2
   JZ   FOUND_BOUND   ;переход если граничный цвет
   TEST AL,00000011B  ;проверяем биты 1-0
   JZ   FOUND_BOUND   ;переход если граничный цвет
   MOV  AL,FILL_COLOR ;граничного цвета нет, заполняем байт
   MOV  ES:[BX],AL    ;возвращаем байт в видеобуфер
    .
    .
FOUND_BOUND:

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


 

Вы находитесь в разделе: 
Также вам будет интересно:

Добавить коментарий