Воспроизведение не сжатых рисунков
Строки образа рисунка могут храниться в файле в прямом или обратном порядке. В первом случае они расположены по возрастанию номеров, т. е. сначала в файле записаны точки первой строки, затем второй и так вплоть до последней. Во втором случае они расположены по убыванию номеров, т. е. сначала в файле записаны точки последней строки, затем предпоследней и так до первой строки.
Первый способ хранения образа рисунка применяется, например, в файлах, соответствующих стандарту 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 повторяет его выполнение до тех пор, пока не будут построены все строки рисунка.
После выхода из цикла восстанавливаются сохраненные в стеке величины, исходное окно видеопамяти и происходит возврат на вызывающий модуль.