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?
How does Circle() work? (make areas of image transparent)
-
- Addict
- Posts: 1265
- Joined: Wed Feb 28, 2007 9:13 am
- Location: London
- Kaeru Gaman
- Addict
- Posts: 4826
- Joined: Sun Mar 19, 2006 1:57 pm
- Location: Germany
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
In case you're interested.
Here's a PB translation of the c code linked to by Freak
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
Steve Martin
He who waits too long to hesitate…hesitates last.
He who waits too long to hesitate…hesitates last.
- netmaestro
- PureBasic Bullfrog
- Posts: 8451
- Joined: Wed Jul 06, 2005 5:42 am
- Location: Fort Nelson, BC, Canada
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
BERESHEIT
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)
(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