Draw an antialiased circle?
Posted: Fri Feb 20, 2015 1:54 pm
I'm using Circle() on an image but it's jaggy. Is there a way (or trick) to do it anti-aliased, so it's got a smooth edge?
http://www.purebasic.com
https://www.purebasic.fr/english/
Code: Select all
UsePNGImageEncoder()
InitSprite()
OpenWindow(0,0,0,600,600,"SOFTWARE",#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0),0,0,800,600,#True,0,0)
CreateImage(0,1200,1200,32)
StartDrawing(ImageOutput(0))
Circle(600,600,550,$00DDDD)
Circle(600,600,545,$000000)
StopDrawing()
ResizeImage(0,555,555,#PB_Image_Smooth)
StartDrawing(ScreenOutput())
DrawImage(ImageID(0),25,25)
StopDrawing()
FlipBuffers()
SaveImage(0,GetTemporaryDirectory()+"/smoothercircle.png")
Delay(2000)
Hello Dude. The jagged edges are caused by the low screen resolution. The trick would be to draw the circle on a high resolution context, and then transpose it onto the screen, like so:Dude wrote:...Is there a way (or trick) to do it anti-aliased, so it's got a smooth edge?
Code: Select all
wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
OpenWindow(0, 0, 0, 500, 500, "Smooth Circle", wFlags)
If CreateImage(0, 2000, 2000, 32, #Red) And StartDrawing(ImageOutput(0))
Circle(1000, 1000, 900, #Yellow)
StopDrawing()
ResizeImage(0, 500, 500)
ImageGadget(0, 0, 0, 500, 500, ImageID(0))
EndIf
While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend
Code: Select all
Enumeration
#Window
#Canvas
EndEnumeration
Declare AntialiasedCircle(StartX.d, StartY.d, Radius.d, AntiLength.d, Color.i)
Global.i WindowW = 800
Global.i WindowH = 600
If OpenWindow(#Window, 0, 0, WindowW, WindowH, "Antialiased Circle", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(#Canvas, 0, 0, WindowW, WindowH)
StartDrawing(CanvasOutput(#Canvas))
Box(0, 0, WindowW, WindowH, RGB(30,30,30))
AntialiasedCircle(WindowW*0.5, WindowH*0.5, 200, 2, RGB(255,0,0))
AntialiasedCircle( 100, 100, 80, 2, RGB(0,0,255))
AntialiasedCircle(WindowW-100, 100, 50, 2, RGB(0,255,0))
AntialiasedCircle( 100, WindowH-100, 50, 2, RGB(0,255,0))
AntialiasedCircle(WindowW-100, WindowH-100, 80, 2, RGB(0,0,255))
StopDrawing()
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
EndIf
End
Procedure AntialiasedCircle(StartX.d, StartY.d, Radius.d, AntiLength.d, Color.i)
Define.i R,G,B
Define.d Normal, Value
If Radius <= 0
Radius = 0.00001
EndIf
If AntiLength <= 0
AntiLength = 0.00001
EndIf
DrawingMode(#PB_2DDrawing_AlphaBlend | #PB_2DDrawing_Gradient)
ResetGradientColors()
R = Red(Color)
G = Green(Color)
B = Blue(Color)
Normal = 1 / Radius
Value = 1.0 - AntiLength * Normal
GradientColor( 0.0, RGBA(R,G,B,255))
GradientColor(Value, RGBA(R,G,B,255))
GradientColor( 1.0, RGBA(R,G,B,0))
CircularGradient(StartX, StartY, Radius)
Circle(StartX, StartY, Radius)
EndProcedure
Yes, indeed! Thanks for sharing, Samuel.luis wrote:Nice idea Samuel.
Code: Select all
Enumeration
#Window
#Canvas
EndEnumeration
Declare AntialiasedCircle(StartX.d, StartY.d, Radius.d,dick.d,AntiLength.d, front,back,art=0)
Global.i WindowW = 800
Global.i WindowH = 600
If OpenWindow(#Window, 0, 0, WindowW, WindowH, "Antialiased Circle", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(#Canvas, 0, 0, WindowW, WindowH)
StartDrawing(CanvasOutput(#Canvas))
Box(0, 0, WindowW, WindowH, #White ); RGB(30,30,30))
AntialiasedCircle(WindowW*0.5, WindowH*0.5, 200,7.1, 1, #Red,#White)
AntialiasedCircle(WindowW*0.5, WindowH*0.5, 100,2, 2, #Blue,#Red,#PB_2DDrawing_Outlined)
AntialiasedCircle(100,100, 80,2, 3, RGB(0,0,255),#White,#PB_2DDrawing_Outlined)
AntialiasedCircle(WindowW-100,100, 50, 1.1, 1, RGB(0,255,0), #White, #PB_2DDrawing_Default)
AntialiasedCircle(100, WindowH-100, 50, 1.1, 1, RGB(0,255,0), #White, #PB_2DDrawing_Outlined)
AntialiasedCircle(WindowW-100, WindowH-100, 80,1.1,1, #Black,#White, #PB_2DDrawing_Outlined)
StopDrawing()
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
EndIf
End
Procedure AntialiasedCircle(StartX.d, StartY.d, Radius.d,dick.d, AntiLength.d, front,back,art=0)
Define.i R,G,B
Define.d Normal, Value
If art=#PB_2DDrawing_Outlined
radius+dick/2 ; to get the line in middle off the radius
EndIf
If Radius <= 0
Radius = 0.00001
EndIf
If AntiLength <= 0
AntiLength = 0.00001
EndIf
DrawingMode(#PB_2DDrawing_AlphaBlend | #PB_2DDrawing_Gradient) ; |#PB_2DDrawing_Transparent)
ResetGradientColors()
R = Red(front)
G = Green(front)
B = Blue(front)
Normal = 1 / Radius
Value = 1.0 - AntiLength * Normal
GradientColor( 0.0, RGBA(R,G,B,255))
GradientColor(Value, RGBA(R,G,B,255))
GradientColor( 1.0, RGBA(R,G,B,0))
CircularGradient(StartX, StartY, Radius)
Circle(StartX, StartY, Radius)
If art=#PB_2DDrawing_Outlined
R = Red(back)
G = Green(back)
B = Blue(back)
radius-dick
GradientColor( 0.0, RGBA(R,G,B,255))
GradientColor(Value, RGBA(R,G,B,255))
GradientColor( 1.0, RGBA(R,G,B,0))
CircularGradient(StartX, StartY, Radius)
Circle(StartX, StartY, Radius)
EndIf
EndProcedure
Code: Select all
Enumeration
#Window
#Canvas
EndEnumeration
Procedure MyCircle(x,y,radius,color,width=0,mode=0)
Global MyCircleSmooth=2
Protected d.d,s.d
Protected fillcolor
Protected xxcolor
width-MyCircleSmooth>>1
Debug width
If width
radius+width>>1
EndIf
If radius>0
s=MyCircleSmooth
If s<=0
s=0.0001
EndIf
d=1/(radius+s)
fillcolor=color|$FF000000
xxcolor=color|$40000000
DrawingMode(#PB_2DDrawing_AlphaBlend|#PB_2DDrawing_Gradient)
ResetGradientColors()
GradientColor(0,fillcolor)
If mode=#PB_2DDrawing_Outlined
GradientColor(0,color)
GradientColor(d*(radius-width-s),color)
GradientColor(d*(radius-width-s/2),xxcolor)
GradientColor(d*(radius-width),fillcolor)
EndIf
GradientColor(d*radius,fillcolor)
GradientColor(d*(radius+s/2),xxcolor)
GradientColor(1,color)
CircularGradient(x,y,radius)
Circle(x,y,radius)
EndIf
EndProcedure
Global.i WindowW = 800
Global.i WindowH = 600
If OpenWindow(#Window, 0, 0, WindowW, WindowH, "Antialiased Circle", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(#Canvas, 0, 0, WindowW, WindowH)
StartDrawing(CanvasOutput(#Canvas))
Box(0, 0, WindowW, WindowH, #White ); RGB(30,30,30))
For i=1 To 15
MyCircle(50+i*20,50+i*20,50+i*10,Random(#White),i,#PB_2DDrawing_Outlined)
MyCircle(WindowW-50-i*20,50+i*20,50+i*10,Random(#White),16-i,#PB_2DDrawing_Outlined)
Next i
StopDrawing()
Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
EndIf
Code: Select all
OpenWindow(0, 0, 0, 600, 600, "Smooth Circle")
CreateImage(0, 1000, 1000, 32, $000000) ; would like to make this transparent
StartDrawing(ImageOutput(0))
Circle(500, 500, 300, $0000FF)
StopDrawing()
ResizeImage(0, 500, 500)
ImageGadget(0, 0, 0, 500, 500, ImageID(0))
While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend