我目前正在x86 TASM中编写一个程序,我使用一种方法来转换256色BMP图像并在屏幕上绘制(通过绘画我的意思是“以图形模式”打印图像)。我已经为两张照片做了这个,但是当我为第三张照片做的时候 图片看起来像这样:
然而,当我使用这种方法时会发生什么事情(它的大小差异很好,我说的是黑线):
我还尝试过另一张不仅仅是一种纯色的照片,而且它会使图像偏斜。
以下是我使用的方法示例(我使用的是VGA 320x200模式,它适用于2个320x200图像,所以可能与尺寸有关?):
IDEAL
MODEL small
STACK 100h
MAX_BMP_WIDTH = 320
MAX_BMP_HEIGHT = 200
SMALL_BMP_HEIGHT = 40
SMALL_BMP_WIDTH = 40
DATASEG
OneBmpLine db MAX_BMP_WIDTH dup (0) ; One Color line read buffer
ScreenLineMax db MAX_BMP_WIDTH dup (0) ; One Color line read buffer
;BMP File data
FileHandle dw ?
Header db 54 dup(0)
Palette db 400h dup (0)
SmallPicName db 'circle1.bmp',0
BmpFileErrorMsg db 'Error At Opening Bmp File .', 0dh, 0ah,'$'
ErrorFile db 0
BB db "BB..",'$'
BmpLeft dw ?
BmpTop dw ?
BmpColSize dw ?
BmpRowSize dw ?
CODESEG
start:
mov ax, @data
mov ds, ax
call SetGraphic
mov [BmpLeft],10
mov [BmpTop],50
mov [BmpColSize], 50
mov [BmpRowSize] ,50
mov dx,offset SmallPicName
call OpenShowBmp
cmp [ErrorFile],1
jne cont1
jmp exitError
cont1:
jmp exit
exitError:
mov dx, offset BmpFileErrorMsg
mov ah,9
int 21h
exit:
mov dx, offset BB
mov ah,9
;int 21h
mov ah,0
int 16h
mov ax,2
int 10h
mov ax, 4c00h
int 21h
; input :
; 1.BmpLeft offset from left (where to start draw the picture)
; 2. BmpTop offset from top
; 3. BmpColSize picture width ,
; 4. BmpRowSize bmp height
; 5. dx offset to file name with zero at the end
proc OpenShowBmp near
push cx
push bx
call OpenBmpFile
cmp [ErrorFile],1
je @@ExitProc
call ReadBmpHeader
; from here assume bx is global param with file handle.
call ReadBmpPalette
call CopyBmpPalette
call ShowBMP
call CloseBmpFile
@@ExitProc:
pop bx
pop cx
ret
endp OpenShowBmp
; input dx filename to open
proc OpenBmpFile near
mov ah, 3Dh
xor al, al
int 21h
jc @@ErrorAtOpen
mov [FileHandle], ax
jmp @@ExitProc
@@ErrorAtOpen:
mov [ErrorFile],1
@@ExitProc:
ret
endp OpenBmpFile
proc CloseBmpFile near
mov ah,3Eh
mov bx, [FileHandle]
int 21h
ret
endp CloseBmpFile
; Read 54 bytes the Header
proc ReadBmpHeader near
push cx
push dx
mov ah,3fh
mov bx, [FileHandle]
mov cx,54
mov dx,offset Header
int 21h
pop dx
pop cx
ret
endp ReadBmpHeader
proc ReadBmpPalette near ; Read BMP file color palette, 256 colors * 4 bytes (400h)
; 4 bytes for each color BGR + null)
push cx
push dx
mov ah,3fh
mov cx,400h
mov dx,offset Palette
int 21h
pop dx
pop cx
ret
endp ReadBmpPalette
; Will move out to screen memory the colors
; video ports are 3C8h for number of first color
; and 3C9h for all rest
proc CopyBmpPalette near
push cx
push dx
mov si,offset Palette
mov cx,256
mov dx,3C8h
mov al,0 ; black first
out dx,al ;3C8h
inc dx ;3C9h
CopyNextColor:
mov al,[si+2] ; Red
shr al,2 ; divide by 4 Max (cos max is 63 and we have here max 255 ) (loosing color resolution).
out dx,al
mov al,[si+1] ; Green.
shr al,2
out dx,al
mov al,[si] ; Blue.
shr al,2
out dx,al
add si,4 ; Point to next color. (4 bytes for each color BGR + null)
loop CopyNextColor
pop dx
pop cx
ret
endp CopyBmpPalette
proc ShowBMP
; BMP graphics are saved upside-down.
; Read the graphic line by line (BmpRowSize lines in VGA format),
; displaying the lines from bottom to top.
push cx
mov ax, 0A000h
mov es, ax
mov cx,[BmpRowSize]
mov ax,[BmpColSize] ; row size must dived by 4 so if it less we must calculate the extra padding bytes
xor dx,dx
mov si,4
div si
mov bp,dx
mov dx,[BmpLeft]
@@NextLine:
push cx
push dx
mov di,cx ; Current Row at the small bmp (each time -1)
add di,[BmpTop] ; add the Y on entire screen
; next 5 lines di will be = cx*320 + dx , point to the correct screen line
mov cx,di
shl cx,6
shl di,8
add di,cx
add di,dx
; small Read one line
mov ah,3fh
mov cx,[BmpColSize]
add cx,bp ; extra bytes to each row must be divided by 4
mov dx,offset ScreenLineMax
int 21h
; Copy one line into video memory
cld ; Clear direction flag, for movsb
mov cx,[BmpColSize]
mov si,offset ScreenLineMax
rep movsb ; Copy line to the screen
pop dx
pop cx
loop @@NextLine
pop cx
ret
endp ShowBMP
proc SetGraphic
mov ax,13h ; 320 X 200
;Mode 13h is an IBM VGA BIOS mode. It is the specific standard 256-color mode
int 10h
ret
endp SetGraphic
END start
你能帮我解决黑线/图像偏斜的问题吗? 感谢