【问题标题】:Linear interpolation of pixel color between its original color and white based on square of its distance from the point x,y基于与点 x,y 距离的平方,像素颜色在其原始颜色和白色之间的线性插值
【发布时间】:2015-01-31 19:14:27
【问题描述】:

我需要帮助以了解以下任务中线性插值的正确算法:

将 24 bpp .BMP 图像淡化为白色,以便每个像素的颜色根据其距离的平方在其原始颜色和白色之间线性插值,该距离由其 x 和 y 坐标指定的点。假设 x, y 位于图像内。平方距离 >= dist 的像素不会褪色。

我需要在 x86 程序集中实现它。

我对此的想法是我需要做以下事情:

  • 用坐标 (x,y) 计算某个像素(点)与参考点 (xr,yr) 之间的距离差。为此,我需要计算 dx = |xr - x|,还有 dy = |yr - y|然后计算dx^2和dy^2,所以其实我不需要dx和dy的绝对值。
  • 计算 d^2 = dx^2 + dy^2
  • 然后使用适当的算法计算像素的颜色。

我试图实现一些算法,但我发现它不正确。

提前感谢您的帮助:)

编辑:

这是我执行此任务的代码:

    section .text
    global _sunfade

; arguments
%define img     [ebp+8]
%define width   [ebp+12]
%define height  [ebp+16]
%define dist    [ebp+20]
%define xc      [ebp+24]
%define yc      [ebp+28]

; local variables
%define row_bytes   [ebp-4]
%define dx_2    [ebp-8]
%define dy_2    [ebp-12]
%define d_2     [ebp-16]
%define lvl     [ebp-20]
%define x       [ebp-24]
%define y       [ebp-28]
%define dist_2  [ebp-32]


_sunfade:
    ; stack frame
    push    ebp
    mov     ebp, esp
    sub     esp, 32

    ; save required registers
    push    ebx
    push    esi
    push    edi

    ; source image data address
    mov     esi, img

    ; calculate row size
    mov     eax, width      ; row size in pixels
    imul    eax, 3      ; row size* in bytes (3 bytes per pixel)
    add     eax, 3      ; 3 is the maximum value to fit on 2 least sign. bits
    and     eax, 0fffffffch ; zero out 2 least sign. bits, to round up to multiple of 4

    mov     row_bytes, eax  ; row size in bytes (multiple of 4, padding handled)

    ; source pixels data address
    add     esi, 54

    ; lines counter
    mov     ecx, height     ; ecx stores lines amount left


;=================================================================================================
;   ------------ Begining of the algorithm ---------------- 

_line:
    ; line pixel count - pixels left to proceed
    mov     edi, width      ; set / restet pixels to proceed
        ; counter of pixels left to procede in a line

    ; pixel index in a line - current pixel
    xor     ebx, ebx        ; reset index
        ; ebx = x
_fade:

    push    edx
    push    ebx

    xor     edx, edx

    mov     eax, ebx
    mov     ebx, 3
    div     ebx     
    mov     x, eax  ; x coordnate


    mov     eax, height
    sub     eax, ecx    ; y = height - lines amount left
    mov     y, eax      ; y coordinate


    mov     eax, xc
    sub     eax, x      ; eax = dx = xc - x
    imul    eax, eax    ; eax = dx^2 (dx * dx)
    mov     dx_2, eax   ; dx_2 = dx^2


    mov     eax, yc
    sub     eax, y      ; eax = dy = yc -y  
    imul    eax, eax    ; eax = dy^2 (dy * dy)
    mov     dy_2, eax   ; dy_2 = dy^2


    mov     eax, dist
    imul    eax, eax    ; eax = dist^2 (dist * dist)
    mov     dist_2, eax


    pop     ebx
    pop     edx

    mov     eax, dx_2
    add     eax, dy_2   ; eax = (dx^2 +dy^2) 
    mov     d_2, eax        ; d_2 = d^2 = (dx^2 +dy^2) 
    cmp     eax, dist_2     ; d^2 - dist^2
    jae     _next_pix   ; if d^2 >= dist^2 then jump to _next_pix, to not change color of this pixel

    xor     edx, edx

;=================================================================================================  
;   ---------- PIXEL OPERATIONS START ----------

    ; saving counters
    push    ecx ; counter of lines to proceed
    push    ebx ; pixel index in a line - current pixel


    mov     eax, d_2
    mov     ebx, dist_2
    div     ebx         ; eax = d^2 / dist^2

    mov     ebx, 1
    sub     ebx, eax    ; fading coeficient = 1 - (d^2 / dist^2)

        ;mov    eax, 256 
        ;imul   ebx, eax
    mov     ecx, ebx    ; ecx = fading coefficient

    pop     ebx
    ;pop        eax 

    movzx   edx, byte [esi+ebx+0]   ; getting the current color (its Blue coefficient)

    mov     eax, edx    ; eax current color
    imul    eax, ecx    ; fadded color = current collor * fading coefficient

        ;add        eax, ecx
        ;shr        eax, 1
            ;add    eax, edx 

    mov     [esi+ebx+0], al     ; saving faded color (its Blue coefficient)

;=================================================================================================

    push    ebx ; pixel index in a line - current pixel


    mov     eax, d_2
    mov     ebx, dist_2
    div     ebx         ; eax = d^2 / dist^2

    mov     ebx, 1
    sub     ebx, eax    ; fading coeficient = 1 - (d^2 / dist^2)

        ;mov        eax, 256
        ;imul   ebx, eax
    mov     ecx, ebx    ; ecx = fading coefficient

    pop     ebx

    movzx   edx, byte [esi+ebx+1]   ; getting the current color (its Green coefficient)

    mov     eax, edx    ; dx = current color
    imul    eax, ecx    ; fadded color = current collor * fading coefficient


        ;add        eax, ecx
        ;shr        eax, 1
            ;add    eax, edx 

    mov     [esi+ebx+1], al     ; saving faded color (its Green coefficient)

;=================================================================================================  

    push    ebx ;  pixel index in a line - current pixel


    mov     eax, d_2
    mov     ebx, dist_2
    div     ebx         ; eax = d^2 / dist^2

    mov     ebx, 1
    sub     ebx, eax    ; fading coeficient = 1 - (d^2 / dist^2)

        ;mov        eax, 256
        ;imul   ebx, eax    
    mov     ecx, ebx    ; ecx = fading coefficient

    pop     ebx

    movzx   edx, byte [esi+ebx+2]   ; getting the current color (its Red coefficient)

    mov     eax, edx    ; dx = current color
    imul    eax, ecx    ; fadded color = current collor * fading coefficient

        ;add        eax, ecx
        ;shr        eax, 1
            ;add    eax, edx 

    mov     [esi+ebx+2], al     ; saving faded color (its Red coefficient)

    pop     ecx

;=================================================================================================  
;   ---------- PIXEL OPERATIONS END ----------

_next_pix:
    add     ebx, 3      ; next pixel    
    dec     edi         ; decrement pixels left to proceed in a line
    jnz     _fade       ; if not 0, continue to next pixel in a line


    add     esi, row_bytes  ; advance address to next line
    dec     ecx         ; decrement lines to proceed amount
    jnz     _line       ; if not 0, continut to next line

    ; restore registers
    pop     edi
    pop     esi
    pop     ebx

    ; remove stack frame
    mov     esp, ebp
    pop     ebp
    ; return from procedure
    ret

它正确地选择了改变像素颜色的区域,但是颜色改变了,并且没有褪色。我的褪色算法不正确。

你知道正确的算法是什么样的吗?

编辑2: 一种颜色的代码更改部分:

;   ---------- PIXEL OPERATIONS START ----------

    ; saving counters
    push    ecx ; counter of lines to proceed
    push    ebx ; pixel index in a line - current pixel


    mov     eax, d_2
    mov     ebx, dist_2
    div     ebx         ; eax = d^2 / dist^2

    mov     ebx, 1
    sub     ebx, eax    ; fading coeficient = 1 - (d^2 / dist^2)

        mov     eax, 256 
        imul    ebx, eax ; ebx = fading coefficient * 256
    mov     ecx, ebx    ; ecx = fading coefficient

    pop     ebx

    movzx   edx, byte [esi+ebx+0]   ; getting the current color (its Blue coefficient)

    mov     eax, edx    ; eax current color
    imul    eax, ecx    ; fadded color = current collor * fading coefficient

        shr     eax, 8 ; faded color / 256

            add     eax, edx ; new_color = current_color + (faded color/256)

    mov     [esi+ebx+0], al     ; saving faded color (its Blue coefficient)

EDIT3 再次将部分更改为一种颜色: 但它不起作用......当我尝试运行它时,程序停止工作。

EDIT4 它不起作用,因为我意外删除了 pop ecx 指令...... 现在它正在绘制,类似于圆形,但拉伸到右上角的方向和左下角的方向。它有许多不同颜色的线条。嗯,长相不好形容:P

;   ---------- PIXEL OPERATIONS START ----------

    ; saving counters
    push    ecx ; counter of lines to proceed
    push    ebx ; pixel index in a line - current pixel


    mov     eax, d_2
    shl     eax, 8      ; eax = d_2 * 256
    mov     ebx, dist_2
    div     ebx         ; eax = (d^2 * 256 ) / dist^2

    mov     ebx, 256
    sub     ebx, eax    ; fading coeficient = 256 - [(d^2 * 256) / dist^2)]

    mov     ecx, ebx    ; ecx = fading coefficient

    pop     ebx

    movzx   edx, byte [esi+ebx+0]   ; getting the current color (its Blue coefficient)

    mov     eax, edx    ; eax current color
    imul    eax, ecx    ; fadded color = current collor * fading coefficient

        shr     eax, 8 ; faded color / 256

            add     eax, edx ; new_color = current_color + (faded color/256)

    mov     [esi+ebx+0], al     ; saving faded color (its Blue coefficient)

【问题讨论】:

    标签: assembly x86 linear-interpolation


    【解决方案1】:

    imul eax, ecx 将当前通道值乘以衰落系数,该系数是(或应该是?)介于 0..255 之间的值 - 实际上是一个 分数 乘以 256。因此,结果必须再次除以 256 以使其恢复到有效范围,然后再存储回来。目前,您正在存储最低、最低有效的 8 位。

    【讨论】:

    • 感谢您的回答:) 好吧,我只存储 8 位,因为它是 24 bmp 位图,所以像素的每种颜色 R、G、B 都存储在 24 位中的 8 位中总,我说的对吗?
    • 你是对的 that .. 但是乘法将结果“向上”移动了 256 倍。你应该乘以一个因子介于 0 和 1 之间,但它是“256 倍”,因此它适合整数寄存器。
    • 哦,是的。这是真的:) 那么当我将它乘以 256,然后除以 256 时,它应该在低 8 位中吗?看看修改后的代码。
    • 啊——我想我找到了你的错误的根源。您不能在常规寄存器中进行除法(d/dist)——它们都是整数!请改用 (d*256/dist)。您的 mul by 256 现在出现在除法之后,修复它为时已晚。
    • 哇,好吧,我试着那样做,但这是错误的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-10
    相关资源
    最近更新 更多