Графические устройства

         

Воспроизведение не сжатых рисунков

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

Последовательность расположения строк в файле определяет логику работы с их адресами при воспроизведении образа рисунка на экране. В данном разделе мы рассмотрим построение рисунков, у которых строки расположены в файле, или в оперативной памяти, в естественном порядке. При этом работа с адресами наиболее проста. Такой порядок расположения строк используется не только в большинстве стандартов, но и при сохранении в оперативной памяти или восстановлении из нее содержимого видеопамяти.



Построение рисунка небольшого размера. Важной характеристикой, влияющей на выбор варианта построения рисунка, является его размер. В первую очередь нас будут интересовать такие рисунки, образ которых помещается в одном сегменте оперативной памяти, т. е. их размер не превышает 65 536 байт. Этому требованию удовлетворяет большинство рисунков, предназначенных для оформления рабочей области экрана. В частности, стандартные пиктограммы занимают на экране квадрат размером 32x32 точки.

Текст подпрограммы, выполняющей построение рисунка, образ которого целиком помещается в одном сегменте оперативной памяти, а строки расположены в естественном порядке, приведен в примере 3.21. Перед обращением к подпрограмме должно быть установлено окно видеопамяти, содержащее левый верхний угол рисунка, а адрес этого угла указан в регистрах es:di. Адрес начала образа рисунка в оперативной памяти задает пара fs:si. В регистрах dx и сх указываются ширина и высота рисунка.

Пример 3.21. Работа с прямоугольной областью небольшого размера

draw:
PushReg
<di, si, cx,b>
;,Cur win>; сохранение исходных величин
mov
bx, horsize
; копируем в bx значение horsize
sub
bx, dx
; и вычитаем из него ширину рисунка
drwout:
push
ex
сохраняем счетчик повторов
mov
ex, dx
задаем размер строки рисунка
call
drawline
! ! или call bp, пояснения в тексте
pop
ex
восстанавливаем счетчик повторов
add
di , bx
адрес начала следующей строки
jnc
@F
-> адрес в пределах сегмента
call
NxtWin
установка следующего окна
@@:
loop
drwout
управление повторами цикла
PopReg
<Cur win,bx,
cx,si,di>; восстановление исходных величин
call
setwin
восстановление исходного окна
ret
возврат из подпрограммы

Построение рисунка отличается от закрашивания прямоугольной области тем, что код каждой выводимой точки выбирается из оперативной памяти, а не их регистра-аккумулятора. Поэтому тексты примеров 3.13 и 3.21 различаются только именем подпрограммы, которая вызывается в цикле построения: horiine в примере 3.13 и drawiine в данном случае.

Выполнение примера 3.21 начинается с сохранения в стеке тех величин, которые могут измениться в процессе построения. Затем две команды формируют константу для переадресации строк. Ее назначение обсуждалось в разделе 3.2.2 перед описанием примера 3.13.

Цикл построения рисунка имеет имя drwout. Он начинается с сохранения в стеке значения счетчика повторов (регистра сх) и записи в него размера строки. Затем происходит вызов подпрограммы drawiine для вывода на экран очередной строки рисунка. После возврата из подпрограммы восстанавливается сохраненное в стеке значение счетчика повторов и вычисляется адрес начала следующей строки. Если при сложении будет получен признак переполнения, то произойдет обращение к подпрограмме Nxtwin для установки следующего окна видеопамяти. Последняя команда цикла loop повторяет его выполнение до тех пор, пока не будут построены все строки рисунка.

После выхода из цикла восстанавливаются сохраненные в стеке величины, исходное окно видеопамяти и происходит возврат на вызывающий модуль.

Выбор вспомогательной подпрограммы

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

Лучше всего его задавать в регистре Ьр, в виде адреса нужной подпрограммы, а в тексте примера 3.21 вместо команды call drawiine записать call bp, как это указано в комментарии. Если вспомогательные подпрограммы
включены в текст задачи, то для формирования адреса используется команда lea, например:

lea bp, drawline ; для рисования 256-цветных рисунков
lea bp, drwlin4 ; для рисования 16-цветных рисунков
lea bp, drwlinl ; для рисования двухцветных рисунков
lea bp, horline ; для закрашивания прямоугольной области

Таким образом, мы получили универсальную процедуру, позволяющую:

  • закрашивать прямоугольные области произвольного размера;
  • рисовать рисунки небольшого размера;
  • сохранять в оперативной памяти содержимое прямоугольной области;
  • восстанавливать сохраненное ранее содержимое прямоугольной области.

При рисовании, сохранении или восстановлении содержимого видеопамяти прямоугольная область может содержать не более чем 65 536 точек. По существу это единственное ограничение описанной процедуры. Вы можете составить подпрограммы для более сложных манипуляций со строками небольших рисунков. При этом должно соблюдаться только одно требование — по расположению параметров в регистрах они должны быть совместимы с описанными выше.

Особенности работы с большими рисунками

Большие рисунки не помешаются в одном сегменте оперативной памяти, и их приходится считывать и выводить на экран по частям. В этом случае при построении основное время затрачивается не на рисование строк, а на чтение данных из файла в оперативную память. Очевидно, что чем больше размер порции данных, считываемых за одно обращение к файлу, тем меньше повторных обращений к процедуре чтения и тем быстрее будет построен рисунок. Стандартные средства DOS, например функция 3Fh прерывания int 2ih, позволяют прочитать за одно обращение к диску от 1 до 65 535 байт. Однако считывать каждый раз по 65 535 байтов не рационально, и вот почему.

Размер считываемой порции

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

Чтобы узнать его, надо число 65 535 разделить на размер строки рисунка. После деления частное умножается на размер строки, в результате получается размер порции для чтения в байтах. Последняя порция данных наверняка окажется меньшего размера и это надо учесть при построении рисунка.

Новые переменные

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

SwpOf fs

         
SwpOf fs

         

         

Содержание раздела