【问题标题】:change a code from flipping "8bpp .bmp image" horizontally to flip a "1bpp .bmp image" horizontally in x86将代码从水平翻转“8bpp .bmp 图像”更改为在 x86 中水平翻转“1bpp .bmp 图像”
【发布时间】:2011-01-22 12:19:34
【问题描述】:

您好,我已经开发了水平镜像/翻转 8 bpp .BMP 图像的代码。正确处理任何宽度,不仅是 4 的倍数。现在我必须将此代码转换为相同但为 1 bpp 。使用 x86 的 bmp 图像(灰度)。困难的部分是我不知道如何超越个别位也许有人可以编辑这段代码..

        section     .text
    global      mirrorbmp8
mirrorbmp8:
    push        ebp
    mov     ebp, esp
    push        ebx
    push        esi
    push        edi

    mov     ebx, [ebp+12]       ;width - without padding
    and     ebx, 11b
    je      init            ;checking if there is a padding
    mov     edi, 4
    sub     edi, ebx
    add     [ebp+12], edi       ;width - with padding

init:
    mov     ebx, [ebp+16]   
    ;calculating the distance between top&bottom pixel
    dec     ebx
    mov     eax, [ebp+12]
    mul     ebx
    mov     esi, eax

    mov     edi, [ebp+8]    ;the first bottom pixel
    mov     edx, edi            ;the first top pixel
    mov     eax, edi
    add     eax, esi
    mov     ecx, [ebp+12]   
            ;register responsible for calc left columns

loop0:
    push        esi
    mov     esi, [ebp+12]

loop1:
    mov     bl, [edi]               ;changing pixels
    xchg        bl, [eax]
    mov     [edi], bl

    add     edi, esi        ;next pixel in this column
    sub     eax, esi
    cmp     edi, eax
    jl      loop1


    inc     edx             ;next bottom pixel
    mov     edi, edx

    mov     eax, edi                ;next top pixel
    pop     esi
    add     eax, esi

    dec     ecx         ;decrement number of columns left
    jnz     loop0           ;was that the last column?



end:
    pop     edi
    pop     esi 
    pop     ebx

    mov     esp, ebp
    pop     ebp
    ret

任何帮助将不胜感激。 在此先感谢:)

p.s 如果我能做这个版本,那么我也必须将整个代码转换为 x86-64 版本,这方面的任何提示也会有所帮助..

【问题讨论】:

  • 在我看来,代码是垂直翻转图像,而不是水平翻转。我错过了什么吗?
  • 这是用于水平翻转而不是垂直:)

标签: assembly image-processing bitmap x86 x86-64


【解决方案1】:

如果您想知道如何从左到右而不是从上到下翻转图像,请按照以下方法操作。

首先,将位图的标题复制到另一个文件中。接下来,计算每条扫描线末尾有多少位超过 imageWidth % 32:

orphanBits = imageWidth % 32

在下面的示例中,orphanedBits 为 19。将扫描线末尾的最后两个 DWORD 读入两个通用寄存器:

ebx = 10001010 11010101 00101010 10101010
eax = 01010101 01011000 00000000 00000000
  END OF SCAN LINE ^

使用 SHRD 操作数将位从 ebx 移动到 ecx 直到整个寄存器被填满:

shrd eax, ebx, orphanBits

ebx = 00000000 00000000 00010001 01011010
eax = 10100101 01010101 01001010 10101011
                       END OF SCAN LINE ^

然后使用以下代码交换eax的位:

mov edx,eax
shr eax,1
and edx,055555555h
and eax,055555555h
lea eax,[2*edx+eax]
mov edx,eax
shr eax,2
and edx,033333333h
and eax,033333333h
lea eax,[4*edx+eax]
mov edx,eax
shr eax,4
and edx,0F0F0F0Fh
and eax,0F0F0F0Fh
shl edx,4
add eax,edx
bswap eax

eax = 11010101 01010010 10101010 10100101
      ^ END OF SCAN LINE

将调整后的 DWORD(现在以相反的顺序)写入新图像。重复直到读取整个扫描线。重复直到读取所有扫描线。

编辑:在我记得它交换字节之前,最初只是 bswap,而不是比特。

【讨论】:

    【解决方案2】:

    位图存储在扫描线中,每条扫描线有一行像素。您真正需要做的就是颠倒这些行的顺序。第一步是将位图的标题复制到另一个文件中。然后你应该计算每条扫描线的长度。因为每条扫描线都是 32 位填充的,所以您需要一些数学运算:

    scanlineLength = imageWidth / 8
    IF imageWidth % 32 != 0
      scanlineLength += 1
    ENDIF
    

    接下来,将 scanlineLength 字节从旧文件复制到新文件中。向上移动一条扫描线并重复该过程,直到它们都被复制。

    编辑:重读您的问题后,我仍然不确定您以哪种方式翻转图像,所以我不确定这是否适用。

    【讨论】:

    • 我正在水平翻转图像,我唯一想知道的是如何为 1 bpp 图像执行此操作,因为在 x86 寄存器中无法访问单个位最小的寄存器是 8 位。
    猜你喜欢
    • 2011-06-09
    • 2019-10-18
    • 1970-01-01
    • 1970-01-01
    • 2019-11-26
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    相关资源
    最近更新 更多