Draw an antialiased circle?
Draw an antialiased circle?
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?
Re: Draw an antialiased circle?
As it exists is in this snippet, this method is pretty much unusable in actual applications, but yields the smooth circle that you seek.
After running, a file is in your temp folder for inspection.Depending on the background imagery, if you transform the circle image into a transparent sprite, then you may have a solution.
After running, a file is in your temp folder for inspection.
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)
Keep it BASIC.
-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: Draw an antialiased circle?
If Windows only, you can use the GDI Lib:
http://www.purebasic.fr/english/viewtop ... 12&t=46987
http://www.purebasic.fr/english/viewtop ... 14&t=29165
http://www.purebasic.fr/english/viewtop ... 12&t=46987
http://www.purebasic.fr/english/viewtop ... 14&t=29165
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.
Re: Draw an antialiased circle?
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
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel 

Re: Draw an antialiased circle?
You can also use gradients to create anti aliased circles.
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
-
- Addict
- Posts: 4791
- Joined: Thu Jun 07, 2007 3:25 pm
- Location: Berlin, Germany
Re: Draw an antialiased circle?
Yes, indeed! Thanks for sharing, Samuel.luis wrote:Nice idea Samuel.
Re: Draw an antialiased circle?
Wonderful idea Samuel.
I took your example to get also outlined circles.
It does not work for overlapping ones.
I took your example to get also outlined circles.
It does not work for overlapping ones.
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
Re: Draw an antialiased circle?
That's a nice new trick for an old dog Samuel.
It certainly goes into the bag.
Thanks.
It certainly goes into the bag.
Thanks.
Keep it BASIC.
Re: Draw an antialiased circle?
Thanks for all the awesome responses to my question! 

Re: Draw an antialiased circle?
Always wanted smooth circles. Thanks for asking, Dude.
@Samuel
Brilliant. Thank you for sharing.
@Samuel
Brilliant. Thank you for sharing.
DE AA EB
- Michael Vogel
- Addict
- Posts: 2807
- Joined: Thu Feb 09, 2006 11:27 pm
- Contact:
Re: Draw an antialiased circle?
Not bad

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
Re: Draw an antialiased circle?
I came with some anti-aliasing wrapping macros here: http://www.purebasic.fr/english/viewtop ... 12&t=61721
Re: Draw an antialiased circle?
Any simple cross-platform way to have the below circle antialiased AND with no visible surrounding box? Basically I want to see the default window color ($F0F0F0 by default on windows 8, but XP, for instance, has a different shade of gray) around the circle.
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