Page 1 of 1
How does Circle() work? (make areas of image transparent)
Posted: Fri Mar 27, 2009 11:32 am
by Seymour Clufley
I'm looking for a way to make a circular area in an image transparent.
The way I've been doing it is to create a second image, draw the circle on that, then Point() through the whole image and record whether each pixel is black/white into an array. Then, when drawing the
real image, I do it one pixel at a time and only draw each pixel if the corresponding pixel in the array is black (not had the circle drawn over it).
Obviously this method is slow!
It seems a faster way would be to set the alpha value of each pixel
in the image itself. I know how to
get the alpha value of each pixel thanks to
Srod's code, but not how to
set the value. I've requested a PlotAlpha() command but, in the meantime...?
Secondly, how to know which pixels to make transparent?! This is why I asked how the Circle() command works. Is each pixel changed individually or is there some quicker way?
Posted: Fri Mar 27, 2009 12:10 pm
by Kaeru Gaman
a quick circle algorithm draws 8 times an 8th part of a circle.
you need to calculate the Sin/Cos values only for 45° and repeat/mirror these values.
Posted: Fri Mar 27, 2009 1:21 pm
by freak
Posted: Fri Mar 27, 2009 3:46 pm
by cxAlex
Try this Code:
Code: Select all
Procedure _Circle(x, y, rad, color = 0)
Protected sPos.f, ePos.f, y2.d, rad2, oldx
Protected cy1, cy2, cx1, cx2, ocy1, ocy2, ocx1, ocx2
ocy1 = y-rad
ocy2 = y + rad
ocx1 = x
ocx2 = x
rad2 = rad*rad
sPos = x
ePos = x + rad
For x = sPos To ePos
oldx + 1
y2 = Sqr(rad2-oldx*oldx)
cy1 = y-y2
cy2 = y + y2
cx1 = x
cx2 = sPos-oldx
LineXY(ocx1, ocy1, cx1, cy1, color)
LineXY(ocx1, ocy2, cx1, cy2, color)
LineXY(ocx2, ocy1, cx2, cy1, color)
LineXY(ocx2, ocy2, cx2, cy2, color)
ocy1 = cy1
ocy2 = cy2
ocx1 = cx1
ocx2 = cx2
Next
EndProcedure
OpenWindow(0, 0, 0, 450, 450, "demo", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
If StartDrawing(WindowOutput(0))
_Circle(225, 225, 200, $ff)
DrawingMode(#PB_2DDrawing_Outlined)
Circle(225, 225, 150)
StopDrawing()
EndIf
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
C translation
Posted: Fri Mar 27, 2009 4:14 pm
by SMartin
In case you're interested.
Here's a PB translation of the c code linked to by Freak
Code: Select all
Procedure RasterCircle(x0.i,y0.i,Radius.i)
;{ Original C source code
; void rasterCircle(int x0, int y0, int radius)
; {
; int f = 1 - radius;
; int ddF_x = 1;
; int ddF_y = -2 * radius;
; int x = 0;
; int y = radius;
;
; setPixel(x0, y0 + radius);
; setPixel(x0, y0 - radius);
; setPixel(x0 + radius, y0);
; setPixel(x0 - radius, y0);
;
; While(x < y)
; {
; assert(ddF_x == 2 * x + 1);
; assert(ddF_y == -2 * y);
; assert(f == x*x + y*y - radius*radius + 2*x - y + 1);
; If(f >= 0)
; {
; y--;
; ddF_y += 2;
; f += ddF_y;
; }
; x++;
; ddF_x += 2;
; f += ddF_x;
; setPixel(x0 + x, y0 + y);
; setPixel(x0 - x, y0 + y);
; setPixel(x0 + x, y0 - y);
; setPixel(x0 - x, y0 - y);
; setPixel(x0 + y, y0 + x);
; setPixel(x0 - y, y0 + x);
; setPixel(x0 + y, y0 - x);
; setPixel(x0 - y, y0 - x);
; }
; }
;} End Original C source code
Define f.i = 1 - Radius
Define ddF_x = 1
Define ddF_y = -2 * Radius
Define x.i = 0
Define y.i = Radius
StartDrawing(WindowOutput(0))
Plot(x0,y0 + Radius)
Plot(x0,y0 - Radius)
Plot(x0 + Radius,y0)
Plot(x0 - Radius,y0)
StopDrawing()
While (x < y)
If ddF_x = ((2 * x) + 1)
If ddF_y = (-2 * y)
If f = (x * x + y * y - Radius * Radius + 2 * x - y + 1)
If f >= 0
y - 1
ddF_y + 2
f + ddF_y
EndIf
x + 1
ddF_x + 2
f + ddF_x
StartDrawing(WindowOutput(0))
Plot(x0 + x,y0 + y)
Plot(x0 - x,y0 + y)
Plot(x0 + x,y0 - y)
Plot(x0 - x,y0 - y)
Plot(x0 + y,y0 + x)
Plot(x0 - y,y0 + x)
Plot(x0 + y,y0 - x)
Plot(x0 - y,y0 - x)
StopDrawing()
Else
ProcedureReturn
EndIf
Else
ProcedureReturn
EndIf
Else
ProcedureReturn
EndIf
Wend
EndProcedure
If OpenWindow(0, 0, 0, 200, 200, "Raster Circle", #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
RasterCircle(100,100,10)
RasterCircle(100,100,20)
RasterCircle(100,100,40)
RasterCircle(100,100,80)
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
End
Posted: Sat Mar 28, 2009 3:00 am
by netmaestro
Just a bit of fun, you may find it helpful or not:
Code: Select all
; Image to start with, we'll just make it blue
CreateImage(0, 640,640,32)
StartDrawing(ImageOutput(0))
Box(0,0,640,640,#Blue)
; Our transparent color will be pink, make a pink circle
Circle(320,320,100,RGB(255,0,255))
; Now, make all the pink pixels transparent
*ptr.RGBQUAD = DrawingBuffer()
For j=0 To 639
For i=0 To DrawingBufferPitch()-SizeOf(RGBQUAD) Step SizeOf(RGBQUAD)
If *ptr\rgbRed&$FF=$FF And *ptr\rgbGreen&$FF=0 And *ptr\rgbBlue&$FF=$FF ; Found a pink one!
*ptr\rgbReserved=0
Else
*ptr\rgbReserved=$FF
EndIf
*ptr+SizeOf(RGBQUAD)
Next
Next
; All done
StopDrawing()
; Let's see what we got...
OpenWindow(0,0,0,800,700,"",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
Repeat
ev=WaitWindowEvent()
Select ev
Case #PB_Event_Repaint
StartDrawing(WindowOutput(0))
DrawAlphaImage(ImageID(0),100,50)
StopDrawing()
EndSelect
Until ev=#PB_Event_CloseWindow
Posted: Sat Mar 28, 2009 3:14 am
by Demivec
@netmaestro: I'm not seeing anything but a grey window with your example. XP sp3 x86
Posted: Sat Mar 28, 2009 9:16 am
by cxAlex
Here is a very fast Circle Procedure, it's as fast as PB and sometimes faster:
(Tested on a Intel QuadCore @ 3.2 GHz & 4 GB Ram)
Code: Select all
Procedure _Circle(x0, y0, rad, color = 0)
Static x, y, rad2, oldcolor
oldcolor = FrontColor(color)
rad2 = rad*rad
x = 0
Plot(x0, y0 + rad)
Plot(x0, y0-rad)
Plot(x0 + rad, y0)
Plot(x0-rad, y0)
Repeat
x + 1
y = Sqr(rad2-x*x)
Plot(x0-x, y0-y)
Plot(x0-x, y0 + y)
Plot(x0 + x, y0-y)
Plot(x0 + x, y0 + y)
Plot(x0-y, y0-x)
Plot(x0-y, y0 + x)
Plot(x0 + y, y0-x)
Plot(x0 + y, y0 + x)
Until x=>y
FrontColor(oldcolor)
EndProcedure