不了解我的PCX代码出了什么问题 [英] Don't understand what's wrong with my PCX code

查看:92
本文介绍了不了解我的PCX代码出了什么问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用程序集显示PCX的代码
按其宽度

I have a code that shows a PCX using assembly
By its width

示例图片320x200 x = 0,y = 0

Example image 320x200 x=0, y=0

但是,如果X( StartPictX )和Y( StartPictY )不等于0,则会破坏图片.

But if X (StartPictX) and Y (StartPictY) are unequal to 0, it ruins the picture.

我需要解决这个问题...

And I need to fix that...

原始代码:

;--------------------------------------
; 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.
我试图更改它,但没有成功:

I realized the problem is the width of the image. It continues to line pixels until we reach the width of the image and then add to Y.
I tried to change it but didn't succeed:

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帮手

I really need help :)
Tnx for the helpers

推荐答案

ImageSizeInFile 的计算是正确的,但是您的代码使用此信息就像表示地址一样!.我建议您重命名变量并使用下一个计算:

The calculation of the ImageSizeInFile is correct but your code uses this info as if it represented an address!. I suggest you rename the variable and use next calculation:

    mov     ax, [FileSize]
    sub     ax, 768
    mov     [ImageEndAddressInFile], ax

您需要正确计算 ImageWidth ,就像对 ImageHeight 所做的一样. 1条扫描线中的字节数不一定与以像素为单位的图像宽度相对应,尤其是在压缩的情况下!

You need to calculate the ImageWidth correctly, just like you did for the ImageHeight. The number of bytes in 1 scanline does not necessarily correspond to the image width in pixels, especially in case of compression!

    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].

Your current program increments the X position Point_x only conditionally. This is not fine. For every pixel that you've processed, you must always have 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 过程剪切掉屏幕之外的点.

Now we can address the issue of freely selecting StartPictX and StartPictY.

An easy solution is to process the image data fully (just as if the image would snugly fit the screen) and have the PutPixel procedure clip off points that fall outside of the screen.

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坐标:

A mixed solution is somewhat better. Always presenting PutPixel a valid Y-coordinate:

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代码出了什么问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆