So why is the color change "permanent"?
#1
In the sample program attached I use a function to brighten the color of drawn elements. I noticed the color change is permanent even though I am not returning the color value to the color handle itself. Am I doing this wrong  or is there something buggy in how color handles are passed that I don't understand? I figured out a work arround for the situation but I don't care for it.  Any suggestions of comments would be welcome.

Code: (Select All)
Sc& = _NewImage(800, 500, 32)
Screen Sc&
Dim klr&, klr2&, klr3&

klr& = _RGB(27, 27, 128)
klr2& = _RGB(27, 27, 128)
klr3& = _RGB(150, 26, 28)

For n = 1 To 40
    Cls
    _Limit 20
    klr& = _RGB(27, 27, 128) 'if this line is commented out the color is permanently changed by the brighter function
    orb 400, 250, n * 2, klr&, 1.5
    ' klr2& = _RGB(128, 227, 128)   this one is commented out to show what would happen as above
    orb 200, 250, n * 2, klr2&, 1.5
    klr3& = _RGB(227, 26, 28) 'comment this out and the color changes
    orb 600, 250, 40, klr3&, 7 'an orb that is the same size to serve as an example without the scaling to distract with the viewer
    _Display
Next n


Function brighter& (ch&&, p)
    r = _Red(ch&&)
    b = _Blue(ch&&)
    g = _Green(ch&&)

    If p < 0 Then p = 0
    If p > 100 Then p = 100
    p = p / 100
    rdif = 255 - r: rc = rdif * p: brr = Int(r + rc): If brr > 255 Then brr = 255
    gdif = 255 - g: gc = gdif * p: bgg = Int(g + gc): If bgg > 255 Then bgg = 255
    bdif = 255 - b: bc = bdif * p: bbb = Int(b + bc): If bbb > 255 Then bbb = 255
    brighter& = _RGB(brr, bgg, bbb)
End Function

Sub orb (XX As Long, YY As Long, Rd As Long, KK As Long, brt As Integer)
    'for false shaded 3-D look
    'XX,YY arer screen position Rd is outermost radius of the orb KK is the startign color
    'brt is the factor by which color will chnage it is the diffeence from KK to RGB(255,255,255)
    'brt is applied each step so your orb will go to white if it is large or the brt value is high
    ps = _Pi
    p3 = _Pi / 3
    p4 = _Pi / 4
rdc = p4 / Rd
    If Rd < 10 Then ps = _Pi / 3 'so small radius orbs look cool too
    For c = 0 To Int(Rd * .87) Step ps
        KK = brighter&(KK, brt)
        CircleFill XX, YY, Rd - (c), KK
        XX = XX + rdc * (c * p3) ' could be fiddled with to move the center of the gradient
        YY = YY - rdc * (c * 2 * p4) ' could be fiddled with to move the center of the gradient
    Next c
End Sub

Sub CircleFill (CX As Long, CY As Long, R As Long, C As Long)
    'sub by SMcNeill makes a filled circle without worrying about using the paint command to fill an empty circle
    Dim Radius As Long, RadiusError As Long
    Dim X As Long, Y As Long

    Radius = Abs(R)
    RadiusError = -Radius
    X = Radius
    Y = 0

    If Radius = 0 Then PSet (CX, CY), C: Exit Sub

    ' Draw the middle span here so we don't draw it twice in the main loop,
    ' which would be a problem with blending turned on.
    Line (CX - X, CY)-(CX + X, CY), C, BF

    While X > Y
        RadiusError = RadiusError + Y * 2 + 1
        If RadiusError >= 0 Then
            If X <> Y + 1 Then
                Line (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
                Line (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
            End If
            X = X - 1
            RadiusError = RadiusError - X * 2
        End If
        Y = Y + 1
        Line (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
        Line (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
    Wend

End Sub
Reply
#2
I haven't check code yet but you might want to use _Unsigned Long for the Type to hold color values AND use _RGB32 instead of _RGB() which just matches to closest RGB value in an older screen mode ie NOT using _NewImage( wide, High, 32) to setup graphics screen. 

OK you are using  _NewImage so _RGB32() would be better, maybe I have I backwards don't use RGB32 with old screen modes? I just go by Rule if you use 32 to setup screen, use _RGB32.

OK I confess I don't understand what you are trying in Brighter& but suffix should be ~& to cover all colors including alpha.

I use this for gradually going (by fractions) from one color to another:

Code: (Select All)
Function midInk~& (r1%, g1%, b1%, r2%, g2%, b2%, fr##)
    midInk~& = _RGB32(r1% + (r2% - r1%) * fr##, g1% + (g2% - g1%) * fr##, b1% + (b2% - b1%) * fr##)
End Function

r1, g1, b1 is the RGB at the start when fraction fr## is 0 and r2, g2, b2 is the "Goal" color when fr## = 1 so anything between 0 and 1 for fr## is an in between color value eg fr## = .2 closer to start color r1,g1, b1 and fr ## = .8 closer to r2, g2, b2

The brightest color is _RGB32(255, 255, 255, 255) and & Type wont contain it.
b = b + ...
Reply
#3
So the color handle isn't just a pointer? Thinking that it is may be part of my issue.

The brighter function is just to get a lighter color of the original each iteration to do the shading look for the orbs.
Reply
#4
(04-24-2022, 02:41 PM)James D Jarvis Wrote: So the color handle isn't just a pointer? Thinking that it is may be part of my issue.   

The brighter function is just to get a lighter color of the original each iteration to do the shading look for the orbs.

Yes not a pointer, _RGB32 returns a very large integer best contained in the _Unsigned Long Type suffix ~&
Using _Red(), _Green32, _Blue32() is right, for getting a color converted to it's RGB elements and then using those to change gradually.

I worked up a little Demo of what I think you are trying here:
https://staging.qb64phoenix.com/showthread.php?tid=162
b = b + ...
Reply
#5
It looks like the color is being permanently changed here:

Quote:Sub orb (XX As Long, YY As Long, Rd As Long, KK As Long    , brt As Integer)

        KK = brighter&(KK, brt)

Values passed to a sub retain any changes made in that sub.
Reply
#6
[quote pid="659" dateline="1650816800"]

Values passed to a sub retain any changes made in that sub.
[/quote]

Which I thought shouldn't happen unless the variables were explicitly shared or were returned as part of a function call. Darn it really has been ages since I used QB.
Reply
#7
(04-24-2022, 04:50 PM)James D Jarvis Wrote:
Quote:Values passed to a sub retain any changes made in that sub.

Which I thought shouldn't happen unless the variables were explicitly shared or were returned as part of a function call. Darn it really has been ages since I used QB.

That is new to QB64, arguments in a Sub or Function were passed by what they call ByValue in older versions of QB but QB64 does them ByRef. So if you are going to change a variable value it is best to copy the incoming value into a variable for the Sub to work with and leave the incoming variable alone after.
b = b + ...
Reply
#8
Not a complete best practices fix but a fix that solves the issue I was having.

i just added 2 lines :
Dim NK as long
 NK=KK   

and used NK instead of KK in following lines. It works exactly like I expected it to.

Code: (Select All)
Sc& = _NewImage(800, 500, 32)
Screen Sc&
Dim klr&, klr2&, klr3&

klr& = _RGB(27, 27, 128)
klr2& = _RGB(27, 27, 128)
klr3& = _RGB(150, 26, 28)

For n = 1 To 40
    Cls
    _Limit 20
    ' klr& = _RGB(27, 27, 128) 'struck out but left for readibilty on the forum
    orb 400, 250, n * 2, klr&, 1.5
    ' klr2& = _RGB(128, 227, 128)   'struck out but left for readibilty on the forum
    orb 200, 250, n * 2, klr2&, 1.5
    '  klr3& = _RGB(227, 26, 28) 'struck out but left for readibilty on the forum
    orb 600, 250, 80, klr3&, 7 'a orb that is the same size to serve as an example without the scaling to mess with the viewer
    _Display
Next n


Function brighter& (ch&&, p)
    r = _Red(ch&&)
    b = _Blue(ch&&)
    g = _Green(ch&&)

    If p < 0 Then p = 0
    If p > 100 Then p = 100
    p = p / 100
    rdif = 255 - r: rc = rdif * p: brr = Int(r + rc): If brr > 255 Then brr = 255
    gdif = 255 - g: gc = gdif * p: bgg = Int(g + gc): If bgg > 255 Then bgg = 255
    bdif = 255 - b: bc = bdif * p: bbb = Int(b + bc): If bbb > 255 Then bbb = 255
    brighter& = _RGB(brr, bgg, bbb)
End Function

Sub orb (XX As Long, YY As Long, Rd As Long, KK As Long, brt As Integer)
    'for false shaded 3-D look
    'XX,YY arer screen position Rd is outermost radius of the orb KK is the startign color
    'brt is the factor by which color will chnage it is the diffeence from KK to RGB(255,255,255)
    'brt is applied each step so your orb will go to white if it is large or the brt value is high
    Dim nk As Long
    nk = KK ' this solves my problem along with changes to following lines to use nk instead of kk
    ps = _Pi
    p3 = _Pi / 3
    p4 = _Pi / 4
    If Rd < 10 Then ps = _Pi / 6 'so small radius orbs look cool too
    rdc = p4 / Rd
    For c = 0 To Int(Rd * .87) Step ps
        nk = brighter&(nk, brt)
        CircleFill XX, YY, Rd - (c), nk
        XX = XX + rdc * (c * p3) ' could be fiddled with to move the center of the gradient
        YY = YY - rdc * (c * 2 * p4) ' could be fiddled with to move the center of the gradient
    Next c
End Sub

Sub CircleFill (CX As Long, CY As Long, R As Long, C As Long)
    'sub by SMcNeill makes a filled circle without worrying about using the paint comamnd to fill an empty circle
    Dim Radius As Long, RadiusError As Long
    Dim X As Long, Y As Long

    Radius = Abs(R)
    RadiusError = -Radius
    X = Radius
    Y = 0

    If Radius = 0 Then PSet (CX, CY), C: Exit Sub

    ' Draw the middle span here so we don't draw it twice in the main loop,
    ' which would be a problem with blending turned on.
    Line (CX - X, CY)-(CX + X, CY), C, BF

    While X > Y
        RadiusError = RadiusError + Y * 2 + 1
        If RadiusError >= 0 Then
            If X <> Y + 1 Then
                Line (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
                Line (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
            End If
            X = X - 1
            RadiusError = RadiusError - X * 2
        End If
        Y = Y + 1
        Line (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
        Line (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
    Wend

End Sub

Thanks for the help !
Reply
#9
@Admin Help! Where are those tag markings coming from in my post above? (The quotes and numbers and square brackets)

I am not seeing them in the edit screen.
b = b + ...
Reply
#10
I tried to trim the quotes to make it easier to read. I might have done that.

(04-24-2022, 04:56 PM)bplus Wrote:
(04-24-2022, 04:50 PM)James D Jarvis Wrote: [quote pid="659" dateline="1650816800"]

Values passed to a sub retain any changes made in that sub.

Which I thought shouldn't happen unless the variables were explicitly shared or were returned as part of a function call. Darn it really has been ages since I used QB.

That is new to QB64, arguments in a Sub or Function were passed by what they call ByValue in older versions of QB but QB64 does them ByRef. So if you are going to change a variable value it is best to copy the incoming value into a variable for the Sub to work with and leave the incoming variable alone after.
[/quote]

OH... I hadn't noted that in documentation. That explains a few other subroutines and functions that have been driving me crazy the past few days. Well.... fixing those just got a heck of a lot easier too.
Reply




Users browsing this thread: 3 Guest(s)