fbGFX: BUG in Paint statement

General FreeBASIC programming questions.
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

fbGFX: BUG in Paint statement

Post by MrSwiss »

Just discovered a BUG, when using transparency in conjunction with Paint.

If ScreenRes is set to use: GFX_ALPHA_PRIMITIVES and Paint is used,
to fill a box, it doesn't contain fill, to the box's internals, when border's
color isn't set, to a opaque color!
(aka: if Alpha is anything other than 255, or &hFF)

Minimalistic proof of concept:

Code: Select all

' Paint-Leak_ex1.bas    -- (c) 2019-04-06, MrSwiss
'
' compile: -s gui
'
Const As UShort wid = 1024, hei = 768, cd = 32, pg = 2, sflg = 64

ScreenRes(wid, hei, cd, pg, sflg)       ' sflg = GFX_ALPHA_PRIMITIVES
Width wid \ 8, hei \ 16
Color(&hFF000000, &hFFFFFFFF) : Cls     ' black (fg) on white (bg)

Line (100, 100)-(wid-101, hei-101), &hFFFF0000, B   ' works correctly, fully opaque
Paint(101, 101), &h3fFFFF00, &hFFFF0000 ' fill color can be anything!
Flip
Sleep : Cls

Line (100, 100)-(wid-101, hei-101), &hBFFF0000, B   ' 25% transparent border = LEAK!!! 
Paint(101, 101), &h3fFFFF00, &hBFFF0000 ' fill color can be anything!
Flip
Sleep
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: fbGFX: BUG in Paint statement

Post by counting_pine »

Thanks for the report. I'd prefer though if you didn't capitalise the word "bug". It just comes across as shouting.

Your example code has a subtle problem: the red border changes colour if it's partially transparent, so isn't actually equal to the border colour.
But if I fix that - using the value from Point(100,100) - the code still seems to illustrate the bug, so the report does seem to be valid.

To be honest, GFX_ALPHA_PRIMITIVES should probably be deprecated in favour of something better..
The way it handles transparency is broken in some ways, for instance, the way it blends two semitransparent colours. I also seem to recall a problem with Put Trans / Put Alpha,n.
Also, it's a setting that has to be enabled or disabled, whereas it would probably be better to specify it when (and only when) it's actually wanted.
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: fbGFX: BUG in Paint statement

Post by MrSwiss »

counting_pine wrote: I'd prefer though if you didn't capitalise the word "bug". It just comes across as shouting.
Well, I happen to disagree:

"comes across as shouting", is only true, when nothing but capitals are used (e.g. whole title).
Capitalizing a single word, is regarded as "emphasis" only (alike: fbGFX, which is capitalized mostly, anyway).
counting_pine wrote:Your example code has a subtle problem: the red border changes colour if it's partially transparent, so isn't actually equal to the border colour.
??? (sorry, imo, logically incorrect, if referring to code)
That impact is, from my point of view, purely visual which means, the same difference ...
Hex-Number for border, remains equal, so where is the problem, in the code?
(the color itself is equal to, what you'll get, using Point(100, 100))

Setting GFX_ALPHA_PRIMITIVES, should make it pretty obvious, that transparency is wanted ...
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: fbGFX: BUG in Paint statement

Post by counting_pine »

I'd agree with you that capitalisation is sensible and correct to use if you're using an acronym, keyword, constant, etc. that is supposed to be capitalised. But unnecessary emphasis can alter the tone of a post, particularly when its purpose is to draw attention to a fault.

Regarding the example code: because it's drawing a partially transparent red border on a (formerly) white screen, the border is no longer pure red, but a slightly whitish red. So that's the border colour you would want to pass to Paint.

But if I change the Paint code to use the actual border colour, the effect remains the same, so your bug report is still accurate:

Code: Select all

' Paint-Leak_ex1.bas    -- (c) 2019-04-06, MrSwiss
'
' compile: -s gui
'
Const As UShort wid = 1024, hei = 768, cd = 32, pg = 2, sflg = 64

ScreenRes(wid, hei, cd, pg, sflg)       ' sflg = GFX_ALPHA_PRIMITIVES
Width wid \ 8, hei \ 16
Color(&hFF000000, &hFFFFFFFF) : Cls     ' black (fg) on white (bg)

Line (100, 100)-(wid-101, hei-101), &hBFFF0000, B   ' 25% transparent border = leak
print Hex(Point(100,100)) '' C3FF1010
Paint(101, 101), &h3fFFFF00, Point(100,100)
Sleep
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: fbGFX: BUG in Paint statement

Post by MrSwiss »

@counting_pine, thanks for the explanation.

I think I've got it now: Paint when a border-color is given, is in this case, reading/searching
the "combined" or "blended" value off the screen, to determine the aera "to be filled" ...

Isn't a bug something, which should draw "topmost attention"? (aka: has top priority)

I'm aware that this is, to a certain extent, depending on who reports it, because many don't
check their code, for syntactical correctness, etc. causing 'false positives'.
(not enough research, before posting a 'bug')
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: fbGFX: BUG in Paint statement

Post by counting_pine »

MrSwiss wrote:Isn't a bug something, which should draw "topmost attention"? (aka: has top priority)

I'm aware that this is, to a certain extent, depending on who reports it, because many don't
check their code, for syntactical correctness, etc. causing 'false positives'.
(not enough research, before posting a 'bug')
I take special notice of bug reports when I see them, and I take them seriously. I think most developers are the same.
In a way, I sometimes like the false positives more. It becomes more about a puzzle to solve in the given code. (And of course it means no fixes are required in FB.)
Sadly I don't always have the time or energy, or understand the code well enough to manage a fix for genuine bugs. But I think it's important to be aware of them. I think this one would be worth putting it on Github or Sourceforge.
MrSwiss wrote:@counting_pine, thanks for the explanation.

I think I've got it now: Paint when a border-color is given, is in this case, reading/searching
the "combined" or "blended" value off the screen, to determine the aera "to be filled" ...
Yeah. That's the only way it can do it.
But as it happens, it seems you are right about the bug, possibly without actually experiencing a genuine case beforehand?
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: fbGFX: BUG in Paint statement

Post by MrSwiss »

counting_pine wrote:But as it happens, it seems you are right about the bug, possibly without actually experiencing a genuine case beforehand?
Well, the case arose, when testing a freshly written rectangle type rect_t's implementation,
especially the show Sub, which uses Paint to fill, with alternative color.
(I'm using a macro (#Define) to get a random, ranged ULong)

To be honest, I've come across it before, but forgot about it in the meantime, sad but true.

I can put it on sf.net, but not just now (have to retrieve my pwd, from old PC, first).
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: fbGFX: BUG in Paint statement

Post by MrSwiss »

Done: bug-report filed at Source Forge, ticket: #896

Titled: fbGFX: Paint statement 'overflows', with SreenRes: GFX_ALPHA_PRIMITIVES
Component: gfxlib2
Tags: paint, overflow
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: fbGFX: BUG in Paint statement

Post by dodicat »

using opaqueness:
It only takes one pixel overlap in a perimeter to leak, because this pixel will be a different colour
Using line()-(),b overlaps at each corner.
see the faint lines at the corners here

Code: Select all


Const As UShort wid = 1024, hei = 768, cd = 32, pg = 2, sflg = 64

ScreenRes(wid, hei, cd, pg, sflg)       ' sflg = GFX_ALPHA_PRIMITIVES
Width wid \ 8, hei \ 16
Color(&hFF000000, &hFFFFFFFF) : Cls  
for n as long=0 to 50
Line (100+n, 10+n)-(wid-101-n, hei-101-n), &hBFFF0000, B   ' 25% transparent border = LEAK!!!
next
sleep 


But if you draw the lines to avoid a pixel overlap and get the true screen colour of a corner via point, paint seems to behave properly.

Code: Select all

' Paint-Leak_ex1.bas    -- (c) 2019-04-06, MrSwiss
'
' compile: -s gui
'
Const As UShort wid = 1024, hei = 768, cd = 32, pg = 2, sflg = 64

ScreenRes(wid, hei, cd, pg, sflg)       ' sflg = GFX_ALPHA_PRIMITIVES
Width wid \ 8, hei \ 16
Color(&hFF000000, &hFFFFFFFF) : Cls     ' black (fg) on white (bg)

Line (100, 100)-(wid-101, hei-101), &hFFFF0000, B   ' works correctly, fully opaque
Paint(101, 101), &h3fFFFF00, &hFFFF0000 ' fill color can be anything!
print "press a key"
Flip
Sleep : Cls

'dont use Box with line, but set the lines for no overlaps.
line (100,100)-(wid-101,100),&hBFFF0000
line (wid-101,101) -(wid-101,hei-101),&hBFFF0000
line (wid-102,hei-101)-(100,hei-101),&hBFFF0000
line (100,hei-102)-(100,101),&hBFFF0000
''Line (100, 100)-(wid-101, hei-101), &hBFFF0000, B   ' 25% transparent border = LEAK!!! 

var c=point(100,100)

Paint(101, 101), &h3fFFFF00, point(100,100) ' fill color can be anything!

var r=cast(ubyte ptr,@c)[2]
var g=cast(ubyte ptr,@c)[1]
var b=cast(ubyte ptr,@c)[0]
var a=cast(ubyte ptr,@c)[3]

print r;",";g;",";b;",";a; "  is the actual border r,g,b,a colour"

Flip
Sleep   
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: fbGFX: BUG in Paint statement

Post by fxm »

Well seen dodicat (and the others).

So a simpler workaround is:

Code: Select all

' Paint-Leak_ex1.bas    -- (c) 2019-04-06, MrSwiss
'
' compile: -s gui
'
Const As UShort wid = 1024, hei = 768, cd = 32, pg = 2, sflg = 64

ScreenRes(wid, hei, cd, pg, sflg)       ' sflg = GFX_ALPHA_PRIMITIVES
Width wid \ 8, hei \ 16
Color(&hFF000000, &hFFFFFFFF) : Cls     ' black (fg) on white (bg)

Line (100, 100)-(wid-101, hei-101), &hBFFF0000, B   ' 25% transparent border = leak
Paint(101, 101), &h3fFFFF00, Point(100,101) '' (avoiding the corners of the rectangle as reference for border color)
print Hex(Point(100,101)) '' CFFF4040
Sleep
So now, I do not think it's really a bug!
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: fbGFX: BUG in Paint statement

Post by D.J.Peters »

fxm wrote:So now, I do not think it's really a bug!
My hero ... with the right words what a wonderful day ...
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: fbGFX: BUG in Paint statement

Post by dodicat »

A transparent circle fails with paint because it overlaps a pixel at the top and bottom thus producing two leaking points.
(Turn the wheel magnifier to see the right hand circle)
An alternative Bresenham circle avoids this.

Code: Select all

Type Pt
    As Long x,y
End Type

Sub GetCircle(xm As Integer, ym As Integer, r As Integer,p() As pt)
    #define CIRC(r)  ( ( Int( (r)*(1 + Sqr(2)) ) - (r) ) Shl 2 )
    Dim As Long x = -r, y = 0, e = 2 - r Shl 1,count
    Redim p(0 To CIRC(r)+4-1 )
    Do
        count+=1:p(count)=Type<pt>(xm-x, ym+y)
        count+=1:p(count)=Type<pt>(xm-y, ym-x)
        count+=1:p(count)=Type<pt>(xm+x, ym-y)
        count+=1:p(count)=Type<pt>(xm+y, ym+x)
        r = e
        If r<=y Then
            y+=1
            e+=y Shl 1+1
        End If
        If r>x Or e>y Then
            x+=1
            e+=x Shl 1+1
        End If
    Loop While x<0
    p(0)=Type(xm,ym)'set the centre in (0)
    Redim Preserve p(count)
End Sub

Sub Magnify()    
    #define resetwheel(w,fl) fl=w
    #define wheel(w,f) w-f
    Dim As Long mx,my,mw,button:Getmouse mx,my,mw,button
    Static As Long flag,pmw
    mw=Abs(mw/2)
    Line(mx-40,my-40)-(mx+40,my+40),Rgb(0,0,0),B
    If button=1 Then  resetwheel(mw,flag)
    Dim As Ulong array(1 To 6561),count
    pmw=wheel(mw,flag)
    If pmw<=1 Then Exit Sub
    For z As Long=1 To 2
        For x As Long=mx-40 To mx+40
            For y As Long=my-40 To my+40
                count+=1
                If z=1 Then 
                    Var c=Point(x,y) 'needed to magnify an alpha screen
                    Var r =Cast(Ubyte Ptr,@c)[2]
                    Var g =Cast(Ubyte Ptr,@c)[1]
                    Var b =Cast(Ubyte Ptr,@c)[0]
                    Var al=Cast(Ubyte Ptr,@c)[3]
                    array(count)=Rgba(r,g,b,255)
                End If
                If z=2 Then
                    Var NewX=pmw*(x-mx)+mx:Var NewY=pmw*(y-my)+my
                    Line(newx-pmw/2,newy-pmw/2)-(newx+pmw/2,newy+pmw/2),array(count),bf
                End If
            Next y
        Next x
        count=0
    Next z
    Line(mx-pmw*40,my-pmw*40)-(mx+pmw*40,my+pmw*40),5,B
End Sub


Sub _circle(p() As pt,c As Ulong)
    For n As Long=Lbound(p)+1 To Ubound(p)
        Pset (p(n).x,p(n).y),c
    Next
End Sub



Dim As Long rad=150

Dim As pt c()
getCircle(220,300,rad,c())
Screen 19,32,,64
Color ,Rgb(255,255,255)
Cls

Draw String(350,300),"Press a key",Rgb(0,200,0)

dim as ulong colour= Rgba(200,0,0,100)
Do
    Screenlock
    Cls
    Draw String(200,20),"Left circle - bresenham, Right circle - gfx",Rgb(0,0,0)
    _circle(c(),colour)
    Circle(580,300),rad,colour
    pset(400,300),rgb(0,200,0) ' screen centre
    magnify
    Screenunlock
    Sleep 1,1
Loop Until Len(Inkey)
Cls

_circle(c(),colour)

Paint(c(0).x,c(0).y),colour,Point(c(1).x,c(1).y)
Sleep
 
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: fbGFX: BUG in Paint statement

Post by fxm »

Are you saying that the bug is rather for the Circle keyword (and Line...,B...), but not Paint? :-)
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: fbGFX: BUG in Paint statement

Post by Tourist Trap »

fxm wrote:Are you saying that the bug is rather for the Circle keyword (and Line...,B...), but not Paint? :-)
Hi all,

I use a lot the ALPHA flag, and find it very good. But when you are in this configuration of screen, I think that there is no better strategy than using multiple buffers and blend them with PUT. So one could paint in pure RGB on a buffer, then put the buffer on the background. Otherwise, I can't see how PAINT would be fast if it had to test the borders after blending.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: fbGFX: BUG in Paint statement

Post by dodicat »

For circles and boxes there are dedicated filling methods anyway, so you wouldn't use paint.
Mr Swiss reckons a bug in paint bounded by transparency, but this seems not the real case.
For oddball shapes the coder must carefully bound a perimeter with no overlaps in external angles < 90 degrees, over 90 degrees an overlapped pixel would lie outside the paint region but would still be seen for those who look too closely.

Here is a star with no overlaps either way, but it is messy to code.

Code: Select all

Const pi=4*Atn(1)
Type pt
    As Long x,y
End Type

Sub Magnify()    
    #define resetwheel(w,fl) fl=w
    #define wheel(w,f) w-f
    Dim As Long mx,my,mw,button:Getmouse mx,my,mw,button
    Static As Long flag,pmw
    mw=Abs(mw/2)
    Line(mx-40,my-40)-(mx+40,my+40),Rgb(0,0,0),B
    If button=1 Then  resetwheel(mw,flag)
    Dim As Ulong array(1 To 6561),count
    pmw=wheel(mw,flag)
    If pmw<=1 Then Exit Sub
    For z As Long=1 To 2
        For x As Long=mx-40 To mx+40
            For y As Long=my-40 To my+40
                count+=1
                If z=1 Then 
                    Var c=Point(x,y) 'needed to magnify an alpha screen
                    Var r =Cast(Ubyte Ptr,@c)[2]
                    Var g =Cast(Ubyte Ptr,@c)[1]
                    Var b =Cast(Ubyte Ptr,@c)[0]
                    Var al=Cast(Ubyte Ptr,@c)[3]
                    array(count)=Rgba(r,g,b,255)
                End If
                If z=2 Then
                    Var NewX=pmw*(x-mx)+mx:Var NewY=pmw*(y-my)+my
                    Line(newx-pmw/2,newy-pmw/2)-(newx+pmw/2,newy+pmw/2),array(count),bf
                End If
            Next y
        Next x
        count=0
    Next z
    Line(mx-pmw*40,my-pmw*40)-(mx+pmw*40,my+pmw*40),5,B
End Sub

Function lngth(a As pt,b As pt) As Long
    Return Sqr((a.x-b.x)^2 + (a.y-b.y)^2)
End Function

Function shortline(fp As pt,p As pt,length As Long) As pt
    Dim As Long diffx=p.x-fp.x,diffy=p.y-fp.y
    Dim As Single L=Sqr(diffx*diffx+diffy*diffy)
    Return Type(fp.x+length*diffx/L,fp.y+length*diffy/L)
End Function

Sub Star(starx As Long,stary As Long,size As Long,col As Ulong)
    Static As pt p(1 To 11)
    Var t=col
    Var count=0,rad=0.0,px=0.0,py=0.0
    For z As Single=0+.28 To 2*pi+.1+.28 Step 2*pi/10
        count=count+1
        If count Mod 2=0 Then rad=size Else rad=.5*size
        px=starx+rad*Cos(z)
        py=stary+rad*Sin(z)
        p(count)=Type<pt>(px,py) 'get vertices
    Next z
    Dim As pt tmp
    For n As Long=1 To 10
        Var L=lngth(p(n),p(n+1))
        tmp=shortline(p(n),p(n+1),L-1)'reduce length by one pixel
        Line(p(n).x,p(n).y)-(tmp.x,tmp.y),col
    Next
    Pset(starx,stary-2),col
    col=Point(starx,stary-2) 'get correct border colour
    Paint (starx,stary),t,col
End Sub  

Screen 19,32,,64
Color ,Rgb(255,255,255)
Do
    Screenlock
    Cls
    draw string (389,300),"Hello",rgb(0,0,0)
    star(400,300,250,Rgba(0,100,255,150))
    magnify
    Screenunlock
    Sleep 1,1
Loop Until Len(Inkey)
Sleep  
Post Reply