Author Topic: Magnifyingglass effect  (Read 950 times)

0 Members and 1 Guest are viewing this topic.

Offline Paul

  • Pentium
  • *****
  • Posts: 1490
  • Karma: 47
    • View Profile
Magnifyingglass effect
« on: October 06, 2007 »


Hi
Here's a lens effect that i made, could probably get it more optimised, but i don't know how :(
Used Mike_g's colourblend, hope thats ok.

Use the mousewheel or up and down to change the magnification

Code: [Select]
Const gx=1024,gy=768
Graphics gx,gy,32,1
SetBuffer BackBuffer()


Dim buffer(gx,gy)

Local image=LoadImage("C:\Users\paul\Desktop\Paul\mekis0fx200g1a.jpg")
If image=0 Then RuntimeError("Image failed to load")

If ImageWidth (image)>gx Then BX=gx-1 Else bx=ImageWidth (image)-1;check to see that we don't load an image thats bigger than our aray(x)
If ImageHeight(image)>gy Then By=gy-1 Else by=ImageHeight(image)-1;-----------------------------------!!------------------------------(y)


LockBuffer ImageBuffer(image);copy image inteo an array
For x=0 To bx
For y=0 To by
buffer(x,y)=ReadPixelFast(x,y,ImageBuffer(image))
Next
Next
UnlockBuffer ImageBuffer(image)


Global r#=50
While Not KeyHit(1)
DrawImage(image,0,0)


r#=r#+KeyDown(208)-KeyDown(200)+MouseZSpeed()
If KeyHit(203)+KeyHit(205) Then r#=60

LockBuffer
magnify(200,MouseX(),MouseY())
UnlockBuffer

Text 0,20,r#-50
;-------------------------------------------------------------------------
frame=frame+1;FPS timer
If MilliSecs()>time
time=MilliSecs()+1000
frames=frame
frame=0
EndIf
Text 0,0,"FPS:"+frames
;-------------------------------------------------------------------------
Flip 0
Cls
Wend


Function magnify(radius,cx,cy)
Local x,y,half_row_width,tx,ty,ang#,dist#
Local tx2#,ty2#

For y=-radius To radius
half_row_width=Sqr(radius^2-y^2)
For x=-half_row_width To half_row_width
tx=(cx+x) ;Get the current x drawing position
ty=(cy+y) ;Get the current y drawing position

ang#=ATan2(x,y) ;get the angle betwen the centre and the current pixel being drawn
;dist#=Sin(Sqr(x*x+y*y)/0.5)*(100)
dist#=(x*x+y*y)/500+Sqr(x*x+y*y)*r#/100 ;Get the distance ----------------------!!-------------------------

If tx>0 And ty>0 And tx<gx And ty<gy ;make sure we arent drawing outside the screen
tx2#=cx+Sin(ang)*dist ;precalcute the x
ty2#=cy+Cos(ang)*dist ; and y position
If tx2#>0 And tx2#<gx And ty2#>0 And ty2#<gy ; make sure we arent readin from outside the screen
x1=Floor(tx2#) ;Get the low  x cordinate
x2=Ceil (tx2#) ;Get the high x cordinate
y1=Floor(ty2#) ;Get the low  y cordinate
y2=Ceil (ty2#) ;Get the high y cordinate
col1=ColourBlend(buffer(x2,y1),buffer(x1,y1),(tx2#-x1)*256) ; blend the two colors with the difference betwen their two positions
col2=ColourBlend(buffer(x2,y2),buffer(x1,y2),(tx2#-x1)*256) ; in the x direction

col1=ColourBlend(col2,col1,(ty2#-y1)*256) ; and the y dirrection
WritePixelFast(tx,ty,col1) ; then draw it all to the screen
Else
WritePixelFast(tx,ty,0) ;if we try to draw to the screen but try to read from outside the screen then draw a black pixel
EndIf
EndIf
Next
Next

End Function


Function ColourBlend( rgb_1, rgb_2, alpha_1 );Mike_g's colour blend routine
alpha_2 = 256 - alpha_1

rb_1 = ((rgb_1 And $00FF00FF) * alpha_1) And $FF00FF00
g_1  = ((rgb_1 And $0000FF00) * alpha_1) And $00FF0000
rb_2 = ((rgb_2 And $00FF00FF) * alpha_2) And $FF00FF00
g_2  = ((rgb_2 And $0000FF00) * alpha_2) And $00FF0000

rb_1 = rb_1 + rb_2
g_1  = g_1 + g_2

Return (rb_1 Or g_1) Sar 8
End Function

« Last Edit: October 06, 2007 by Paul »
I will bite you - http://s5.bitefight.se/c.php?uid=31059
Challenge Trophies Won:

Offline p01

  • Atari ST
  • ***
  • Posts: 158
  • Karma: 51
    • View Profile
    • www.p01.org
Re: Magnifyingglass effect
« Reply #1 on: October 06, 2007 »
You can of course precalc the x&y&alpha coefs once and for all.

Offline Paul

  • Pentium
  • *****
  • Posts: 1490
  • Karma: 47
    • View Profile
Re: Magnifyingglass effect
« Reply #2 on: October 07, 2007 »
Thats a good ide, why didn't i think of that?
I will bite you - http://s5.bitefight.se/c.php?uid=31059
Challenge Trophies Won:

Offline Paul

  • Pentium
  • *****
  • Posts: 1490
  • Karma: 47
    • View Profile
Re: Magnifyingglass effect
« Reply #3 on: October 07, 2007 »
Got that implemented, and it's like 4x faster thx allot :)
And made the colourblend function inline. these two changes made if 5x faster than the original!
Hold the first mousebutton down to use the precalculated function instead of the other one.
Any thing else i can do to make it faster?

Code: [Select]
Const gx=1024,gy=768
Graphics gx,gy,32
SetBuffer BackBuffer()


Dim buffer(gx,gy)

Local image=LoadImage("C:\Users\paul\Desktop\Paul\mekis0fx200g1a.jpg")
If image=0 Then RuntimeError("Image failed to load")

If ImageWidth (image)>gx Then BX=gx-1 Else bx=ImageWidth (image)-1;check to see that we don't load an image thats bigger than our aray(x)
If ImageHeight(image)>gy Then By=gy-1 Else by=ImageHeight(image)-1;-----------------------------------!!------------------------------(y)


LockBuffer ImageBuffer(image);copy image inteo an array
For x=0 To bx
For y=0 To by
buffer(x,y)=ReadPixelFast(x,y,ImageBuffer(image))
Next
Next
UnlockBuffer ImageBuffer(image)

Global r#=50,size=200
magnifyPC(size)

While Not KeyHit(1)
DrawImage(image,0,0)

r#=MouseZ()+50
If MouseZSpeed() Then magnifyPC(size)



LockBuffer

If MouseDown(1)
magnifyP(size,MouseX(),MouseY())
Else
magnify(size,MouseX(),MouseY())
EndIf


UnlockBuffer

;-------------------------------------------------------------------------
frame=frame+1;FPS timer
If MilliSecs()>time
time=MilliSecs()+1000
frames=frame
frame=0
EndIf
Text 0,0,"FPS:"+frames
;-------------------------------------------------------------------------
Flip 0
Cls
Wend
Dim magny#(0,0)
Dim magny2(0,0)
Function magnifyPC(radius)
Local x,y,half_row_width,tx,ty,ang#,dist#
Local tx2#,ty2#
Dim magny#(Ceil((radius+1)^2*Pi),1)
Dim magny2(Ceil((radius+1)^2*Pi),3)
DebugLog Ceil(radius^2*Pi)
TR#=r#/Float(100)
del#=Float(1)/500
For y=-radius To radius
half_row_width=Sqr(radius^2-y^2)
For x=-half_row_width To half_row_width
tx=(cx+x) ;Get the current x drawing position
ty=(cy+y) ;Get the current y drawing position
i=i+1
ang#=ATan2(x,y) ;get the angle betwen the centre and the current pixel being drawn
;dist#=Sin(Sqr(x*x+y*y)/0.5)*(100)
dist#=Float(x*x+y*y)*del+Sqr(x*x+y*y)*TR#;r#/100 ;Get the distance ----------------------!!-------------------------
;dist=Sin(Sqr((x*x+y*y)*0.45)+40)*Sqr((x*x+y*y))

tx2#=cx+Sin(ang)*dist ;precalcute the x
ty2#=cy+Cos(ang)*dist

x1=Floor(tx2#) ;Get the low  x cordinate
;x2=Ceil (tx2#) ;Get the high x cordinate
y1=Floor(ty2#) ;Get the low  y cordinate
;y2=Ceil (ty2#) ;Get the high y cordinate
magny(i,0)=tx2# ;Svae the x read value
magny(i,1)=ty2# ;and teh y read value
magny2(i,0)=x1 ;save x nd y values for blending
;magny2(i,1)=x2 ;...
magny2(i,1)=y1 ;...
;magny2(i,3)=y2 ;...
Next
Next

End Function

Function magnifyP(radius,cx,cy)
Local x,y,half_row_width,tx,ty,i
Local tx2#,ty2#
Local rgb_1,rgb_2,alpha_1,alpha_2,x1,x2,y1,y2,col1

For y=-radius To radius
half_row_width=Sqr(radius^2-y^2)
For x=-half_row_width To half_row_width
tx=(cx+x) ;Get the current x drawing position
ty=(cy+y) ;Get the current y drawing position
i=i+1

If tx>0 And ty>0 And tx<gx And ty<gy ;make sure we arent drawing outside the screen
tx2#=magny(i,0)+cx;+Sin(ang)*dist ;precalcute the x
ty2#=magny(i,1)+cy;+Cos(ang)*dist ; and y position
If tx2#>0 And tx2#<gx And ty2#>0 And ty2#<gy ; make sure we arent readin from outside the screen
x1=magny2(i,0)+cx;Floor(tx2#) ;Get the low  x cordinate
x2=x1+1
y1=magny2(i,1)+cy;Floor(ty2#) ;Get the low  y cordinate
y2=y1+1

;col1=ColourBlend(buffer(x2,y1),buffer(x1,y1),(tx2#-x1) *256) ; blend the two colors with the difference betwen their two positions
;col2=ColourBlend(buffer(x2,y2),buffer(x1,y2),(tx2#-x1) *256) ; in the x direction
;col1=ColourBlend(col2,col1,(ty2#-y1) *256) ; and the y dirrection

;-------------------------------------------------------------------------Blending
rgb_1=buffer(x2,y1)
rgb_2=buffer(x1,y1)

alpha_1=(tx2#-x1) *256
alpha_2=256-alpha_1

col1=(((((rgb_1 And $00FF00FF) * alpha_1) And $FF00FF00)+(((rgb_2 And $00FF00FF) * alpha_2) And $FF00FF00)) Or ((((rgb_1 And $0000FF00) * alpha_1) And $00FF0000)+(((rgb_2 And $0000FF00) * alpha_2) And $00FF0000))) Sar 8

rgb_1=buffer(x2,y2)
rgb_2=buffer(x1,y2)
rgb_1=(((((rgb_1 And $00FF00FF) * alpha_1) And $FF00FF00)+(((rgb_2 And $00FF00FF) * alpha_2) And $FF00FF00)) Or ((((rgb_1 And $0000FF00) * alpha_1) And $00FF0000)+(((rgb_2 And $0000FF00) * alpha_2) And $00FF0000))) Sar 8
rgb_2=col1

alpha_1=(ty2#-y1) *256
alpha_2=256-alpha_1
col1=(((((rgb_1 And $00FF00FF) * alpha_1) And $FF00FF00)+(((rgb_2 And $00FF00FF) * alpha_2) And $FF00FF00)) Or ((((rgb_1 And $0000FF00) * alpha_1) And $00FF0000)+(((rgb_2 And $0000FF00) * alpha_2) And $00FF0000))) Sar 8
;-------------------------------------------------------------------------

WritePixelFast(tx,ty,col1) ; then draw it all to the screen
Else
WritePixelFast(tx,ty,0) ;if we try to draw to the screen but try to read from outside the screen then draw a black pixel
EndIf
EndIf
Next
Next

End Function


Function magnify(radius,cx,cy)
Local x,y,half_row_width,tx,ty,ang#,dist#
Local tx2#,ty2#

For y=-radius To radius
half_row_width=Sqr(radius^2-y^2)
For x=-half_row_width To half_row_width
tx=(cx+x) ;Get the current x drawing position
ty=(cy+y) ;Get the current y drawing position
i=i+1
ang#=ATan2(x,y) ;get the angle betwen the centre and the current pixel being drawn
;dist#=Sin(Sqr(x*x+y*y)/0.5)*(100)
;dist#=(x*x+y*y)/500+Sqr(x*x+y*y)*r#/100 ;Get the distance ----------------------!!-------------------------
dist#=Float(x*x+y*y)/500+Sqr(x*x+y*y)*r#/100

If tx>0 And ty>0 And tx<gx And ty<gy ;make sure we arent drawing outside the screen
tx2#=cx+Sin(ang)*dist ;precalcute the x
ty2#=cy+Cos(ang)*dist ; and y position
If tx2#>0 And tx2#<gx And ty2#>0 And ty2#<gy ; make sure we arent readin from outside the screen
x1=Floor(tx2#) ;Get the low  x cordinate
x2=Ceil (tx2#) ;Get the high x cordinate
y1=Floor(ty2#) ;Get the low  y cordinate
y2=Ceil (ty2#) ;Get the high y cordinate
col1=ColourBlend(buffer(x2,y1),buffer(x1,y1),(tx2#-x1)*256) ; blend the two colors with the difference betwen their two positions
col2=ColourBlend(buffer(x2,y2),buffer(x1,y2),(tx2#-x1)*256) ; in the x direction

col1=ColourBlend(col2,col1,(ty2#-y1)*256) ; and the y dirrection
WritePixelFast(tx,ty,col1) ; then draw it all to the screen
Else
WritePixelFast(tx,ty,0) ;if we try to draw to the screen but try to read from outside the screen then draw a black pixel
EndIf
EndIf
Next
Next

End Function


Function ColourBlend( rgb_1, rgb_2, alpha_1 )
alpha_2 = 256 - alpha_1

;rb_1 = ((((rgb_1 And $00FF00FF) * alpha_1) And $FF00FF00)+(((rgb_2 And $00FF00FF) * alpha_2) And $FF00FF00))
;g_1  = ((((rgb_1 And $0000FF00) * alpha_1) And $00FF0000)+(((rgb_2 And $0000FF00) * alpha_2) And $00FF0000))
;rb_2 = (((rgb_2 And $00FF00FF) * alpha_2) And $FF00FF00)
;g_2  = (((rgb_2 And $0000FF00) * alpha_2) And $00FF0000)

;rb_1 = rb_1 + rb_2
;g_1  = g_1 + g_2
Return (((((rgb_1 And $00FF00FF) * alpha_1) And $FF00FF00)+(((rgb_2 And $00FF00FF) * alpha_2) And $FF00FF00)) Or ((((rgb_1 And $0000FF00) * alpha_1) And $00FF0000)+(((rgb_2 And $0000FF00) * alpha_2) And $00FF0000))) Sar 8
;Return (rb_1 Or g_1) Sar 8
End Function


« Last Edit: October 07, 2007 by Paul »
I will bite you - http://s5.bitefight.se/c.php?uid=31059
Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7145
  • Karma: 69
    • View Profile
Re: Magnifyingglass effect
« Reply #4 on: October 07, 2007 »
Nice one Paul :)
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 16787
  • Karma: 439
  • evil/good
    • View Profile
    • My Homepage
Re: Magnifyingglass effect
« Reply #5 on: October 07, 2007 »
Good karma for Paul and P01!  :)
Shockwave ^ Codigos
Challenge Trophies Won:

Offline mike_g

  • Amiga 1200
  • ****
  • Posts: 435
  • Karma: 34
    • View Profile
Re: Magnifyingglass effect
« Reply #6 on: October 09, 2007 »
Lol I'd hardly call it 'My' colour blending function. After all stonemonkey told me how to do it all :P

Its a nice effect :) Dident notice too much of a difference with the look up tables tho, like +2 fps. But lookup tables are good no doubt.

Cheers.

Offline Paul

  • Pentium
  • *****
  • Posts: 1490
  • Karma: 47
    • View Profile
Re: Magnifyingglass effect
« Reply #7 on: October 09, 2007 »
whats your fps from the beggining mike_g?
Mine, in the version without tables if 24 and the one withjout 125, and thats a pretty big difference.
I will bite you - http://s5.bitefight.se/c.php?uid=31059
Challenge Trophies Won:

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1215
  • Karma: 92
    • View Profile
Re: Magnifyingglass effect
« Reply #8 on: October 09, 2007 »
Nice work paul. For the 2 ways, i get around 10fps and 42 fps.

I've been doing it something like this although it probably won't make much difference:

Code: [Select]
;everything is (unsigned) integer except x_fraction and y_fraction

x_blend=(255.0*x_fraction)+1
y_blend=(255.0*y_fraction)+1


top_l_blend=(x_blend*(257-y_blend))shr 8
top_r_blend=((257-x_blend)*(257-y_blend))shr 8
bot_l_blend=(x_blend*y_blend)shr 8
bot_r_blend=((257-x_blend)*y_blend)shr 8


r_b=(((argb0 and $ff00ff)*top_l_blend)+((argb1 and $ff00ff)*top_r_blend)+((argb2 and $ff00ff)*bot_l_blend)+((argb3 and $ff00ff)*bot_r_blend))and $ff00ff00

g__=(((argb0 and $ff00)*top_l_blend)+((argb1 and $ff00)*top_r_blend)+((argb2 and $ff00)*bot_l_blend)+((argb3 and $ff00)*bot_r_blend))and $ff0000

argb_out=(r_b or g__)shr 8

It calculates the weights for each of the 4 pixels first.