BMP TUT



#Start Contents

Wyswietlanie obrazkow BMP

Jesli przejrzeliscie moj poprzedni kurs zwiazany z grafika, to
umiecie juz cos samodzielnie narysowac.
Ale przeciez w Internecie (i nie tylko) jest tyle ciekawych rysunkow,
nie mowiac juz o tych, ktore moglibyscie stworzyc dla jakiegos
specjalnego celu, np. swojej wlasnej gry. Dlatego teraz pokaze, jak
takie rysunki wyswietlac. Ze wzgledu na prostote formatu, wybralem
pliki typu BMP. Plik, ktory chcecie wyswietlic powinien miec rozmiar
320x200 pikseli w 256 kolorach (jak pamietamy, taki rysunek pasuje
jak ulal do trybu graficznego 13h).
Wszystkie operacje na pliku zostaly juz przez mnie szczegolowo
opisane w jednej z czesci mojego kursu, wiec tutaj nie bedziemy
poswiecac im zbyt wiele uwagi.
Ale przejdzmy wreszcie do interesujacych nas szczegolow.
Powinniscie zaopatrzyc sie w cokolwiek, co opisuje format BMP.
Informacje, z ktorych bede tutaj korzystal, znalazlem w Internecie
(niestety, nie pamietam juz gdzie, ale mozecie poszukac na
Wotsit.org).
A oto naglowek pliku BMP (skladnia jezyka Pascal niestety, info:
"Piotr Sokolowski, 6 maja 1998r"):
(przeskocz opis naglowka)
Type
TBitMapHeader =
Record
bfType : Word; (dwa bajty)
bfSize : LongInt; (cztery bajty)
bfReserved : LongInt;
bfOffBits : LongInt;
biSize : LongInt;
biWidth : LongInt;
biHeight : LongInt;
biPlanes : Word;
biBitCount : Word;
biCompression : LongInt;
biSizeImage : LongInt;
biXPelsPerMeter : LongInt;
biYPelsPerMeter : LongInt;
biClrUsed : LongInt;
biClrImportant : LongInt;
End;

Gdzie:
* bftype - jest to dwubajtowa sygnatura "BM"
* bfsize - czterobajtowy rozmiar pliku
* bfreserved - pole zarezerwowane (0)
* bfoffbits - przesuniecie (adres) poczatku danych graficznych
* bisize - podaje rozmiar naglowka
* biwidth - wysokosc bitmapy w pikselach
* biheight - szerokosc bitmapy w pikselach
* biplanes - liczba planow (prawie zawsze ma wartosc 1)
* bibitcound - ilosc bitow na piksel. Przyjmuje wartosc 1,4,8 lub
24.
* bicompression - sposob kompresji
* bisizeimag - rozmiar obrazka w bajtach. W przypadku bitmapy
nieskompresowanej rowne 0.
* biXpelspermeter, biYpelspermeter - ilosc pikseli na metr
* biclrused - ilosc kolorow istniejacej palety, a uzywanych wlasnie
przez bitmape
* biclrimporant - okresla, ktory kolor bitmapy jest najwazniejszy,
gdy rowny 0 to wszystkie sa tak samo istotne.

Ale spokojnie - nie musicie znac tych wszystkich pol, bo my nie
bedziemy wszystkich uzywac. Scisle mowiac, nie bedziemy uzywac ani
jednego z tych pol!
No to po co to wszystko?
Po to, aby znac dlugosc naglowka pliku (54 bajty), ktory ominiemy
przy analizie pliku.
Po naglowku idzie paleta 256 kolorow * 4 bajty/kolor = kolejny 1kB.
Jesli macie jakies watpliwosci co do tego 1 kilobajta, to slusznie.
Oczywiscie, do opisu koloru wystarcza 3 bajty (odpowiadajace kolorom
czerwonemu, zielonemu i niebieskiemu - RGB), co daje razem 768
bajtow. Co czwarty bajt nie zawiera zadnej istotnej informacji i
bedziemy go pomijac (zmienna "z").
Zaraz po palecie idzie obraz, piksel po pikselu. Niestety, nie jest
to tak logiczne ustawienie, jak bysmy sobie tego zyczyli. Otoz,
pierwsze 320 bajtow to ostatni wiersz obrazka, drugie 320 -
przedostatni, itd. Dlatego trzeba bedzie troszke pokombinowac.
Zanim jeszcze zaczniemy, nalezy sie przyjrzec, ktorych portow (choc
to samo mozna uzyskac wywolujac odpowiednie przerwanie) i dlaczego
bedziemy uzywac (patrzymy do pliku "ports.lst" w Spisie Przerwan
Ralfa Brown'a):
(przeskocz opis portow)
03C8 RW (VGA,MCGA) PEL address register (write mode)
Sets DAC in write mode and assign start of color register
index (0..255) for following write accesses to 3C9h.
Don't read from 3C9h while in write mode. Next access to
03C8h will stop pending mode immediatly.
03C9 RW (VGA,MCGA) PEL data register
Three consequtive reads (in read mode) or writes (in write
mode) in the order: red, green, blue. The internal DAC index
is incremented each 3rd access.
bit7-6: HiColor VGA DACs only: color-value bit7-6
bit5-0: color-value bit5-0

Czyli najpierw na 3C8h idzie numer rejestru dla danego koloru
(rejestrow jest 256 i kolorow tez), a potem na 3C9h ida trzy wartosci
kolorow: czerwonego, zielonego i niebieskiego, ktorych polaczenie
daje nam zadany kolor.
Ale dobierzmy sie wreszcie do kodu:
(przeskocz program)
; Program wyswietla na ekranie kolorowy rysunek o rozmiarze
; 320x200 w 256 kolorach, umieszczony w pliku.
;
; nasm -O999 -o bmp1.com -f bin bmp1.asm
;
; Autor: Bogdan D., bogdandr (at) op (kropka) pl
;
; na podstawie kodu podpisanego "Piotr Sokolowski",
; napisanego w jezyku Pascal

org 100h

start:
mov ax, 13h
int 10h ; uruchamiamy tryb graficzny 13h - 320x200x256

mov ax, 3d00h ; otwieramy plik tylko do odczytu
mov dx, nazwa_pliku
int 21h

jnc otw_ok

mov ah, 9
mov dx, blad_plik ; wyswietlane, gdy wystapil blad
int 21h

err:
mov ax, 4c01h ; wyjscie z kodem bledu=1
int 21h

otw_ok:
mov bx, ax ; bx = uchwyt do pliku
mov ah, 3fh ; czytanie z pliku
mov cx, 54 ; wyrzucamy 54 bajty naglowka
mov dx, smieci
int 21h
jc err

; wczytywanie palety z pliku:


xor si, si ; indeks do tablicy "paleta"

czytaj_pal:
mov ah, 3fh ; czytanie z pliku
mov cx, 4 ; czytam po 4 bajty - do b,g,r i z.
; ("z" nas nie interesuje)
mov dx, b
int 21h
jc err

; ustawiamy palete:
mov al, [r]
shr al, 2
mov [paleta+si], al ; paleta[si] = [r] / 4

mov al, [g]
shr al, 2
mov [paleta+si+1], al ; paleta[si] = [g] / 4

mov al, [b]
shr al, 2
mov [paleta+si+2], al ; paleta[si] = [b] / 4

add si, 3 ; przejdz o 3 miejsca dalej -
; na kolejne wartosci RGB

cmp si, 256*3 ; sprawdz, czy nie zapisalismy
; juz wszystkich kolorow
jb czytaj_pal

; wysylanie palety do karty graficznej:

xor ax, ax
xor si, si ; SI = indeks do palety

mov dx, 3c8h ; port karty graficznej
wyslij_palete:
out dx, al ; wysylamy numer rejestru,
; wszystkie od 0 do 255

inc dx ; DX = port 3C9h

push ax
; zapisujemy kolorki:
; czerwony, zielony, niebieski.

mov al, [paleta+si] ; AL = czerwony
; (patrz: petla "czytaj_pal")
out dx, al

mov al, [paleta+si+1] ; AL = zielony
out dx, al

mov al, [paleta+si+2] ; AL = niebieski
out dx, al

pop ax

add si, 3 ; przejdz do nastepnych kolorow

dec dx ; DX z powrotem 3C8h

inc ax ; wybierzemy kolejny rejestr koloru
; w karcie graficznej

cmp ax, 256 ; sprawdz, czy juz koniec pracy
jb wyslij_palete

; wczytywanie obrazka:

mov ax, 0a000h
mov ds, ax ; czytaj bezposrednio do pamieci ekranu

mov dx, 64000-320 ; DX = adres ostatniego wiersza

mov cx, 320 ; z pliku czytamy po 320 bajtow

obrazek:
mov ah, 3fh
int 21h ; czytaj 320 bajtow prosto na ekran
jc err

sub dx, 320 ; przejdz do wczesniejszego wiersza
jnc obrazek ; dopoki nie musimy pozyczac
; do odejmowania. Pozyczymy dopiero
; wtedy, gdy DX < 320 - a to sie
; zdarzy dopiero, gdy DX = 0, czyli
; przerobilismy caly obrazek i ekran.
; Wtedy konczymy prace.


; koniec programu:

mov ah, 3eh
int 21h ; zamknij plik
jc err

xor ah, ah
int 16h ; czekamy na klawisz

mov ax, 3
int 10h ; powrot do trybu tekstowego

mov ax, 4c00h
int 21h

; dane:


nazwa_pliku db "rys1.bmp",0
blad_plik db "Blad operacji na pliku!$"

smieci: times 54 db 0
paleta: times 768 db 0
b db 0
g db 0
r db 0
z db 0
kolor db 0

Mam nadzieje, ze kod jest dosc jasny. Nawet jesli znacie asemblera
tylko w takim stopniu, w jakim to jest mozliwe po przeczytaniu mojego
kursu, zrozumienie tego programu nie powinno sprawic Wam wiecej
klopotow niz mnie sprawilo przetlumaczenie go z Pascala.

Spis tresci off-line (Alt+1)
Spis tresci on-line (Alt+2)
Ulatwienia dla niepelnosprawnych (Alt+0)


Wyszukiwarka

Podobne podstrony:
BMP TUT
BMP TUT
DOS BMP TUT
ART121 tut 2
phys tut 08
bmp metadata
BMP 2 dentystyka
phys tut 12
DOS DIOD TUT
SYS TUT
ART121 tut 3
MYSZ TUT
PWR TUT
GRAF TUT
tut?2 sdram vhdl

więcej podobnych podstron