打印800 * 600 bmp图片组装

问题描述 投票:0回答:1

我一直在做一个装配项目,我需要在屏幕上打印一张bmp图片。我将屏幕的分辨率更改为800 * 600,并且我有一个代码(我没写过)打印320 * 200 bmp图片。我不知道怎么改它打印800 * 600的图片。

有人可以帮忙吗?谢谢。

这是需要更改的代码的一部分:

proc CopyBitmap
; BMP graphics are saved upside-down.
; Read the graphic line by line (200 lines in VGA format),
; displaying the lines from bottom to top.
mov ax, 0A000h
mov es, ax
mov cx,200
PrintBMPLoop:
push cx
; di = cx*320, point to the correct screen line
mov di,cx
shl cx,6
shl di,8
add di,cx
; Read one line
mov ah,3fh
mov cx,320
mov dx,offset ScrLine
int 21h
; Copy one line into video memory
cld ; Clear direction flag, for movsb
mov cx,320
mov si,offset ScrLine 

rep movsb ; Copy line to the screen
 ;rep movsb is same as the following code:
 ;mov es:di, ds:si
 ;inc si
 ;inc di
 ;dec cx
 ;... loop until cx=0
pop cx
loop PrintBMPLoop
ret
endp CopyBitmap
assembly x86-16 bmp vga
1个回答
3
投票

你说你自己写的代码是错的!要使用相同大小的位图填充整个320x200 256色屏幕,Y坐标必须在199 downto 0之间变化。此代码当前从200 downto 1循环,因此位图的底线永远不会显示。这很容易解决。

当您告诉我们您已将屏幕分辨率更改为800x600时,您还应告诉我们颜色分辨率。在下面的代码中,我将假设它是256色,就像在示例代码中一样。此外,我将介绍一种使用LinearFrameBuffer方法的解决方案。存在窗口方法但更难(当然如果你不想削减太多的角落)。对于不再适合64KB图形窗口(800 * 600 = 480000字节)的视频模式,它将涉及使用VESA进行存储体切换。

但320x200示例也可以使用LFB方法。

视频窗口位于分段地址0A000h:0000h。这实际上是线性地址000A0000h。

; On entry BX is handle for the file with filepointer at bitmap data!!!
proc CopyBitmap
    ; BMP graphics are saved upside-down.
    ; Read the graphic line by line (200 lines in VGA format),
    ; displaying the lines from bottom to top.
    push    es
    xor     ax, ax
    mov     es, ax
    mov     cx, 200
PrintBMPLoop:
    push    cx

    ; Point to the correct screen line
    dec     cx             ; Y ranging from 199 to 0
    movzx   edi, cx
    imul    edi, 320
    add     edi, 000A0000h

    ; Read one line
    mov     dx, offset ScrLine
    mov     cx, 320
    mov     ah, 3Fh        ; DOS.ReadFile
    int     21h
    jc      WhatIfError?
    cmp     ax, cx
    jne     WhatIfError?

    ; Copy one line into video memory
    mov     si, dx
    add     dx, cx         ; DX now points to the end of the buffer
CopyLoop:
    lodsd                  ; Load 4 pixels together
    stosd   [edi]          ; This generates an AddressSizePrefix
    cmp     si, dx
    jb      CopyLoop

    pop     cx
    loop    PrintBMPLoop

    pop     es
    ret
endp CopyBitmap

800x600代码非常相似。

从检查VESA 4F01h ReturnVBEModeInformation函数的结果中获取BytesPerScanLine值和LinearFrameBuffer地址。

  • ModeInfoBlock PhysBasePtr(dword)的偏移量+40
  • ModeInfoBlock的偏移量+50 LinBytesPerScanLine(word)

BytesPerScanLine值不必为800.图形环境可能很容易选择1024作为更合理的值。你需要检查而不仅仅是假设。

; On entry BX is handle for the file with filepointer at bitmap data!!!
proc CopyBitmap
    ; BMP graphics are saved upside-down.
    ; Read the graphic line by line (600 lines in SVGA format),
    ; displaying the lines from bottom to top.
    push    es
    xor     ax, ax
    mov     es, ax
    mov     cx, 600
PrintBMPLoop:
    push    cx

    ; Point to the correct screen line
    dec     cx             ; Y ranging from 599 to 0
    movzx   edi, cx
    imul    edi, BytesPerScanLine
    add     edi, LinearFrameBuffer

    ; Read one line
    mov     dx, offset ScrLine
    mov     cx, 800
    mov     ah, 3Fh        ; DOS.ReadFile
    int     21h
    jc      WhatIfError?
    cmp     ax, cx
    jne     WhatIfError?

    ; Copy one line into video memory
    mov     si, dx
    add     dx, cx         ; DX now points to the end of the buffer
CopyLoop:
    lodsd                  ; Load 4 pixels together
    stosd   [edi]          ; This generates an AddressSizePrefix
    cmp     si, dx
    jb      CopyLoop

    pop     cx
    loop    PrintBMPLoop

    pop     es
    ret
endp CopyBitmap
© www.soinside.com 2019 - 2024. All rights reserved.