Highlighting an image (glass effect)

Just starting out? Need help? Post your questions and find answers here.
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Highlighting an image (glass effect)

Post by Michael Vogel »

some days ago, netmaestro posted a nice alarm clock which had a superb white shining area which looked like a glass...

I tried to do something like that and after a while I had the first success - an elliptical segment which is bright white in the middle and gets darker and darker to its edges.
But on thenNext step, transferring the code to alpha transparency, everything went wrong and I did not find a clue how to get it running for now :cry:

Code: Select all

Procedure.f QuickDistanz(x1.l,y1.l,x2.l)
	x1-x2
	x1*x1
	ProcedureReturn Sqr(x1+y1)
EndProcedure
Procedure GlassEffect(Image)

	Structure BGRA
		blue.c
		green.c
		red.c
		alpha.c
	EndStructure

	Protected bmp.BITMAP
	Protected *bits.BGRA,*px.BGRA

	Protected w.l,h.l
	Protected scaler.f
	Protected shifter.l
	Protected b1x.l,bx2.l
	Protected x.l,y.l,ys.l
	Protected c.b

	GetObject_(ImageID(image), SizeOf(BITMAP),bmp)

	*bits=bmp\bmBits

	; Breite und Höhe
	w=bmp\bmWidthBytes
	h=bmp\bmHeight

	; Tricksen...
	scaler=650/h
	shifter=h-h>>2

	; Brennpunkte
	bx1=w>>3
	b2x=w-b1x


	For y=0 To h
		ys=y*y*scaler

		For x=0 To w>>1

			c=(QuickDistanz(x,ys,b1x)+QuickDistanz(x,ys,b2x))-(b2x-b1x)
			If c<0
				c=0
			Else
				c*2
				If c<0
					c=0
				ElseIf c>255
					c=255
				EndIf
			EndIf

			If y%3=0
				If shifter+y/3<h
					*px=*bits+bmp\bmWidthBytes*(y/3+shifter)+x
					*px\alpha=c
					*px=*bits+bmp\bmWidthBytes*(y/3+shifter)+w-x
					*px\alpha=c
				EndIf
			EndIf
			If shifter-y>0
				*px=*bits+bmp\bmWidthBytes*(shifter-y)+x
				*px\alpha=c
				*px=*bits+bmp\bmWidthBytes*(shifter-y)+w-x
				*px\alpha=c
			EndIf
		Next x
	Next y


EndProcedure

w=200
h=100

CreateImage(0,200,100)
StartDrawing(ImageOutput(0))
Box(0,0,200,100,#Red)
DrawText(0,0,"Just a Test")
DrawText(50,30,"Just a Test")
DrawText(100,50,"Just a Test")
StopDrawing()

OpenWindow(0,0,0,w,h,"",$CF0001)
ImageGadget(0,0,0,w,h,ImageID(0))

#Glass=1
CreateImage(#Glass,200,100,32)
StartDrawing(ImageOutput(#Glass))
Box(0,0,150,100,#White)
StopDrawing()
GlassEffect(#Glass)

dc = StartDrawing(WindowOutput(0))
DrawAlphaImage(ImageID(#Glass),0,0)
StopDrawing()

Repeat:Until WaitWindowEvent()=#WM_CLOSE
Any idea how to get this stuff running?

Thanks,
Michael
Perkin
Enthusiast
Enthusiast
Posts: 504
Joined: Thu Jul 03, 2008 10:13 pm
Location: Kent, UK

Post by Perkin »

Add the following just before your DrawText commands

Code: Select all

DrawingMode(#PB_2DDrawing_Transparent)
Is that what you wanted?
%101010 = $2A = 42
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post by Fluid Byte »

Perkin wrote:Is that what you wanted?
No, he wants alpha-transparency.
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
Perkin
Enthusiast
Enthusiast
Posts: 504
Joined: Thu Jul 03, 2008 10:13 pm
Location: Kent, UK

Post by Perkin »

I think I found the clock with the effect.

Sorry for the suggestion, obviously it wasn't what he wanted.

I just ran the code, saw background of text and thought that was what he wanted.
%101010 = $2A = 42
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Post by Michael Vogel »

Slowly I'll get what I want, but there are still (at least) two problems:

- the white corners should be eleminated
- the shining effect should be smoother on the left and right border also

Michael

Code: Select all

Procedure.f QuickDistanz(x1.l,y1.l,x2.l)
	x1-x2
	x1*x1
	ProcedureReturn Sqr(x1+y1)
EndProcedure
Procedure GlassEffect(Image)

	Structure BGRA
		blue.c
		green.c
		red.c
		alpha.c
	EndStructure

	Protected bmp.BITMAP
	Protected *bits.BGRA,*px.BGRA

	Protected w.l,h.l
	Protected scaler.f
	Protected shifter.l
	Protected b1x.l,bx2.l
	Protected x.l,y.l,ys.l
	Protected c.b

	GetObject_(ImageID(image), SizeOf(BITMAP),bmp)

	*bits=bmp\bmBits


	For y=0 To bmp\bmHeight-1
		For x=0 To bmp\bmWidthBytes-1 Step 4
			*px=*bits+bmp\bmWidthBytes * y + x
			*px\alpha=128
		Next
	Next

	; Breite und Höhe
	w=bmp\bmWidthBytes>>2
	h=bmp\bmHeight

	; Tricksen...
	scaler=650/h
	shifter=h-h>>2

	; Brennpunkte
	bx1=w>>3
	b2x=w-b1x


	#MaxLight=250

	For y=0 To h
		ys=y*y*scaler

		For x=0 To w>>1

			c=(QuickDistanz(x,ys,b1x)+QuickDistanz(x,ys,b2x))-(b2x-b1x)
			If c<>9999
				c=#MaxLight-c
				If c<0
					;c=0
				ElseIf c>#MaxLight
					;c=#MaxLight
				EndIf
			Else
				c=0
			EndIf

			If y%3=0
				If shifter+y/3<h
					*px=*bits+bmp\bmWidthBytes*(y/3+shifter)+x<<2
					*px\alpha=c
					*px=*bits+bmp\bmWidthBytes*(y/3+shifter)+(w-x)<<2
					*px\alpha=c
				EndIf
			EndIf
			If (shifter-y>=0) And (shifter-y<h)
				*px=*bits+bmp\bmWidthBytes*(shifter-y)+x<<2
				*px\alpha=c
				*px=*bits+bmp\bmWidthBytes*(shifter-y)+(w-x)<<2
				*px\alpha=c
			EndIf
		Next x
	Next y


EndProcedure

w=200
h=100

CreateImage(0,200,100)
StartDrawing(ImageOutput(0))
Box(0,0,200,100,#Red)
DrawText(0,0,"Just a Test")
DrawText(50,30,"Just a Test")
DrawText(100,50,"Just a Test")
StopDrawing()

OpenWindow(0,0,0,w,h,"",$CF0001)
ImageGadget(0,0,0,w,h,ImageID(0))

#Glass=1
CreateImage(#Glass,200,100,32)
StartDrawing(ImageOutput(#Glass))
Box(0,0,200,100,#White)
StopDrawing()
GlassEffect(#Glass)

dc = StartDrawing(WindowOutput(0))
DrawAlphaImage(ImageID(#Glass),0,0)
StopDrawing()

Repeat:Until WaitWindowEvent()=#WM_CLOSE
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

still now, for a shiny partly transparent area, you have to prerender a 32bit PNG with this effect, include it, and draw it via DrawAlphaImage.

Alphadrawing may be possible via some API, but messin'round with this right now is futile...
according to freaks words, the beta of 4.4 is to expect within the next weeks and it will contain Alpha-Drawing.
oh... and have a nice day.
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Post by Michael Vogel »

Kaeru Gaman wrote:still now, for a shiny partly transparent area, you have to prerender a 32bit PNG with this effect, include it, and draw it via DrawAlphaImage.
I need to create the effect for elements with different sizes, so I'd like to create it dynamically - ResizeImage does not work here for transparent images :x

My second approach is not that bad but still needed some improvements :roll::

Code: Select all

 :
Protected c.l	INSTEAD		Protected c.b
 :
b1x=w>>3			INSTEAD		bx1=w>>3
 :
If c<#MaxLight
	c=#MaxLight-c
Else
	c=0
EndIf
Michael
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

Rectangular glass isn't difficult to achieve in code, it's basically inner dropshadows and highlights. I made custom Box and Line routines that draw at specified alphas and using these it's just a matter of drawing increasingly smaller outlined boxes at decreasing alphas. The Line version finishes the edges of the highlights. Using these simple techniques you can produce some remarkably nice glass effects. PB will probably have these native quite soon.
Last edited by netmaestro on Mon May 11, 2009 7:02 pm, edited 1 time in total.
BERESHEIT
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Post by Michael Vogel »

netmaestro wrote:Rectangular glass isn't difficult to achieve in code, it's basically inner dropshadows and highlights. I made custom Box and Line routines that draw at specified alphas and using these it's just a matter of drawing increasingly smaller boxes at decreasing alphas. The Line version finishes the edges of the highlights. Using these simple techniques you can produce some remarkably nice glass effects. PB will probably have these native quite soon.
Thanks for the information - until the new 4.40 will be available I keep my selfmade code from above (not that smooth and far away from your results :?)...

Here it is - the "Glaseffekt" slider have to be changed in the configuration dialog to see the effekt

Michael
dige
Addict
Addict
Posts: 1391
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

Post by dige »

I can now only see the PureBasic Logo, the next screen is dark...
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Post by Michael Vogel »

dige wrote:I can now only see the PureBasic Logo, the next screen is dark...
@%&! - changed quite a lot in my source code and it works fine started from the editor because a different ini file (in the temp directory) is used :evil:

Sorry 'bout that - you can do a hack (add the line "smooth=0" to the ini file) or download the new exe now...

Michael
User avatar
einander
Enthusiast
Enthusiast
Posts: 744
Joined: Thu Jun 26, 2003 2:09 am
Location: Spain (Galicia)

Post by einander »

Hi Michael:
May be this helps

Code: Select all

; Gdip Elliptic Light
; by einander
; PB 4.30 - may 11/2009 
#GDIP=0
#DEGTORAD=#PI/180.0
Global _GDIP,_GRAPH,_DRAWING

Structure PointF :  X.F : Y.F : EndStructure
Structure ARRL :  A.L[3] : EndStructure 

Structure GdiplusStartupInput
  GdiPlusVersion.L
  DebugEventCallback.L
  SuppressBackgroundThread.L
  SuppressExternalCodecs.L
EndStructure

Macro MMx :  WindowMouseX(EventWindow()) : EndMacro
Macro MMy :  WindowMouseY(EventWindow()) : EndMacro
  
Macro RGB2ARGB(RGB,Alpha=$FF) ;- RGB2ARGB(RGB,Alpha=$FF) - convert RGB to Alpha RGB
  Blue(RGB)|Green(RGB)<<8|Red(RGB)<<16|Alpha<<24
EndMacro

Macro ARGB(RGB=0,Alpha=255)  ;- ARGB((RGB=0,Alpha=255)
  RGB2ARGB(RGB,Alpha)
EndMacro 

Prototype GdiplusStartup(*a,*b,C=0)
Macro GName : GetFunction(#GDIP,Name) : EndMacro   ;- Gname
Prototype P1(A) : Macro M1(Name,A) : GF.P1=GName:GF(A) :EndMacro 
Prototype p2(A,B) : Macro M2(Name,A,B) : GF.P2=GName:GF(A,B) :EndMacro
Prototype P3(A,B,C) : Macro M3(Name,A,B,C) : GF.P3=GName:GF(A,B,C) :EndMacro
Prototype P4(A,B,C,D) : Macro M4(Name,A,B,C,D) : GF.P4=GName:GF(A,B,C,D) :EndMacro

Procedure  GradBrushF(Array Points.PointF(1),Sides,ARGB1,ARGB2,ARGB3)
  blend.ARRL\A[0]=ARGB1
  blend\A[1]=ARGB2
  blend\A[2]=ARGB3
  M4("GdipCreatePathGradient",@Points(),Sides,1,@GpBrush)
  M2("GdipSetPathGradientCenterColor",GpBrush,ARGB3)
  Le=2  ;number of colors to blend
  M3("GdipSetPathGradientSurroundColorsWithCount", GpBrush, blend, @Le)
  ProcedureReturn GpBrush
EndProcedure 

Procedure GdipPolygonFree(Sides,ARRAY Pf.PointF(1),Rim.F=1,ARGB1=0,ARGB2=$FFFFFF,ARGB3=0,Type=1)
  GpBrush=GradBrushF(Pf(),Sides,ARGB2,ARGB2,ARGB3) 
  M4("GdipFillPolygon2",_GRAPH, GpBrush, @Pf(),Sides)
  M1("GdipDeleteBrush",GpBrush)
EndProcedure

Macro DrawGDIP ;- DrawGDIP ; make new _GRAPH 
  If _GRAPH :  M1("GdipDeleteGraphics",_GRAPH) : EndIf
  M2("GdipCreateFromHDC",_DRAWING, @_GRAPH)
  M2("GdipSetSmoothingMode",_GRAPH,2)  ; 2 = HiRes
EndMacro

Procedure AngleF(X,Y,Ang.F,xRadius,yRadius,*P.PointF) ; Ret  elliptic endpoint 
  *P\X = X+Cos(Ang*#DEGTORAD) * xRadius 
  *P\Y = Y+Sin(Ang*#DEGTORAD) * yRadius
EndProcedure 

Procedure GdipEllipticLight(X,Y,RadX,RadY,ARGB,BkRGB=0,Stps=90)
  STP.F=360/Stps
  Dim pt.PointF(Stps)
  For i=0 To Stps
    AngleF(X,Y,i*STP,RadX,RadY,pt(i))
  Next
  GdipPolygonFree(Stps,pt(),0,0,ARGB(BkRGB,1),ARGB)
EndProcedure 

;<<<<<<<<<<<<<<<<<<<<<<<
hwnd=OpenWindow(0, 100, 100,700,500 ,"Elliptic Light",  #WS_OVERLAPPEDWINDOW |1) 
Wi=WindowWidth(0):He=WindowHeight(0)
_Img=CreateImage(-1,Wi,He-21,32)
Fon=LoadFont(-1,"arial",40)
Shine=800

TB=TrackBarGadget(-1,0,He-20,Wi,20,1,Shine)
SetGadgetState(TB,Shine/2)
_DRAWING=StartDrawing(ImageOutput(_Img))
  If OpenLibrary(#GDIP,"GDIPlus.DLL")
    Gdip.GdiplusStartupInput\GdiPlusVersion=1
    Gdip\DebugEventCallback = 0
    Gdip\SuppressBackgroundThread = 0
    Gdip\SuppressExternalCodecs = 0
    GF.GdiplusStartup = GetFunction(#GDIP, "GdiplusStartup") : GF(@_GDIP,@Gdip)
    _GDIP=#True
  Else
    MessageRequester("","GDIPlus.DLL Not found",0)
  EndIf
  
  Box(0,0,Wi,He,#Red)
  DrawingFont(FontID(Fon))
  DrawingMode( #PB_2DDrawing_Transparent)
  
  For i=0 To 6
    DrawText(i*40,i*60,"Just a Test",#White,#Red)
  Next
StopDrawing()
_ImGad=ImageGadget(-1,0,0,0,0,ImageID(_Img)) 
 
Repeat 
  Ev=WaitWindowEvent(1) 
  If GetAsyncKeyState_(27) :  End : EndIf
  If Ev=#WM_PAINT Or Ev=#PB_Event_Gadget And EventGadget()=TB
    Shine=GetGadgetState(TB)   
    If IsImage(TmpIMG):FreeImage(TmpIMG):EndIf
    TmpIMG=GrabImage(_Img,-1,0,0,ImageWidth(_Img),ImageHeight(_Img))
    _DRAWING=StartDrawing(ImageOutput(TmpIMG))
      DrawGDIP 
      GdipEllipticLight(Wi/2,He/2,Shine,Shine/2,ARGB(#White))      
    StopDrawing()
    SetGadgetState(_ImGad,ImageID(TmpIMG))
  EndIf
Until Ev=#WM_CLOSE 
Cheers
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Post by Michael Vogel »

einander wrote:Hi Michael:
May be this helps
[...]
Thanks einander, every good code example helps me to learn! Therefore I'll keep your code at a safe place in my source code library :)

At the moment, I'll keep my version and wait until the end of the month :lol:

Again, here is how it looks...

Code: Select all

Procedure.f QuickDistanz(x1.l,y1.l,x2.l)
	x1-x2
	x1*x1
	ProcedureReturn Pow(x1+y1,0.51)
EndProcedure
Procedure GlassEffect(Image,MaxLight)

	Structure BGRA
		blue.c
		green.c
		red.c
		alpha.c
	EndStructure

	Protected bmp.BITMAP
	Protected *bits.BGRA,*px.BGRA

	Protected w.l,h.l
	Protected scaler.f
	Protected shifter.l
	Protected b1x.l,b2x.l
	Protected x.l,y.l,ys.l
	Protected c.l

	If IsImage(Image)

		StartDrawing(ImageOutput(Image))
		Box(0,0,ImageWidth(Image),ImageHeight(Image),#White)
		StopDrawing()

		GetObject_(ImageID(image), SizeOf(BITMAP),bmp)

		*bits=bmp\bmBits

		; komplett durchsichtig...
		;For y=0 To bmp\bmHeight-1
		;	For x=0 To bmp\bmWidthBytes-1 Step 4
		;		*px=*bits+bmp\bmWidthBytes * y + x
		;		*px\alpha=0
		;	Next
		;Next

		; Breite und Höhe
		w=bmp\bmWidthBytes>>2
		h=bmp\bmHeight

		; Tricksen...
		scaler=2000/h;	größere Werte machen die Lichtblase kleiner
		shifter=h-h>>2

		; Brennpunkte
		b1x=w>>2
		b2x=w-b1x

		For y=0 To h
			ys=y*y*scaler

			For x=0 To w>>1

				c=(QuickDistanz(x,ys,b1x)+QuickDistanz(x,ys,b2x))-(b2x-b1x)
				If c<MaxLight
					c=MaxLight-c
				Else
					c=0
				EndIf

				If y%3=0
					If shifter+y/3<h
						*px=*bits+bmp\bmWidthBytes*(y/3+shifter)+x<<2
						*px\alpha=c
						*px=*bits+bmp\bmWidthBytes*(y/3+shifter)+(w-x)<<2
						*px\alpha=c
					EndIf
				EndIf
				If (shifter-y>=0) And (shifter-y<h)
					*px=*bits+bmp\bmWidthBytes*(shifter-y)+x<<2
					*px\alpha=c
					*px=*bits+bmp\bmWidthBytes*(shifter-y)+(w-x)<<2
					*px\alpha=c
				EndIf
			Next x
		Next y

	EndIf

EndProcedure

w=400
h=100
CreateImage(0,w,h)
StartDrawing(ImageOutput(0))
Box(0,0,w,h,#Black)
y=0
While y<w
	LineXY(y,0,y,h-1,Random($ffffff))
	y+3
Wend
DrawingMode(#PB_2DDrawing_Transparent)
DrawText(50,0,"Just a Test",#White,#Black)
DrawText(100,20,"Just a Test",#Yellow,#Black)
DrawText(150,40,"Just a Test",#Red,#Black)
StopDrawing()

OpenWindow(0,0,0,w,h,"",$CF0001)

#Glass=1
CreateImage(#Glass,w,h,32)
GlassEffect(#Glass,255)


StartDrawing(ImageOutput(0))
DrawAlphaImage(ImageID(#Glass),0,-10)
StopDrawing()
ImageGadget(0,0,0,w,h,ImageID(0))


Repeat:Until WaitWindowEvent()=#WM_CLOSE
User avatar
einander
Enthusiast
Enthusiast
Posts: 744
Joined: Thu Jun 26, 2003 2:09 am
Location: Spain (Galicia)

Post by einander »

@Michael:
Your new example looks nice, and now it is also in my source code library. :wink:
Post Reply