Бiблiотека ASM-86 для перегляду графiки в стандартах BMP та PCX
Змiст
Вступ
1. Постановка задачi
2. Обґрунтування вибору методiв розв’язку задачi
3. Алгоритм програми
4. Реалiзацiя програми
5. Системнi вимоги
Висновки
Використана лiтература
Додаток. Лiстинг програми
Вступ
Тепер комп’ютери вiдiграють у життi людини все бiльшу та бiльш роль. Ранiше, коли ще не було комп’ютерiв, чи вони були мало розповсюдженнi, все робилося вручну. Коли комп’ютери одержали широке розповсюдження, комп’ютер став допомагати людинi, бо вiн може багато операцiй робити набагато швидше, нiж людина.
В наш час дуже популярнi графiчнi редактори, якi дозволяють зберiгати зображення в популярних графiчних форматах. Але iнколи потрiбна невелика програма, яка дозволяє переглядати графiчнi формати. Якщо ви хочете написати програму для зображень строго визначеного формату, щоб вона, наприклад, працювала удвiчi швидше, нiж "Load from..." у PC Paintbrush, то ви повиннi вивчити структуру заголовку та алгоритм стиснення даних для даного формату.
1
. Постановка задачi
2
. Обгрунтування вибору методiв розв’язку задачi
Необхiдно написати, бiблiотеку бiблiотеку, сумiсну з мовою програмування Pascal для перегляду графiки в стандартах: BMP, PCX.
Структура заголовкiв графiки в стандартах BMP та PCX, а також алгоритми розшифрування даних в цих стандартах приводиться в багатьох книжках, тож з вибором алгоритму у мене не виникло нiяких труднощiв.
Формат файлу зображень (. PCX) зображення з рiзним дозволом i рiзною кiлькiстю квiтiв, вам належить коректно iнтерпретувати iнформацiю, що знаходиться в даному заголовку. Частина файлу, що залишилася, iз зображенням складається з закодованих графiчних даних. При кодуваннi використовується простий алгоритм, заснований на методi довгих серiй. Ми залишаємо за собою право змiнювати цей алгоритм iз метою пiдвищення ефективностi упакування даних. Якщо у файлi запам'ятовується кiлька колiрних шарiв, кожен рядок зображення запам'ятовується по колiрних шарах (у загальному випадку червоному-R, зеленому-G, синьому-B i шарую iнтенсивностi-I) за схемою, приведеної нижче:
Рядок зображення 0:
RRR...
GGG...
BBB...
III...
Рядок зображення 1:
RRR...
GGG...
BBB...
III...
Метод кодування полягає в наступному:
<повторювач> = 6 молодшим биткам X<данi> = наступному байту за XІНАКШЕ<повторювач> = 1<данi> = X
Формат заголовка PCX
Змiщений. Позначення Довжина Опис/коментар
0 Manufacturer 1 Постiйний прапор 10 = ZSoft. PCX
1 Version 1 Інформацiя про версiю:
0 = Версiя 2. 5
2 = Версiя 2. 8 з iнформацiєю про палiтру
3 = Версiя 2. 8 без iнформацiї про палiтру
2 Encoding 1 1 = . PCX кодування довгими серiями
3 Bits per pixel 1 Число бiт на пiксел у шарi
4 Window 8 Розмiри зображення (Xmin, Ymin) - (Xmax, Ymax) у пiкселах включно
12 HRes 2 Горизонтальний дозвiл пристрою, що створює
14 VRes 2 Вертикальний дозвiл пристрою, що створює
16 Colormap 48 Набiр колiрної палiтри (див. далi текст)
64 Reserved 1
65 NPlanes 1 Число колiрних шарiв
66 Bytes per Line 2 Число байт на рядок у колiрному шарi (для PCX-файлiв завжди повинне бути парним)
68 Palette Info 2 Як iнтерпретувати палiтру:
1 = кольорова/чорно-бiла,
2 = градацiї сiрого
70 Filler 58 Заповнюється нулями до кiнця заголовка
[XSIZE = Xmax - Xmin + 1] i [YSIZE = Ymax - Ymin + 1].
Потiм обчислите, скiльки байтiв потрiбно для збереження одного незжатого рядка розгорнення зображення:
TotalBytes = NPlanes * BytesPerLine
Вiдзначимо, що оскiльки завжди використовується цiле число байтiв, можливе iснування невикористовуваних даних наприкiнцi кожного рядка розгорнення. TotalBytes показує скiлькох пам'ятей повинне бути доступно для декодування кожного рядка розгорнення, включаючи невикористовувану iнформацiю на правому кiнцi кожного рядка.
Тепер ви можете почати декодування першого рядка розгорнення - прочитайте перший байт даних з файлу. Якщо два старших бiти цього байта рiвнi 1, то залишилися шiсть бiтiв, якi показують скiльки разiв варто повторити НАСТУПНИЙ байт iз файлу. Якщо це не так, то цей байт сам є даними з повторювачем рiвним 1. Продовжуйте декодування до кiнця рядка, ведучи пiдрахунок кiлькостi байтiв, переданих у буфер висновку. Наприкiнцi кожного рядка розгорнення має мiсце зупинка алгоритму кодування, але її не iснує при переходi вiд одного шару до iншого. Коли рядок сформований цiлком, наприкiнцi кожного шару усерединi рядка можливий наявнiсть зайвих даних. Для перебування цього залишку використовуйте значення XSIZE i YSIZE. Якщо данi є багатошаровими, то BytesPerLine показує, де закiнчується кожен шар усерединi рядка розгорнення.
Продовжуйте декодування рядкiв, що залишилися. У файлi можлива наявнiсть зайвих рядкiв з округленням на 8 чи 16 рядкiв.
Опис iнформацiї про палiтру
Інформацiя про палiтру запам'ятовується в одному з двох рiзних форматiв. У стандартному форматi RGB (IBM EGA, IBM VGA) данi запам'ятовуються в 16 трiйках. Кожна трiйка складається з байтiв зi значеннями червоного (Red), зеленого (Green) i синього (Blue) квiтiв. Значення можуть знаходитися в дiапазонi 0-255, i тому необхiдна їхня iнтерпретацiя у формат використовуваного устаткування. Наприклад, на IBM EGA iснують 4 можливих рiвнi RGB для кожного кольору. Оскiльки 256/4 = 64, те нижче приведений список вiдповiдностi колiрних значень i рiвнiв:
Значення Рiвень
0-63 0
64-127 1
128-192 2
193-254 3
Інформацiя про 256-кольорову палiтру VGA
В даний час ZSoft додав можливiсть збереження у файлi зображення PCX палiтри, що перевищує 16 квiтiв. 256-кольорова палiтра форматується й iнтерпретується точно так, як 16-кольорова, природно, за винятком того, що вона довша. Палiтра (число кольорiв x 3 байти довжини) додається в кiнець PCX файлу i їй передує байт iз десятковим значенням 12. Для визначення палiтри VGA BIOS вам досить роздiлити прочитанi значення квiтiв на 4.
Для доступу до 256-кольорової палiтри потрiбно:
1. Прочитати в заголовку поле Version. Якщо воно дорiвнює 5, палiтра повинна бути.
2. Прочитати кiнець файлу i вiдрахувати назад 769 байт. Знайдене вами значення повинне дорiвнювати 12, що вказує на присутнiсть 256-кольорової палiтри.
3
. Алгоритм програми
Алгоритм головної програми:
1. Перехiд в графiчний режим
3. Чекання натиснення клавiшi ENTER.
4. Виклик процедури виводу графiки в стандартi.BMP.
5. Чекання натиснення клавiшi ENTER.
6. Закiнчити програму.
1. Читання заголовку.
2. Аналiз заголовку
3. Читання палiтри
4. Заповнення палiтри
5. Читання даних
7. Кiнець функцiї.
Алгоритм функцiї виводу графiки в стандартi. PCX.
1. Читання заголовку.
2. Аналiз заголовку
3. Читання палiтри
4. Заповнення палiтри
5. Читання даних
7. Кiнець функцiї.
4
Програма написана на мовi ASM-86 з використанням команд процесора 86/286. Вона складається з головної програми, яка написана на мовi програмування Pascal, i з бiблiотеки, написаної на мовi програмування ASM-86, функцiї якої викликаються в головнiй програмi.
LoadPcx(x,y:integer;s:string);
Де x, y – координати початку виводу картини, s – iмя файлу з розширенням PCX.
LoadBmp(x,y:integer;s:string);
Де x, y – координати початку виводу картини, s – iмя файлу з розширенням BMP. Бiблiотека компiлюється за допомогою Turbo Assembler, зв’язується з головною програмою за допомогою TURBO. EXE.
5
. Системнi вимоги
- IBM сумiсний комп’ютер iз мiкропроцесором Intel 80386 або старшим.
- Пам’ять – 640 К i вище
6
. Інструкцiя для користувача
Для демонстрацiї бiблiотеки написана програма, яка виводить на екран графiки в форматi.BMP, . PCX. Для запуску цiєї програми потрiбно в командному рядку набрати loadmy. exe та натиснути Enter. Програма спочатку виведе на екран картину в форматi. PCX, потiм, пiсля натиснення Enter виведе другу картину в форматi. PCX, потiм пiсля натиснення Enter програма завершить свою роботу.
Використана лiтература
I. Криволап. Москва 1997р. ст. 309
4. “Ассемблер для початкiвцiв”М. П. Шукiн. Київ 1980р. ст. 155
6. “Макро Асемблер”К. С. Кропiйко О. Д. Богатирова. Київ – “Наука” 1991р.
7. Електроний довiдник BOOK
8. Електронна документацiя про формати. PCX та.BMP.
Додаток. Лiстинг програми
var graphresult1,graphresult,i:integer; {результат чтения графики}
asm
mov ah,0 {функция установки видеорежема}
mov al,mode {номер режима}
end;
{$L pcx. obj} {подключаем нашу библиотеку}
external;
begin {MAIN}
if paramcount=0 then
begin
setvideo($5f); {устанавливает видеорежим 640x480 256 цветов}
graphresult:=LoadPcx(1,1,'a1. pcx');{вызывает функцию для чтения. PCX
и возвращает результат чтения}
readln; {ждет нажатия Enter}
setvideo($5f);
graphresult1:=LoadBmp(1,1,'a3.bmp');
readln;
setvideo(3); {установка текстового видеорежима}
if graphresult<>0 then writeln('Ошибка чтения a1. pcx');
<>0 then writeln('Ошибка чтения a3.bmp');
end
else {paramcount - количество параметров}
setvideo($5f); {устанавливает видеорежим 640x480 256 цветов}
>0 then
graphresult:=LoadPcx(1,1,paramstr(i)){вызывает функцию для чтения. PCX
с указанным в командной строке именем файла
else
graphresult:=LoadBMP(1,1,paramstr(i));{вызывает функцию для чтения.BMP
и возвращает результат чтения}
if graphresult<>0 then begin
writeln('Ошибка чтения '+paramstr(i));
readln;
end else readln; {ждет нажатия Enter}
end;
readln;
setvideo(3); {установка текстового видеорежима}
end.
Текст бiблiотеки:
. 386 ;разрешение инструкций 386 процессора
model SMALL,PASCAL ;модель памяти SMALL для распределения кода и данных
;и совместимая с паскалем
PUBLIC PASCAL LoadPcx ;Обьявляем общие процедуры
CODESEG
zagpcx db 130 dup(0) ;буфер для заголовков BMP и PCX
nfile db 'a. pcx',100 dup(0) ;буфер для имени файла
flc dw 0 ;индекс файла
x1 dw 0 ;координаты текущей точки
y1 dw 0
x2 dw 0
y2 dw 0
col db 770 dup(0) ;буфер для палитры
yres dw 0 ;размер картинки
xres dw 0
povt db 0 ;повторитель(сколько пикселей нарисовать)
buf db 1024 dup(0) ;буфер для данных
bufsz dw 1024 ;размер буфера данных
bufpos dw 0 ;текущее положение буфера
maxx dw 640
pusha ;сохранение регистров в стеке
mov ax,[maxx] ;проверка на выход за экран
cmp [x1],ax
mov ax,[C1] ;задаем цвет
mov ah,0ch
mov cx,[x1] ;задаем координаты
mov bh,0
int 10h ;вывод точки
@@ex:
popa ;восстановление регистров
ret
ENDP
PROC LoadBmp ;процедура вывода картинки в стандарте BMP
ARG nx:WORD,ny:WORD,file:WORD:2 ;параметры ;адрес строки имени картинки
push ds
mov dx,cs ;установка DS на сегмент кода
mov ds,dx
MASM ;переход в режим MASM
mov ax,[file] ;копирование имени файла
mov bx,ax
mov ax,[file]+2
mov es,ax
IDEAL ;переход в идеальный режим
mov al,[es:bx];
inc bx;
@lpabmp:mov cl,[es:bx];
mov [si],cl;
inc si;
sub al,1;
jnz @lpabmp; ;копирование имени файла в буфер
mov al,0
mov [si],al;
mov ax,3d00h; ;открытиефайла
mov dx,offset nfile;адресименифайла
int 21h;
jnc @lpbbmp;
jmp @lppoorbmp;
@lpbbmp:
mov [flc],ax;сохраняем номер файла
mov dx,offset zagpcx;адрес буфера
mov cx,54; количество байт для чтения данных из файла
mov bx,[flc]; заносим номер файла
mov ax,3f00h; чтение файла
int 21h;
mov bx,offset zagpcx;адрес буфера заголовка
mov ax,[bx];первое слово заголовка
cmp ax,4D42h;проверка на PCX
jz @lpcbmp;
jmp @lppoor1bmp;
@lpcbmp:
@lpdbmp:add bx,18; чтение координат окна картинки
mov ax,[bx];
mov [x1],ax;
add bx,4;
mov [y1],ax;
add bx,4;
add ax,[x1];
mov [xres],ax;
add bx,2;
mov ax,[ny];
add ax,[y1];
mov ax,[nx]; устанавливаем текущую точку в начальную точку
mov [x1],ax;
mov ax,[ny];
mov [y1],ax;
mov [x2],0;
mov [y2],0;
@lpgbmp:
mov cx,768;
mov bx,[flc];
mov ax,3f00h;
int 21h;
mov cx,768;
MASM
@lpfbmp:ror byte ptr [bx],2;деление на 4 всех элементов палитры
IDEAL
inc bx;
sub cx,1;
jnz @lpfbmp;
mov ax,ds;
mov bx,0h;
int 10h; установка палитры
mov bx,offset zagpcx;
add bx,10
mov dx,[bx];
mov ax,4200h;
mov bx,[flc];
int 21h;
@lpibmp:mov bx,[flc];
mov ax,3f00h;
int 21h;
mov [bufpos],0;
@lpxbmp:
push ds
mov bx,offset buf
add bx,[bufpos];
mov ax,[bufpos];
jz @lpibmp;
mov al,[es:bx];
inc [bufpos];
jz @lpkbmp;
mov cl,[povt];
mov ah,0h;
mov [c1],ax;
call putpixel ;выводточки
inc [x1];
cmp ax,[xres];
mov ax,[nx];
mov [x1],ax;
mov [x2],0;
inc [y2];
mov ax,[y2];
dec ax;
jnz @lmcbmp;
jmp @lpokbmp;
@lmcbmp:dec cl;
jnz @lmdbmp;
jmp @lpxbmp;
mov ah,al;
@lpybmp:
mov ah,0h;
mov [c1],ax;
call putpixel; выводточки
inc [x1];
inc [x2];
mov ax,[x2];
dec ax;
cmp ax,[xres];
jnz @lpxbmp;
mov [x1],ax;
mov [x2],0;
inc [y1];
mov ax,[y2];
jnz @lpxbmp;
jmp @lpokbmp;
@lpokbmp:
pop ds
popa; ;восстановление регистров
mov ah,3eh; ;закрытие файла
mov bx,[flc];
@lppoorbmp:
pop ds
@lpubmp:
ret
endp
PROC LoadPcx ;процедура чтения и вывода на экран PCX
ARG nx:WORD,ny:WORD,file:WORD:2 ;адрес строки имени картинки
pusha; ;сохранение регистров
mov dx,cs ;установка сегмента данных равным сегменту кода
mov ds,dx
MASM
mov ax,[file] ;копирование имени файла в буфер
mov ax,[file]+2
mov si,offset nfile
IDEAL
mov al,[es:bx];
inc bx;
@lpa:mov cl,[es:bx];
mov [si],cl;
inc si;
inc bx;
mov [si],al;
mov ax,3d00h; ;открытиефайла
mov dx,offset nfile;адресименифайла
int 21h;
jmp @lppoor;
@lpb:
mov [flc],ax;сохраняем номер файла
mov dx,offset zagpcx;адрес буфера
mov cx,128; количество байт для чтения данных из файла
mov bx,[flc]; заносим номер файла
int 21h;
mov bx,offset zagpcx;адрес буфера заголовка
mov ax,[bx];первое слово заголовка
cmp ax,050ah;проверка на PCX
jmp @lppoor1;
@lpc:add bx,2;
cmp ax,0801h; проверка на 256 цветов
jz @lpd;
jmp @lppoor1;
@lpd:add bx,2; чтение координат окна картинки
mov ax,[bx];
mov [x1],ax;
add bx,2;
mov ax,[bx];
mov [y1],ax;
add bx,2;
mov ax,[bx];
sub ax,[x1];
mov [xres],ax
add bx,2;
sub ax,[y1];
mov [yres],ax ; вычисление размеров картинки
mov ax,[nx];
mov [x1],ax; устанавливаем текущую точку в начальную точку
mov [x2],0;
mov [y2],0;
add bx,55;
mov al,[bx]; проверка
cmp al,01h;
mov bx,[flc];
mov cx,0;
int 21h;
sub ax,769; вычисление начало палитры
sbb dx,0h;
mov cx,dx;
mov dx,ax;
mov bx,[flc];
mov ax,4200h; установка указателя файла на начало палитры
int 21h;
mov dx,offset col;чтение палитры
mov cx,769; количество байт для чтения
mov ax,3f00h;
MASM
cmp byte ptr [bx],0ch; проверка на 256 цветов
jz @lpe;
jmp @lppoor1;
@lpe:inc bx;
mov cx,768;
@lpf:ror byte ptr [bx],2;деление на 4 всех элементов палитры
IDEAL
inc bx ;
sub cx,1;
jnz @lpf;
mov dx,offset col+1;
mov ax,ds;
moves,ax;
mov ax,1012h; установка палитры
mov bx,0h;
mov cx,256;
mov ax,4200h; установка положения указателя файла на 128 от начала
mov cx,0;
mov dx,80h;
int 21h;
mov [povt],0;
@lpi:mov bx,[flc];
mov dx,offset buf ;чтение данных в буфер по блокам (1 Kb).
int 21h;
@lpx:
push ds
pop es
mov bx,offset buf
add bx,[bufpos];
cmp ax,[bufsz]; проверка на конец блока
jz @lpi;
mov al,[es:bx];
inc [bufpos]; увеличение положения буфера
cmp [povt],0; установка повторителя в 0
jz @lpk;
mov cl,[povt]; чтение повторителя
mov [c1],ax; установка цвета точки
@lmd:
inc [x1]; увеличение Х
inc [x2];
mov ax,[x2];
dec ax;
cmp ax,[xres]; сравнение с размерами картинки
jnz @lmc;
mov ax,[nx]; установка X в начальное положение
mov [x1],ax;
mov [x2],0;
inc [y1]; увеличение Y
inc [y2];
mov ax,[y2];
cmp ax,[yres]; сравнение с размерами картинки
jnz @lmc;
jmp @lpok;
@lmc:dec cl;
jnz @lmd;
mov [povt],0; установка повторителя в 0
@lpk:mov ah,al;
and ah,0c0h; проверка на несколько точек
and al,3fh;
mov [povt],al; установка повторителя в кол. точек
jmp @lpx;
mov [c1],ax; установка цвета
call putpixel; вывод точки
inc [x1]; увеличение Х
inc [x2];
mov ax,[x2];
dec ax;
cmp ax,[xres];сравнение с размерами картинки
jnz @lpx;
mov ax,[nx]; установка X в начальное положение
mov [x1],ax;
inc [y1]; увеличение Y
inc [y2];
mov ax,[y2];
dec ax;
cmp ax,[yres]; сравнение с размерами картинки
jnz @lpx;
jmp @lpok;
@lpok:
pop ds
popa; ;восстановление регистров
mov ax,0
jmp @lpu;
mov ah,3eh; ;закрытие файла
movbx,[flc];
int 21h;
@lppoor:
popa; ;восстановление регистров
mov ax,3
@lpu:
ret
endp
END
|