不明白我的 PCX 代码有什么问题
Don't understand what's wrong with my PCX code
我有一个代码可以使用程序集显示 PCX
按其宽度
示例图片 320x200 x=0, y=0
但是如果X(StartPictX)和Y(StartPictY)不等于0,就会毁图
我需要解决这个问题...
原代码:
;--------------------------------------
; Load and show file *.PCX 320x200x256
;
;--------------------------------------
IDEAL
MODEL large
P386
MACRO SHOWPCX StartX, StartY, fName
mov ax, [StartX]
mov [Point_X], ax
mov ax, [StartY]
mov [Point_Y], ax
mov dx, offset fName
call ShowPCXFile
ENDM SHOWPCX
STACK 256
DATASEG
ErrorReadingFile DB 'Can not open file$'
FileName1 DB 'mouse.pcx',0
FileName DW ? ; offset file name for current file
FileHandle DW ?
FileSize DW ?
ImageSizeInFile DW ?
ImageWidth DW ?
ImageHeigth DW ?
PaletteOffset DW ?
Point_X DW ?
Point_Y DW ?
Color DB ?
StartPictX DW ?
StartPictY DW ?
SEGMENT FILEBUF para public 'DATA'
DB 65200 DUP(?)
ENDS
CODESEG
Start:
mov ax, @data
mov ds, ax
mov ax, 0013h
int 10h
; -----------------= Show Pic1 =----------------
mov [StartPictX], 0
mov [StartPictY], 0
SHOWPCX StartPictX, StartPictY, FileName1
mov ah,00h
int 16h
mov ah,00h
mov al,03h
int 10h
Exit:
mov ax,04c00h
int 21h
;-------------------------------------------
; ReadPCXFile - read PCX file into FILEBUF
;-------------------------------------------
; Input:
; File name
; Output:
; File into FILEBUF
; Registers
; AX, BX, CX, DX, DS
;-------------------------------------------
PROC ReadPCXFile Near
pusha
;----- Initialize variables
mov [FileHandle],0
mov [FileSize],0
;----- Open file for reading
mov ah, 3Dh
mov al, 0
; mov DX,offset FileName
int 21h
jc @@Err
mov [FileHandle],AX ; save Handle
;----- Get the length of a file by setting a pointer to its end
mov ah, 42h
mov al ,2
mov bx, [FileHandle]
xor cx, cx
xor dx, dx
int 21h
jc @@Err
cmp dx,0
jne @@Err ;file size exceeds 64K
;----- Save size of file
mov [FileSize], ax
;----- Return a pointer to the beginning of the file
mov ah, 42h
mov al, 0
mov bx, [FileHandle]
xor cx, cx
xor dx, dx
int 21h
jc @@Err
;----- Read file into FILEBUF
mov bx, [FileHandle]
pusha
push ds
mov ax,FILEBUF
mov ds, ax
xor dx, dx
mov cx, 65200
mov ah, 3Fh
int 21H
pop ds
popa
jc @@Err
;----- Close the file
mov ah, 3Eh
mov bx,[FileHandle]
int 21H
jc @@Err
popa
ret
;----- Exit - error reading file
@@Err: ; Set text mode
mov ax, 3
int 10h
mov dx, offset ErrorReadingFile
mov ah, 09h
int 21h
jmp Exit
ENDP ReadPCXFile
;-------------------------------------------
; ShowPCXFile - show PCX file
;-------------------------------------------
; Input:
; File name
; Output:
; The file
; Registers
; AX, BX, CX, DX, DS
;-------------------------------------------
PROC ShowPCXFile Near
pusha
call ReadPCXFile
mov ax, FILEBUF
mov es, ax
;----- Set ES:SI on the image
mov si, 128
;----- Calculate the width and height of the image
mov ax, [es:42h]
mov [ImageWidth], ax
dec [ImageWidth]
mov ax, [es:0Ah]
sub ax, [es:6]
inc ax
mov [ImageHeigth], ax
;----- Calculate the offset from the beginning of the palette file
mov ax, [FileSize]
sub ax, 768
mov [PaletteOffset], ax
call SetPalette
mov ax, [FileSize]
sub ax, 128+768
mov [ImageSizeInFile], ax
xor ch, ch ; Clear high part of CX for string copies
push [StartPictX] ; Set start position
pop [Point_x]
push [StartPictY]
pop [Point_y]
NextByte:
mov cl, [es:si] ; Get next byte
cmp cl, 0C0h ; Is it a length byte?
jb normal ; No, just copy it
and cl, 3Fh ; Strip upper two bits from length byte
inc si ; Advance to next byte - color byte
mov al, [es:si]
mov [Color], al
NextPixel:
call PutPixel
cmp cx, 1
je CheckEndOfLine
inc [Point_X]
loop NextPixel
jmp CheckEndOfLine
Normal:
mov [Color], cl
call PutPixel
CheckEndOfLine:
mov ax, [Point_X]
sub ax, [StartPictX]
cmp ax, [ImageWidth]
;----- [Point_X] - [StartPictX] >= [WidthPict]
jae LineFeed
inc [Point_x]
jmp cont
LineFeed:
push [StartPictX]
pop [Point_x]
inc [Point_y]
cont:
inc si
cmp si, [ImageSizeInFile] ; End of file? (written 320x200 bytes)
jb nextbyte
popa
ret
ENDP ShowPCXFile
;-------------------------------------------
; PutPixel - draw pixel
;-------------------------------------------
; Input:
; x - Point_x, y - Point_y, Color - color
; Output:
; The pixel
; Registers
; AX, BH, CX, DX
;-------------------------------------------
PROC PutPixel near
pusha
mov bh, 0h
mov cx, [Point_x]
mov dx, [Point_Y]
mov al, [color]
mov ah, 0ch
int 10h
popa
ret
ENDP PutPixel
;-------------------------------------------
; SetPalette - change palette from 0-255 to from 0-63
;-------------------------------------------
; Input:
; PaletteOffset
; Output:
; New palette
; Registers
; AX, BX, CX, DX, SI, ES
;-------------------------------------------
SetPalette:
pusha
mov cx, 256*3
mov si, [PaletteOffset]
NextColor:
shr [byte es:si], 2
inc si
loop NextColor
mov dx, [PaletteOffset]
mov ax, 1012h
mov bx, 00h
mov cx, 256d
int 10h
popa
ret
End Start
我意识到问题出在图像的宽度上。它继续排列像素,直到我们达到图像的宽度,然后添加到 Y。
我尝试更改它但没有成功:
CheckEndOfLine:
mov ax, [Point_X]
;sub ax, [StartPictX]
cmp ax, 320
jae LineFeed
inc [Point_x]
inc si
jmp cont
LineFeed:
push [StartPictX]
pop [Point_x]
inc [Point_y]
mov bx,320
sub bx,[StartPictX]
@@lop:
mov cl, [es:si] ; Get next byte
cmp cl, 0C0h ; Is it a length byte?
jb nor
and cl, 3Fh ; Strip upper two bits from length byte
add si,cx
sub bx,cx
jmp next
nor:
inc si
dec bx
next:
cmp bx,1
jg @@lop
cont:
cmp si, [ImageSizeInFile] ; End of file? (written 320x200 bytes)
jb nextbyte
popa
ret
我真的需要帮助:)
Tnx 帮助者
ImageSizeInFile 的计算是正确的但是您的代码使用此信息就好像它代表地址一样!。我建议您重命名变量并使用下一个计算:
mov ax, [FileSize]
sub ax, 768
mov [ImageEndAddressInFile], ax
您需要正确计算 ImageWidth,就像计算 ImageHeight 一样。 1 条扫描线中的字节数不一定对应于以像素为单位的图像宽度,尤其是在压缩的情况下!
mov ax, [es:0008h] ; X2
sub ax, [es:0004h] ; X1
inc ax
mov [ImageWidth], ax
mov ax, [es:000Ah] ; Y2
sub ax, [es:0006h] ; Y1
inc ax
mov [ImageHeight], ax
您当前的程序仅有条件地递增 X 位置 Point_x。这不好。对于您处理过的每个像素,您必须始终具有 inc [Point_x]
.
NextByte:
mov cl, [es:si] ; Get next byte
inc si
cmp cl, 0C0h ; Is it a length byte?
jb Normal ; No, just copy it
and cx, 003Fh ; Strip upper two bits from length byte
mov al, [es:si] ; The color
inc si
mov [Color], al
jcxz CheckEndOfLine ; Could exist this one!
NextPixel:
call PutPixel
inc [Point_X]
loop NextPixel
jmp CheckEndOfLine
Normal:
mov [Color], cl
call PutPixel
inc [Point_x]
CheckEndOfLine:
mov ax, [Point_X]
sub ax, [StartPictX] ; Number of processed pixels
cmp ax, [ImageWidth] ; Image width measured in pixels
jb Cont
LineFeed:
push [StartPictX]
pop [Point_x]
inc [Point_y]
Cont:
cmp si, [ImageEndAddressInFile]
jb NextByte
现在可以解决自由选择StartPictX和StartPictY.
的问题了
一个简单的解决方案是完全处理图像数据(就好像图像会紧贴屏幕一样)并让 PutPixel 过程剪掉落在屏幕之外的点屏幕。
PROC PutPixel near
cmp [Point_y], 200
jnb IsOutside
cmp [Point_x], 320
jnb IsOutside
pusha
mov dx, [Point_y]
mov cx, [Point_x]
mov bh, 0
mov al, [Color]
mov ah, 0Ch
int 10h
popa
IsOutside:
ret
ENDP PutPixel
混合解决方案会好一些。始终显示 PutPixel 有效的 Y 坐标:
LineFeed:
push [StartPictX]
pop [Point_x]
inc [Point_y]
cmp [Point_y], 200 <<<<<
jnb Done <<<<<
Cont:
cmp si, [ImageEndAddressInFile]
jb NextByte
Done:
和
PROC PutPixel near
cmp [Point_x], 320
jnb IsOutside
pusha
mov dx, [Point_y]
mov cx, [Point_x]
mov bh, 0
mov al, [Color]
mov ah, 0Ch
int 10h
popa
IsOutside:
ret
ENDP PutPixel
我有一个代码可以使用程序集显示 PCX
按其宽度
示例图片 320x200 x=0, y=0
但是如果X(StartPictX)和Y(StartPictY)不等于0,就会毁图
我需要解决这个问题...
原代码:
;--------------------------------------
; Load and show file *.PCX 320x200x256
;
;--------------------------------------
IDEAL
MODEL large
P386
MACRO SHOWPCX StartX, StartY, fName
mov ax, [StartX]
mov [Point_X], ax
mov ax, [StartY]
mov [Point_Y], ax
mov dx, offset fName
call ShowPCXFile
ENDM SHOWPCX
STACK 256
DATASEG
ErrorReadingFile DB 'Can not open file$'
FileName1 DB 'mouse.pcx',0
FileName DW ? ; offset file name for current file
FileHandle DW ?
FileSize DW ?
ImageSizeInFile DW ?
ImageWidth DW ?
ImageHeigth DW ?
PaletteOffset DW ?
Point_X DW ?
Point_Y DW ?
Color DB ?
StartPictX DW ?
StartPictY DW ?
SEGMENT FILEBUF para public 'DATA'
DB 65200 DUP(?)
ENDS
CODESEG
Start:
mov ax, @data
mov ds, ax
mov ax, 0013h
int 10h
; -----------------= Show Pic1 =----------------
mov [StartPictX], 0
mov [StartPictY], 0
SHOWPCX StartPictX, StartPictY, FileName1
mov ah,00h
int 16h
mov ah,00h
mov al,03h
int 10h
Exit:
mov ax,04c00h
int 21h
;-------------------------------------------
; ReadPCXFile - read PCX file into FILEBUF
;-------------------------------------------
; Input:
; File name
; Output:
; File into FILEBUF
; Registers
; AX, BX, CX, DX, DS
;-------------------------------------------
PROC ReadPCXFile Near
pusha
;----- Initialize variables
mov [FileHandle],0
mov [FileSize],0
;----- Open file for reading
mov ah, 3Dh
mov al, 0
; mov DX,offset FileName
int 21h
jc @@Err
mov [FileHandle],AX ; save Handle
;----- Get the length of a file by setting a pointer to its end
mov ah, 42h
mov al ,2
mov bx, [FileHandle]
xor cx, cx
xor dx, dx
int 21h
jc @@Err
cmp dx,0
jne @@Err ;file size exceeds 64K
;----- Save size of file
mov [FileSize], ax
;----- Return a pointer to the beginning of the file
mov ah, 42h
mov al, 0
mov bx, [FileHandle]
xor cx, cx
xor dx, dx
int 21h
jc @@Err
;----- Read file into FILEBUF
mov bx, [FileHandle]
pusha
push ds
mov ax,FILEBUF
mov ds, ax
xor dx, dx
mov cx, 65200
mov ah, 3Fh
int 21H
pop ds
popa
jc @@Err
;----- Close the file
mov ah, 3Eh
mov bx,[FileHandle]
int 21H
jc @@Err
popa
ret
;----- Exit - error reading file
@@Err: ; Set text mode
mov ax, 3
int 10h
mov dx, offset ErrorReadingFile
mov ah, 09h
int 21h
jmp Exit
ENDP ReadPCXFile
;-------------------------------------------
; ShowPCXFile - show PCX file
;-------------------------------------------
; Input:
; File name
; Output:
; The file
; Registers
; AX, BX, CX, DX, DS
;-------------------------------------------
PROC ShowPCXFile Near
pusha
call ReadPCXFile
mov ax, FILEBUF
mov es, ax
;----- Set ES:SI on the image
mov si, 128
;----- Calculate the width and height of the image
mov ax, [es:42h]
mov [ImageWidth], ax
dec [ImageWidth]
mov ax, [es:0Ah]
sub ax, [es:6]
inc ax
mov [ImageHeigth], ax
;----- Calculate the offset from the beginning of the palette file
mov ax, [FileSize]
sub ax, 768
mov [PaletteOffset], ax
call SetPalette
mov ax, [FileSize]
sub ax, 128+768
mov [ImageSizeInFile], ax
xor ch, ch ; Clear high part of CX for string copies
push [StartPictX] ; Set start position
pop [Point_x]
push [StartPictY]
pop [Point_y]
NextByte:
mov cl, [es:si] ; Get next byte
cmp cl, 0C0h ; Is it a length byte?
jb normal ; No, just copy it
and cl, 3Fh ; Strip upper two bits from length byte
inc si ; Advance to next byte - color byte
mov al, [es:si]
mov [Color], al
NextPixel:
call PutPixel
cmp cx, 1
je CheckEndOfLine
inc [Point_X]
loop NextPixel
jmp CheckEndOfLine
Normal:
mov [Color], cl
call PutPixel
CheckEndOfLine:
mov ax, [Point_X]
sub ax, [StartPictX]
cmp ax, [ImageWidth]
;----- [Point_X] - [StartPictX] >= [WidthPict]
jae LineFeed
inc [Point_x]
jmp cont
LineFeed:
push [StartPictX]
pop [Point_x]
inc [Point_y]
cont:
inc si
cmp si, [ImageSizeInFile] ; End of file? (written 320x200 bytes)
jb nextbyte
popa
ret
ENDP ShowPCXFile
;-------------------------------------------
; PutPixel - draw pixel
;-------------------------------------------
; Input:
; x - Point_x, y - Point_y, Color - color
; Output:
; The pixel
; Registers
; AX, BH, CX, DX
;-------------------------------------------
PROC PutPixel near
pusha
mov bh, 0h
mov cx, [Point_x]
mov dx, [Point_Y]
mov al, [color]
mov ah, 0ch
int 10h
popa
ret
ENDP PutPixel
;-------------------------------------------
; SetPalette - change palette from 0-255 to from 0-63
;-------------------------------------------
; Input:
; PaletteOffset
; Output:
; New palette
; Registers
; AX, BX, CX, DX, SI, ES
;-------------------------------------------
SetPalette:
pusha
mov cx, 256*3
mov si, [PaletteOffset]
NextColor:
shr [byte es:si], 2
inc si
loop NextColor
mov dx, [PaletteOffset]
mov ax, 1012h
mov bx, 00h
mov cx, 256d
int 10h
popa
ret
End Start
我意识到问题出在图像的宽度上。它继续排列像素,直到我们达到图像的宽度,然后添加到 Y。
我尝试更改它但没有成功:
CheckEndOfLine:
mov ax, [Point_X]
;sub ax, [StartPictX]
cmp ax, 320
jae LineFeed
inc [Point_x]
inc si
jmp cont
LineFeed:
push [StartPictX]
pop [Point_x]
inc [Point_y]
mov bx,320
sub bx,[StartPictX]
@@lop:
mov cl, [es:si] ; Get next byte
cmp cl, 0C0h ; Is it a length byte?
jb nor
and cl, 3Fh ; Strip upper two bits from length byte
add si,cx
sub bx,cx
jmp next
nor:
inc si
dec bx
next:
cmp bx,1
jg @@lop
cont:
cmp si, [ImageSizeInFile] ; End of file? (written 320x200 bytes)
jb nextbyte
popa
ret
我真的需要帮助:)
Tnx 帮助者
ImageSizeInFile 的计算是正确的但是您的代码使用此信息就好像它代表地址一样!。我建议您重命名变量并使用下一个计算:
mov ax, [FileSize]
sub ax, 768
mov [ImageEndAddressInFile], ax
您需要正确计算 ImageWidth,就像计算 ImageHeight 一样。 1 条扫描线中的字节数不一定对应于以像素为单位的图像宽度,尤其是在压缩的情况下!
mov ax, [es:0008h] ; X2
sub ax, [es:0004h] ; X1
inc ax
mov [ImageWidth], ax
mov ax, [es:000Ah] ; Y2
sub ax, [es:0006h] ; Y1
inc ax
mov [ImageHeight], ax
您当前的程序仅有条件地递增 X 位置 Point_x。这不好。对于您处理过的每个像素,您必须始终具有 inc [Point_x]
.
NextByte:
mov cl, [es:si] ; Get next byte
inc si
cmp cl, 0C0h ; Is it a length byte?
jb Normal ; No, just copy it
and cx, 003Fh ; Strip upper two bits from length byte
mov al, [es:si] ; The color
inc si
mov [Color], al
jcxz CheckEndOfLine ; Could exist this one!
NextPixel:
call PutPixel
inc [Point_X]
loop NextPixel
jmp CheckEndOfLine
Normal:
mov [Color], cl
call PutPixel
inc [Point_x]
CheckEndOfLine:
mov ax, [Point_X]
sub ax, [StartPictX] ; Number of processed pixels
cmp ax, [ImageWidth] ; Image width measured in pixels
jb Cont
LineFeed:
push [StartPictX]
pop [Point_x]
inc [Point_y]
Cont:
cmp si, [ImageEndAddressInFile]
jb NextByte
现在可以解决自由选择StartPictX和StartPictY.
的问题了一个简单的解决方案是完全处理图像数据(就好像图像会紧贴屏幕一样)并让 PutPixel 过程剪掉落在屏幕之外的点屏幕。
PROC PutPixel near
cmp [Point_y], 200
jnb IsOutside
cmp [Point_x], 320
jnb IsOutside
pusha
mov dx, [Point_y]
mov cx, [Point_x]
mov bh, 0
mov al, [Color]
mov ah, 0Ch
int 10h
popa
IsOutside:
ret
ENDP PutPixel
混合解决方案会好一些。始终显示 PutPixel 有效的 Y 坐标:
LineFeed:
push [StartPictX]
pop [Point_x]
inc [Point_y]
cmp [Point_y], 200 <<<<<
jnb Done <<<<<
Cont:
cmp si, [ImageEndAddressInFile]
jb NextByte
Done:
和
PROC PutPixel near
cmp [Point_x], 320
jnb IsOutside
pusha
mov dx, [Point_y]
mov cx, [Point_x]
mov bh, 0
mov al, [Color]
mov ah, 0Ch
int 10h
popa
IsOutside:
ret
ENDP PutPixel