Page 1 of 1

How can vector drawing be used with alpha channels?

Posted: Fri Sep 27, 2019 9:02 pm
by Mistrel
I'm trying to draw an image which has a transparent background using the vector library.

I created an image with #PB_Image_Transparent and made a circle. But the anti-aliasing appears to have black in it? I tried to work around this by drawing a vector image onto the alpha channel using DrawImage() but this didn't work either. It seems like the only way to draw to the alpha channel is to do so with raster commands.

Can anyone confirm this problem or am I using the library incorrectly?

Code: Select all

OpenWindow(#PB_Any,10,10,320,240,"Vector on transparent")

Image=CreateImage(#PB_Any,320,240,32,#PB_Image_Transparent)

StartVectorDrawing(ImageVectorOutput(Image))
VectorSourceColor(RGBA(255,0,0,255))
AddPathCircle(120,120,120)
ClosePath()
StrokePath(30)
StopVectorDrawing()

ImageGadget(#PB_Any,0,0,32,32,ImageID(Image))

;##

OpenWindow(#PB_Any,10,290,320,240,"Raster draw onto alpha channel")

Image=CreateImage(#PB_Any,320,240,32)

StartDrawing(ImageOutput(Image))
Box(0,0,320,240,#Red)
DrawingMode(#PB_2DDrawing_AlphaChannel)
Circle(120,120,120,RGBA(0,0,0,0))
StopDrawing()

ImageGadget(#PB_Any,0,0,32,32,ImageID(Image))

;##

OpenWindow(#PB_Any,10,570,320,240,"DrawImage() onto alpha channel")

Mask=CreateImage(#PB_Any,320,240,32,#Black)

StartVectorDrawing(ImageVectorOutput(Mask))
VectorSourceColor(RGBA(255,255,255,255))
AddPathCircle(120,120,120)
ClosePath()
StrokePath(30)
StopVectorDrawing()

Image=CreateImage(#PB_Any,320,240,32)

StartDrawing(ImageOutput(Image))
Box(0,0,320,240,#Red)
DrawingMode(#PB_2DDrawing_AlphaChannel)
DrawImage(ImageID(Mask),0,0)
StopDrawing()

ImageGadget(#PB_Any,0,0,32,32,ImageID(Image))

Repeat
Until WaitWindowEvent(1)=#PB_Event_CloseWindow

Re: How can vector drawing be used with alpha channels?

Posted: Sat Sep 28, 2019 10:40 am
by #NULL
I think what I explained in a recent thread applies here as well:
Clearing a vector image to transparent, viewtopic.php?f=13&t=73649

If you use opaque white as a background first then the circle will blend/antialias ok with the white.

Code: Select all

VectorSourceColor(RGBA(255,255,255,255))
FillVectorOutput()
A lower alpha value will result in a blend with the existing pixels. For example filling with VectorSourceColor(RGBA(255,255,255,0)) will do nothing. Since it will always blend, and there is no vector drawing mode like #PB_2DDrawing_AllChannels, you basically can't replace the alpha values (other than with 255).
What I still don't understand is when using a 2d drawing block beforehand to set the background alpha layer to transparent white..

Code: Select all

StartDrawing(ImageOutput(Image))
DrawingMode(#PB_2DDrawing_AllChannels)
Box(0, 0, OutputWidth(), OutputHeight(), RGBA(255,255,255,0))
StopDrawing()
..the vector drawing will still blend as if the existing background was black. I would expect a white fringe around the circle in that case.

Re: How can vector drawing be used with alpha channels?

Posted: Sat Sep 28, 2019 4:13 pm
by netmaestro
Played around with it a bit. Not sure if my code is any help to you but it seems to create the desired result. I found I couldn't draw transparent colors onto existing colors so I basically changed the order of drawing. I start with transparency, mask out the circle and then draw the background, which doesn't affect the previous drawing because I haven't called Fillpath() yet. Anyway, here it is:

Code: Select all

OpenWindow(#PB_Any,10,10,320,240,"Vector on transparent")

Image=CreateImage(#PB_Any,320,240,32,#PB_Image_Transparent)

StartVectorDrawing(ImageVectorOutput(Image))
VectorSourceColor(RGBA(255,0,0,255))
AddPathCircle(120,120,120)
ClosePath()
StrokePath(30)
StopVectorDrawing()

ImageGadget(#PB_Any,0,0,32,32,ImageID(Image))

;##

OpenWindow(#PB_Any,10,290,320,240,"Raster draw onto alpha channel")

Image=CreateImage(#PB_Any,320,240,32)

StartDrawing(ImageOutput(Image))
Box(0,0,320,240,#Red)
DrawingMode(#PB_2DDrawing_AlphaChannel)
Circle(120,120,120,RGBA(0,0,0,0))
StopDrawing()

ImageGadget(#PB_Any,0,0,32,32,ImageID(Image))

;##

OpenWindow(#PB_Any,10,570,320,240,"DrawImage() onto alpha channel")

Mask=CreateImage(#PB_Any,320,240,32,#PB_Image_Transparent) ; Start with whole image transparent

StartVectorDrawing(ImageVectorOutput(Mask))
AddPathCircle(120,120,120)                                 ; Mask out circle, don't have to draw to it
ClosePath()
VectorSourceColor(RGBA(0,0,0,255))                         ; Next operation avoids previous path because it isn't filled yet
AddPathBox(0,0,320,240)
ClosePath()
FillPath()
StopVectorDrawing()

Image=CreateImage(#PB_Any,320,240,32)

StartDrawing(ImageOutput(Image))
Box(0,0,320,240,#Red)
DrawingMode(#PB_2DDrawing_AlphaChannel)
DrawImage(ImageID(Mask),0,0)
StopDrawing()

ImageGadget(#PB_Any,0,0,32,32,ImageID(image))

Repeat
Until WaitWindowEvent(1)=#PB_Event_CloseWindow


Re: How can vector drawing be used with alpha channels?

Posted: Sat Sep 28, 2019 5:35 pm
by RASHAD
You can blend with background

Code: Select all

OpenWindow(#PB_Any,10,10,320,240,"Vector on transparent")

Image=CreateImage(#PB_Any,320,240,32,#PB_Image_Transparent)
StartVectorDrawing(ImageVectorOutput(Image))
  
  BeginVectorLayer(250)
    VectorSourceColor(RGBA(255,0,0,255))
    AddPathCircle(120,120,120)
    StrokePath(30)  
  EndVectorLayer()
  
StopVectorDrawing()

ImageGadget(#PB_Any,0,0,32,32,ImageID(Image))

Repeat
Until WaitWindowEvent(1)=#PB_Event_CloseWindow

Re: How can vector drawing be used with alpha channels?

Posted: Sat Sep 28, 2019 7:41 pm
by Mistrel
I can see that there is some misunderstanding with the code I posted. This is the result I'm trying to achieve on a transparent background:

Image

The other two windows in the example are demonstrations. The second window from the top shows that I can draw on the alpha channel with StartDrawing(). I then made a mask of the first image in an attempt to then "fill" the color channels to achieve the result. The bottom window is blank because DrawImage() doesn't appear to work when combined with DrawingMode(#PB_2DDrawing_AlphaChannel).

For those who can't see the difference, I'm attaching an image zoomed in 500%.

On the left side I'm blending with a transparent background. On the right is what I would expect. Instead of starting with a transparent background, it's a solid color. The result looks the same but the right image has no alpha channel.

Image

Re: How can vector drawing be used with alpha channels?

Posted: Sat Sep 28, 2019 8:44 pm
by #NULL
Right now I rather think it's how the Image[Gagdet] is blended on the window. If you put a white canvas half below the ImageGadget then you can get a white fringe on white and the dark fringe on the gray, which means it's not actually color variations in the image, but the result of the blending with the rest of the gui.

Code: Select all

OpenWindow(#PB_Any,10,10,320,240,"Vector on transparent")
CanvasGadget(#PB_Any, 0, 0, 320, 100)
Image=CreateImage(#PB_Any,320,240,32,#PB_Image_Transparent)

StartVectorDrawing(ImageVectorOutput(Image))
VectorSourceColor(RGBA(255,0,0,255))
AddPathCircle(120,120,120)
ClosePath()
StrokePath(30)
StopVectorDrawing()

ImageGadget(#PB_Any,0,0,32,32,ImageID(Image))

;##

Repeat
Until WaitWindowEvent(1)=#PB_Event_CloseWindow

Re: How can vector drawing be used with alpha channels?

Posted: Sat Sep 28, 2019 9:04 pm
by #NULL
Sorry, I was on Linux. I just tried it on Windows now and I get a dark fringe even over the white canvas. :(

Re: How can vector drawing be used with alpha channels?

Posted: Sat Sep 28, 2019 9:46 pm
by #NULL
The blending during the drawing works different on Windows and Linux.
Here are some samples as RBGA values.
First line is color drawn with Box() and checked with Point().
Second Line is color used with FillVectorOutput().
Third line is result color checked with Point().

Code: Select all


windows

current color : 255,255,255,000 
  vector fill : 255,000,000,127 
 result color : 255,128,128,127 

current color : 000,000,000,000 
  vector fill : 255,000,000,127 
 result color : 127,000,000,127 


linux

current color : 255,255,255,000 
  vector fill : 255,000,000,127 
 result color : 255,000,000,127 

current color : 000,000,000,000 
  vector fill : 255,000,000,127 
 result color : 255,000,000,127 

..So if you use transparent white as a first image background instead of transparent black, does that give the desired result?

Code: Select all

w=OpenWindow(#PB_Any,10,10,320,240,"Vector on transparent")
CanvasGadget(#PB_Any, 0, 0, 320, 100)
Image=CreateImage(#PB_Any,320,240,32,#PB_Image_Transparent)

SetWindowColor(w, RGB(200,200,200))
;SetWindowColor(w, RGB(20,20,20))

StartDrawing(ImageOutput(Image))
  DrawingMode(#PB_2DDrawing_AllChannels)
  Box(0, 0, OutputWidth(), OutputHeight(), RGBA(255,255,255,000))
StopDrawing()

StartVectorDrawing(ImageVectorOutput(Image))
VectorSourceColor(RGBA(255,0,0,255))
AddPathCircle(120,120,120)
ClosePath()
StrokePath(30)
StopVectorDrawing()

ImageGadget(#PB_Any,0,0,32,32,ImageID(Image))

;##

Repeat
Until WaitWindowEvent(1)=#PB_Event_CloseWindow

Re: How can vector drawing be used with alpha channels?

Posted: Wed Jul 03, 2024 7:00 pm
by Michael Vogel
Does anyone understand why the background alpha level will be ignored when using vector functions?

The following code shows circles and a line, all drawn opaque white on a background which is fully transparent. Anyhow the blended pixels are touched by the background color independently of their alpha state. This is also seen when changing the alpha level values - which can be checked by activating the line Box(i,0,1,#BrushSize,#Red|(i<<26)).

For me it seems like the calculation (for each color part) works like this...
Red=(Red_Foreground*Alpha_Foreground + Red_Background*255)/(Alpha_Foreground+255)
...

I would expect something nearer to...
Alpha = Alpha_Foreground + (Alpha_Background * (255 - Alpha_Foreground) / 255)
Red = (Red_Foreground * Alpha_Foreground + Red_Background * Alpha_Background * (255 - Alpha_Foreground) / 255)/Alpha
...

Code: Select all

#BrushSize=	29
#BrushCenter=	#BrushSize/2
#Zoom=		10*#BrushSize
#DrawOpaque=	$ff000000
#ImgPat=		0

OpenWindow(0,0,0,#Zoom,#Zoom,"")

CreateImage(#ImgPat,#BrushSize,#BrushSize,32,#PB_Image_Transparent)

StartDrawing(ImageOutput(#ImgPat))
DrawingMode(#PB_2DDrawing_AllChannels)
For i=0 To 28
	Box(i,0,1,#BrushSize,#Red)
	;Box(i,0,1,#BrushSize,#Red|(i<<26))
Next i
StopDrawing()

StartVectorDrawing(ImageVectorOutput(#ImgPat))

;VectorSourceColor(#White)
;FillVectorOutput()

#C1=		#White
#C2=		$800000

d.d=50
f.d=100/d
d=f/2

VectorSourceCircularGradient(#BrushCenter-f*3,#BrushCenter-f*3,1+5*d)
VectorSourceGradientColor(#DrawOpaque|#C1, 0.0)
VectorSourceGradientColor(#DrawOpaque|#C1, 0.9)
VectorSourceGradientColor(#C1, 1.0)
AddPathCircle(#BrushCenter-f*3,#BrushCenter-f*3,1+5*d)
FillPath()

AddPathCircle(#BrushCenter+f*3,#BrushCenter+f*1,1+5*d)
VectorSourceColor(#DrawOpaque|#C1)
FillPath()

MovePathCursor(0.5,27.2)
AddPathLine(28.5,27.2)
VectorSourceColor(#DrawOpaque|#C1)
StrokePath(1)

StopVectorDrawing()

;ShowLibraryViewer("image",#ImgPat)

SetClipboardImage(#ImgPat)

SetWindowColor(0,$f0e080)
ResizeImage(#ImgPat,#Zoom,#Zoom,#PB_Image_Raw)
ImageGadget(0,0,0,#Zoom,#Zoom,ImageID(#ImgPat))
Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow