Program do przeglądania plików BMP w dwóch trybach.

0

Mam do napisania w assemblerze program do przeglądania plików graficznych BMP w dwóch trybach graficznych:

19 - 320x200x256
18 - 640x480x16

Tryb ma się wybierać automatycznie poprzez sprawdzenie ilości kolorów z nagłówka pliku BMP.

http://www.januszg.hg.pl/teksty/budowa_pliku_bmp.html - oto strona na której przedstawiona jest budowa pliku bmp z której wynika, że do sprawdzenia ile kolorów zawiera plik bmp należy pobrać 2 bajty: czyli 55 - 56 bajt.

Więc na samym początku należy zrealizować otwieranie pliku:

@otwieranie:	mov ax, @DATA
	mov ds, ax

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

	jnc	@sprkolory             ;przejscie do procedury spr ilosc kolorow

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


.data
nazwa_pliku	db	'rys1.bmp','$'
blad_plik	db	'Blad operacji na pliku!','$'

Coś z tym otwieraniem pliku jest nie tak, bo od razu wyrzuca komunikat: "Blad operacji na pliku!"
Może znajdziecie błąd?

A teraz jak robić to odczytywanie bitów z nagłówka pliku BMP?

Pozdrawiam

0

Nazwa pliku ma być w formacie ASCIZ :] czyli zamiast :

nazwa_pliku        db        'rys1.bmp','$' 

napisz

nazwa_pliku        db        'rys1.bmp',0 

i jeszcze jedno :

 mov ax, 3d00h
 mov al, 0 

Nie potrzebne jest tutaj MOV al, 0 :) pierwsza linijka już to robi.

0

OK, to już poprawiłem, teraz jak można zrobić odczytywanie bitów z pliku?

0

Z tego co ja wiem ilość bitów na kolor to 28 i 29 bajt :P
czyli odczyt ( po otwarciu ) wygląda tak :

  1. skok to pliku do odpowiedniego bajtu ( funkcja 42h )
  2. Odczytanie dwóch bajtów do bufora ( funkcja 3fh )
0

A tak, rzeczywiście. Zamiast 14 kb dodałem 40 kb nagłówka podstawowego.

Czy to nadaje się do użytku:

	mov	ah, 42h
	mov al, 0			;przesunięcie względem początku pliku
	mov cx, 27			;przejście do 28 i 29 kilobajta zawierającego dane o kolorach
	mov	bx, ax			;bx = uchwyt do pliku
	mov	ah, 3fh			;czytanie z pliku
	mov	cx, 2			;czytanie 2 kilobajtów nagłówka - 16 bajtów
	int	21h

Wynik badania bajtów trzeba będzie porównać z 4 (dla 16 kolorów) i 8 (dla 256 kolorów) potem wybrac tryb...

0

No więc, dobrze jest ten fragment sprawdzający?

0
ZiomPaul napisał(a)

A tak, rzeczywiście. Zamiast 14 kb dodałem 40 kb nagłówka podstawowego.

Czy to nadaje się do użytku:

	mov	ah, 42h
	mov al, 0			;przesunięcie względem początku pliku
	mov cx, 27			;przejście do 28 i 29 kilobajta zawierającego dane o kolorach
	mov	bx, ax			;bx = uchwyt do pliku
	mov	ah, 3fh			;czytanie z pliku
	mov	cx, 2			;czytanie 2 kilobajtów nagłówka - 16 bajtów
	int	21h

Wynik badania bajtów trzeba będzie porównać z 4 (dla 16 kolorów) i 8 (dla 256 kolorów) potem wybrac tryb...

Ja trochę źle ci powiedziałem :P mówiąc 28 bajt miałem namyśli licząc już od zera =P czyli do cx masz podać 28 a nie 27 =] poza tym nie wywołujesz funkcji ustawiającej wskaźnik - zapomniałeś o int 21h ponadto nie wyzerowałeś DX! w drugiej częsci natomiast nie podałeś adresu docelowaego dla danych.

	
 mov ah, 42h
 mov al, 0			;przesunięcie względem początku pliku
 mov cx, 28			;przejście do 28 i 29 kilobajta zawierającego dane o kolorach
 xor  dx, dx
 mov bx, ax			;bx = uchwyt do pliku
 int 21h                           ; wskaznik w odpowiednim miejscu pliku 

 mov ah, 3fh			;czytanie z pliku
 mov cx, 2			;czytanie 2 kilobajtów nagłówka - 16 bajtów
 lea dx, bufor
 int 21h

gdzie bufor jest zdefiniowany tak:

 bufor dw ?
0

OK, czyli wynik badania bajtów jest w CX, więc co jest w "bufor"?

0

Czytaj dokumentacje przerwań ;-p http://www.ctyme.com/intr/rb-2783.htm
CX to tylko ilosć bajtów do odczytania!! bufor zawiera wynik =]

0

OK, więc na razie program wygląda tak:

.model small
.386 
.code 

@otwieranie:

	mov ax, @DATA
	mov ds, ax

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

	jnc	@sprkolory

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


@err:
	mov	ax, 4c01h		; błąd=1
	int	21h

@sprkolory:

	mov ah, 42h
	mov al, 0                        ;przesunięcie względem początku pliku
	mov cx, 28                        ;przejście do 28 i 29 kilobajta zawierającego dane o kolorach
	xor  dx, dx
	mov bx, ax                        ;bx = uchwyt do pliku
	int 21h                           ; wskaznik w odpowiednim miejscu pliku

	mov ah, 3fh                        ;czytanie z pliku
	mov cx, 2                        ;czytanie 2 kilobajtów nagłówka - 16 bajtów
	lea dx, tryb
	int 21h
 
	cmp tryb, 4
	je @tryb_16
	cmp tryb, 8
	je @tryb_256 

@tryb_16:			; tu będzie procedura wyswietlania bitmapy 320x200x256 

	mov	ah, 09h
	lea	dx, t_16
	int	21h
	jmp @esc

@tryb_256:			; tu będzie procedura wyswietlania bitmapy 640x480x16

	mov	ah, 09h
	lea	dx, t_256
	int	21h

@esc:
	int	21h			; zamknij plik
	jc	@err


.data
t_256 db 'Tryb wyswietlania: 320x200x256                                                  ','$'
t_16 db 'Tryb wyswietlania: 640x480x16                                                   ','$'
tryb dw ?
nazwa_pliku	db	'rys1.bmp',0
blad_plik	db	'Blad operacji na pliku!','$'
smieci		db '                                 ' 

.stack
END @otwieranie

Tylko że to porównywanie zawartości "tryb" coś nie działa....

0

Zły wynik, czy po prostu sie nie kompiluje? jeżeli sie nie kompiluje to przepisz najpierw zawartość tryb do np ax i zamiast cmp tryb, 4 napisz cmp ax, 4; pewnie kompilator czepia się że nie zna rozmiaru porównywanych elementów.

0
 mov ax,tryb
 
 cmp ax, 4
 je @tryb_16
 cmp ax, 8
 je @tryb_256 

Zrobiłem przepisywanie do ax, ale cały czas wybiera procedure "tryb_16" nawet przy zamianie 4 z 8.
Może wartoby było zrobić podgląd tego co program odczytał z pliku BMP, czyli że po uruchomieniu programu pokazuje 4 lub 8 w zależności od tego jaki bedzie obrazek, a dopiero potem porównuje to i wybiera odpowiednią procedure.

0

były 4 poważne błędy :

.model small
.386
.code

@otwieranie:

        mov 	   ax, @DATA
        mov 	   ds, ax

        mov        ax, 3d00h  
        lea        dx, nazwa_pliku
        int        21h

        jnc        @sprkolory

        mov        ah, 09h
        lea        dx, blad_plik          
        int        21h


@err:
        mov        ax, 4c01h     
        int        21h

@sprkolory:
        mov bx, ax                     ; <- error 1; najpierw uchwyt do bx bo następne linijki kasowały ax!!
        mov ah, 42h
        mov al, 0             
        mov dx, 28                    ; ---- error 2;   ADRES nie DX:CX tylko CX:DX !!
        xor cx, cx                      ; /
        int 21h                          

        mov ah, 3fh                  
        mov cx, 2                     
        lea dx, tryb
        int 21h
 
        mov ax, tryb
        cmp ax, 4
        je @tryb_16
        cmp ax, 8
        je @tryb_256

@tryb_16:                   

        mov        ah, 09h
        lea        dx, t_16
        int        21h
        jmp @esc

@tryb_256:                 

        mov        ah, 09h
        lea        dx, t_256
        int        21h

@esc:
        mov        ah, 3eh                ; <- ERROR 3;    zapomniałeś o numerze funkcji 
        int        21h                        
        jc        @err

        mov        ax, 4c00h       ; <- Error 4; Kod kończący program
        int        21h


.data
t_256 db 'Tryb wyswietlania: 320x200x256','$'
t_16 db 'Tryb wyswietlania: 640x480x16$'
tryb dw ?
nazwa_pliku        db        'rys1.bmp',0
blad_plik        db        'Blad operacji na pliku!','$'
smieci                db '                                 '

.stack
END @otwieranie

0

Po współpracy z kolegą zrobiliśmy działający programik.
Działa on, ale bez odczytywania palety z pliku BMP obrazki mają dziwne kolory.
Znalazłem przykład odczytywania palety i chciałbym go zastosować. Ale chyba proste skopiowanie jej do programu nie daje rezultatów. Obrazki odczytują się w takich samych kolorach. na razie została ona skopiowana do procedury odczytywania obrazka 320x200x256. Co jeszcze należy zrobić, żeby to działało?

.model small
.386 
.code 

Start:	mov ax, @DATA
	mov ds, ax

	cmp byte ptr es:[80h],0
	je Brak_arg

	mov cl,es:[80h]
	xor ch,ch
	dec cx
	mov si, 82h
	lea di, NazwaPliku

;wczytanie nazwy pliku z atrybutu
kopiuj:
	mov al,es:[si]
	mov [di],al
	inc si
	inc di
	loop kopiuj
	mov byte ptr [di],'$'

;sprawdzenie czy podany plik istnieje
	mov ah,3Dh	;otworzenie pliku
	mov al,0
	lea dx,NazwaPliku
	int 21h
	jc BrakPliku
	mov Uchwyt,ax


menu:
;wlaczenie trybu tekstowego
	mov ax, 3
	int 10h;

	mov ah,42h	;przesuniecie wskaznika pliku
	mov al,0	;al=0 - wzgledem poczatku pliku
	mov bx,Uchwyt
	xor cx,cx
	mov dx,0Ah	;przesun do informacji o polozeniu poczatku danych
	int 21h
	mov ah,3Fh	;czytanie z pliku
	mov bx,Uchwyt
	lea dx,dane	
	mov cx,4	;ilosc odczytanych bajtow
	int 21h

;sprawdzenie ilosci kolorow
	mov ah,42h	;przesuniecie wskaznika pliku
	mov al,0	;al=0 - wzgledem poczatku pliku
	mov bx,Uchwyt
	xor cx,cx
	mov dx,1Ch	;przesun do informacji o ilosci kolorow
	int 21h
	mov ah,3Fh	;czytanie z pliku
	mov bx,Uchwyt
	lea dx,kolory	;wartosc 08h - 256, 04h - 16
	mov cx,2	;ilosc odczytanych bajtow
	int 21h

;sprawdzenie rozdzielczosci
	mov ah,42h	;przesuniecie wskaznika pliku
	mov al,0	;al=0 - wzgledem poczatku pliku
	mov bx,Uchwyt
	xor cx,cx
	mov dx,12h	;przesun do informacji o szerokosci pliku
	int 21h
	mov ah,3Fh	;czytanie z pliku
	mov bx,Uchwyt
	lea dx,szerokosc	
	mov cx,2	;ilosc odczytanych bajtow
	int 21h

	mov ah,42h	;przesuniecie wskaznika pliku
	mov al,0	;al=0 - wzgledem poczatku pliku
	mov bx,Uchwyt
	xor cx,cx
	mov dx,16h	;przesun do informacji o wysokosci pliku
	int 21h
	mov ah,3Fh	;czytanie z pliku
	mov bx,Uchwyt
	lea dx,wysokosc
	mov cx,2	;ilosc odczytanych bajtow
	int 21h


;przesuniecie wskaznika do poczatku danych
	mov ah,42h	;przesuniecie wskaznika pliku
	mov al,0	;al=0 - wzgledem poczatku pliku
	mov bx,Uchwyt
	xor cx,cx
	mov dx,dane	;przesun do poczatku danych
	int 21h

;wyswietlenie menu
	mov ah, 09h
	lea dx, tMenu
	int 21h
	
;wczytanie wybranej opcji
wybor_trybu:
	mov ah, 08h
	int 21h
	cmp al, 49
	je tryb320
	cmp al, 50
	je tryb640
	cmp al, 27
	je wyjscie
	jmp wybor_trybu



tryb320:
;sprawdzenie czy rozdzielczosc nie jest za duza
	cmp szerokosc,320
	jna wys320
	mov ah,9h
	lea dx,tZaDuzy
	int 21h
	mov ah, 08h
	int 21h
	jmp menu
wys320:
	cmp wysokosc,200
	jna wyswietl320
	mov ah,9h
	lea dx,tZaDuzy
	int 21h
	mov ah, 08h
	int 21h
	jmp menu

;ustawienie trybu graficznego
wyswietl320:
	mov ah,0
	mov al,19	;tryb 320x200x256
	int 10h

	mov cx,0
	mov dx,wysokosc	;przesuniecie do dolu ekranu (200)	
	push cx
	push dx

;//////////////////////////////////////////////////////////

;czytanie_palety
mov     AH,3Fh
mov     CX,kolory              ; CX = liczba kolorów w palecie
shl     CX,2                    ; CX = mnożenie przez 4, aby uzyskać 
                                ; wielkość palety (w bajtach)
mov     DX,offset paleta
int     21h                     ; Umieszczenie palety w buforze

;wysylanie palety
mov     SI,offset paleta      ; Wskazanie buforu zawierającego paletę
mov     CX,kolory             ; CX = Liczba kolorów do wysłania
mov     DX,3C8h
mov     AL,0                   ; Rozpoczęcie od koloru 0
out     DX,AL
inc     DX                     ; DX = 3C9h.

wysylaj:
mov     AL,[SI+2]             ; Uzyskanie wartości czerwonego koloru
shr     AL,2                  ; Maksymalnie 255, ale możliwe jest
                              ; wyświetlenie wartości tylko do 63. 
                              ; Dzielenie przez 4 zapewnia dobry wynik
out     DX,AL                 ; Wysłanie wartości
mov     AL,[SI+1]             ; Uzyskanie wartości zielonego koloru
shr     AL,2
out     DX,AL                 ; Wysłanie wartości
mov     AL,[SI]               ; Uzyskanie wartości niebieskiego koloru
shr     AL,2
out     DX,AL                 ; Wysłanie wartości
add     SI,4                  ; Wskazanie kolejnego koloru
loop    wysylaj


;////////////////////////////////////////////////////////////

;wyswietlanie pliku	
czytaj320:
	mov ah,3Fh
	mov bx,Uchwyt
	lea dx,bufor
	mov cx,1
	int 21h
	cmp ax,0
	je Eof
	pop dx
	pop cx
	mov ah,0Ch	;wyswietlanie pikseli
	mov bh,0	;b - numer strony, al - kolor piksela, cx - Y, dx - X
	mov al, bufor
	int 10h

	cmp kolory,08h
	je k256x320
	shl bufor,4
	inc cx
	mov ah,0Ch	;wyswietlanie pikseli
	mov bh,0	;b - numer strony, al - kolor piksela, cx - Y, dx - X
	mov al, bufor
	int 10h

k256x320:
	inc cx
	cmp cx,szerokosc
	jne dalej320
	dec dx
	xor cx,cx
dalej320:
	push cx
	push dx
	jmp czytaj320



tryb640:
;sprawdzenie czy rozdzielczosc nie jest za duza
	cmp szerokosc,640
	jna wys640
	mov ah,9h
	lea dx,tZaDuzy
	int 21h
	mov ah, 08h
	int 21h
	jmp menu
wys640:
	cmp wysokosc,480
	jna wyswietl640
	mov ah,9h
	lea dx,tZaDuzy
	int 21h
	mov ah, 08h
	int 21h
	jmp menu


;ustawienie trybu graficznego
wyswietl640:
	mov ah,0
	mov al,18	;tryb 640x480x16
	int 10h

	mov cx,0
	mov dx, wysokosc	;przesuniecie do dolu ekranu
	push cx
	push dx

;wyswietlanie pliku	
czytaj640:
	mov ah,3Fh
	mov bx,Uchwyt
	lea dx,bufor
	mov cx,1
	int 21h
	cmp ax,0
	je Eof
	pop dx
	pop cx
	mov ah,0Ch
	mov bh,0
	mov al, bufor
	int 10h

	cmp kolory,08h
	je k256x640
	shl bufor,4
	inc cx
	mov ah,0Ch	;wyswietlanie pikseli
	mov bh,0	;b - numer strony, al - kolor piksela, cx - Y, dx - X
	mov al, bufor
	int 10h

k256x640:
	inc cx
	cmp cx, szerokosc
	jne dalej640
	dec dx
	xor cx,cx
dalej640:
	push cx
	push dx
	jmp czytaj640

Eof:
	mov ah, 08h
	int 21h
	jmp menu

BrakPliku:
	mov ah,9h
	lea dx,tBrakPliku
	int 21h
	jmp wyjscie

Brak_arg:
	mov ah,9h
	lea dx,tBrakArg
	int 21h
	

wyjscie:
	mov ah,3Eh	;zamkniecie pliku
	mov bx, Uchwyt	
	int 21h

	mov ah, 4Ch 
	mov al, 00h 
	int 21h


.data
tMenu db '                        Wybierz tryb wyswietlania bitmapy:                           1 - 320x200 w 256 kolorach,  2 - 640x480 w 16 kolorach,  ESC - wyjscie    ','$' 
tBrakPliku db 'Podany plik nie istnieje!$'
tBrakArg db 'Bledny atrybut pliku! (atrybut - nazwa pliku bmp, np plik.bmp)$'
NazwaPliku db 128 dup(?)
Uchwyt dw 0
bufor db ?
dane dw ?
szerokosc dw ?
wysokosc dw ?
kolory dw ?
tZaDuzy db '                          Plik ma za duza rozdzielczosc!$'
paleta    db 1024 dup('P')

.stack
END Start

1 użytkowników online, w tym zalogowanych: 0, gości: 1