【发布时间】: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