Page 1 of 1

Gradient color algorithm

Posted: Thu Oct 03, 2013 11:54 pm
by trolly
hi all,

i wrote a function to draw a gradient color rectangle (vertical gradient);but i think it should be optimized:
can someone help me with this?

Code: Select all

;void VerticalGradient(x1,y1,x2,y2,c1,c2)
.VerticalGradient:
    push ebp
    mov ebp,esp
    pusha

;; save the values
    mov eax,[ebp+8]   ;end color
    mov [.tmp_bcolor],eax  
    mov eax,[ebp+12] ; start color
    mov [.tmp_color],eax
    mov eax,[ebp+16]  ;y2
    mov [.tmp_y2],eax
    mov eax,[ebp+20]   ;x2
    mov [.tmp_x2],eax  
    mov eax,[ebp+24]   ;y1
    mov [.tmp_y1],eax
    mov eax,[ebp+28]   ;x1
    mov [.tmp_x1],eax

;compute the y difference
    mov eax,[.tmp_y2]
    cmp eax,[.tmp_y1]
    ja @f
        mov ebx,[.tmp_y1]
        mov [.tmp_y1],eax
        mov [.tmp_y2],ebx
    @@:
    mov eax,[.tmp_y2]
    sub eax,[.tmp_y1]
    mov [.diff_y],eax

;begin of loop (for tmp_y = tmp_y1;tmp_y< tmp_y2;tmp_y++)
    mov edx,[.tmp_y1]
    .forY1:
    cmp edx,[.tmp_y2]
    jnb .nextY1
        mov [.tmp_y],edx
        ;new value for red
        mov ebx,[.tmp_color]
        shr ebx,16
        mov ecx,[.tmp_bcolor]
        shr ecx,16
        cmp ebx,ecx
        jnb @f
            sub ecx,ebx ;  ;red should be incremented
            mov [.red_inc],0x1
        jmp .endred1
        @@:
            sub ebx,ecx      ;red will be decremented
            mov [.red_inc],0x0
            mov ecx,ebx
        .endred1:

        ;new red_step= (tmp_y-tmp_y1) * ( (red2 - red1)/diff_y )
        mov eax,ecx
        cmp [.diff_y],0x0
        jna @f
            push edx
            xor edx,edx
            mov ebx,[.diff_y]
            div ebx
            pop edx
            push edx
            sub edx,[.tmp_y1]
            imul eax,edx
            pop edx
        @@:
        shl eax,16
        and eax,0xff0000
        mov [.red_step],eax

        ;same for green
        mov ebx,[.tmp_color]
        shr ebx,8
        and ebx,0xff
        mov ecx,[.tmp_bcolor]
        shr ecx,8
        and ecx,0xff
        cmp ebx,ecx
        jnb @f
            sub ecx,ebx ;ecx contains red
            mov [.green_inc],0x1
            jmp .endgreen1
        @@:
            sub ebx,ecx
            mov [.green_inc],0x0
            mov ecx,ebx
        .endgreen1:
        mov eax,ecx
        cmp [.diff_y],0x0
        jna @f
            push edx
            xor edx,edx
            mov ebx,[.diff_y]
            div ebx
            pop edx
            push edx
            sub edx,[.tmp_y1]
            imul eax,edx
            pop edx
        @@:
        shl eax,8
        and eax,0x00ff00
        mov [.green_step],eax

;same for blue
        mov ebx,[.tmp_color]
        and ebx,0xff
        mov ecx,[.tmp_bcolor]
        and ecx,0xff
        cmp ebx,ecx
        jnb @f
            sub ecx,ebx ;ecx contains red
            mov [.blue_inc],0x1
            jmp .endblue1
        @@:
        sub ebx,ecx
        mov [.blue_inc],0x0
        mov ecx,ebx
        .endblue1:
        mov eax,ecx
        cmp [.diff_y],0x0
        jna @f
            push edx
            xor edx,edx
            mov ebx,[.diff_y]
            div ebx
            pop edx
            push edx
            sub edx,[.tmp_y1]
            imul eax,edx
            pop edx
        @@:
        and eax,0x0000ff
        mov [.blue_step],eax

       ;new color.red = tmp_color.red+red_step   or tmp_color.red-red.step (in case of red_inc=0)
        mov eax,[.tmp_color]
        and eax,0xff0000
        cmp [.red_inc],0x1
        jne @f
            add eax,[.red_step]
            jmp .suite_red1
        @@:
            sub eax,[.red_step]
        .suite_red1:
        and eax,0xff0000     
        mov [.red_step],eax

        ;same for green
        mov eax,[.tmp_color]
        and eax,0x00ff00
        cmp [.green_inc],0x1
        jne @f
            add eax,[.green_step]
            jmp .suite_green1
        @@:
            sub eax,[.green_step]
        .suite_green1:
        and eax,0x00ff00
        mov [.green_step],eax

 ;same for blue
        mov eax,[.tmp_color]
        and eax,0x0000ff
        cmp [.blue_inc],0x1
        jne @f
            add eax,[.blue_step]
            jmp .suite_blue1
        @@:
            sub eax,[.blue_step]
        .suite_blue1:
        and eax,0x0000ff
        mov [.blue_step],eax

;combine colors
        mov eax,[.red_step]
        mov ebx,[.green_step]
        mov ecx,[.blue_step]
        or eax,ebx
        or eax,ecx
        DrawLine [.tmp_x1],[.tmp_y],[.tmp_x2],[.tmp_y],eax 
;next line
    mov edx,[.tmp_y]
    inc edx
    jmp .forY1
    .nextY1:

popa
mov esp,ebp
pop ebp
ret 24  ;return and remove the stack parameters

Re: Gradient color algorithm

Posted: Fri Oct 04, 2013 3:20 pm
by trolly
Finaly solved using mmx instructions.

I did like the apha blending sample, but instead of the alpha value, it's the Delta from the start Y
(delta = (Y / DiffY) * 256)

Re: Gradient color algorithm

Posted: Fri Oct 04, 2013 3:25 pm
by Mario_r4
You can see my code to ColorDialog.