Announcement

Collapse
No announcement yet.

GetGValue Problem?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    GetGValue Problem?

    I'm seeing an odd problem with the GetGValue() function found in the includes.

    If I feed GetGValue the value 14,278,749 then I get the expected return value of 224. But when I pass a variable to GetGValue as in the code below, I get a return value of 55776. I see the problem with other color values as well.

    Can someone point out why I get different values?

    Code:
    #Debug Error On
    #Debug Display On
    #Include "Win32API.inc"
    Type TestA
       altColor(3) As Long
    End Type
    Function PBMain() As Long
       ReDim D(0) As TestA
       D(0).altColor(1) = 14278749
       ? Str$(GetGValue(D(0).altColor(1))) 'return 55776
       ? Str$(GetGValue(14278749))         'returns 224
    End Function
    The problem doesn't occur with GetRValue or GetBValue.

    Here are the MACROS from Jose's and PBWin's includes. No difference that I see.
    Code:
    Macro GetRValue(nRGB) = Lo(Byte, nRGB)
    Macro GetGValue(nRGB) = Lo(Byte, nRGB \ 256)
    Macro GetBValue(nRGB) = Lo(Byte, nRGB \ 65536)
    
    Macro GetRValue(nRGB)=Lo(Byte,nRGB)
    Macro GetGValue(nRGB)=Lo(Byte,(nRGB)\256)
    Macro GetBValue(nRGB)=Lo(Byte,(nRGB)\65536)
    Last edited by Gary Beene; 11 Aug 2015, 12:29 AM.

    #2
    If I use a simpler variable (not a UDT whose elements is an array), like this:

    Code:
       iColor = D(0).altColor(1)
       ? Str$(GetGValue(iColor)) 'returns 224
    Then the correct value is returned.

    It would seem that the macro is not getting used correctly. But if not in GetGValue, then why not in GetRValue and GetBValue.

    Comment


      #3
      I see this in Help, but don't see how it applies in this case:

      Macro parameters are substituted directly, so whitespace characters in the passed macro parameters may cause unexpected problems if the expanded code is syntactically incorrect with the additional whitespace. For example, this can be important when specifying UDT variables as macro parameters. Consider the following code:

      Comment


        #4
        Gary,
        I also experienced a problem while trying to extract the G value inasmuch as I used the following:

        gVal = (ColorValue AND &HFF00)/ 256

        After much fumbling around I found that the resultant value also included the most significant byte, so I had to modify the expression as follows:

        gVal = (ColorValue AND &H00FF00)/ 256

        That fixed the problem.

        That's why I specified the values as BYTES when using GetRValue, GetGValue, and GetBValue. If it's bigger than 255 I don't want it. Don't want to step in it twice!
        Last edited by Michael Boho; 11 Aug 2015, 12:51 AM.
        It's impossible to make anything foolproof because fools are so ingenious.

        Comment


          #5
          Tested this in my getcolour function that I wrote years ago and your udt works fine there.

          Code:
          #COMPILE EXE
          #DIM ALL
          
          #DEBUG ERROR ON
          #DEBUG DISPLAY ON
          #INCLUDE "Win32API.inc"
          TYPE TestA
             altColor(3) AS LONG
          END TYPE
          FUNCTION PBMAIN() AS LONG
            LOCAL r, g, b AS LONG
            LOCAL colrgb AS STRING
             REDIM D(0) AS TestA
             D(0).altColor(1) = 14278749
             ? STR$(GetGValue(D(0).altColor(1))) 'return 55776
             ? STR$(GetGValue(14278749))         'returns 224
             colrgb=getcolour(14278749, r, g, b)
             ? colrgb
             ? FORMAT$(r)+$CRLF+FORMAT$(g)+$CRLF+FORMAT$(b)
             colrgb=getcolour(D(0).altColor(1), r, g, b)
             ? colrgb
             ? FORMAT$(r)+$CRLF+FORMAT$(g)+$CRLF+FORMAT$(b)
          END FUNCTION
          
          FUNCTION getcolour(colr AS LONG, arr AS LONG, geee AS LONG, beee AS LONG) AS STRING
            LOCAL ddd,one,two,three AS STRING
            ddd=HEX$(colr,6)
            three="&h"+LEFT$(ddd,2)
            two="&h"+MID$(ddd,3,2)
            one="&h"+RIGHT$(ddd,2)
            arr=VAL(one)
            geee=VAL(two)
            beee=VAL(three)
            FUNCTION = "RGB("+FORMAT$(arr,"000")+","+FORMAT$(geee,"000")+","+FORMAT$(beee,"000")+")" 'one + ","+two+","+three
          END FUNCTION
          I can't think of any reason for the issue with GetGValue.
          Rod
          In some future era, dark matter and dark energy will only be found in Astronomy's Dark Ages.

          Comment


            #6
            Originally posted by Gary Beene View Post
            If I feed GetGValue the value 14,278,749 then I get the expected return value of 224. But when I pass a variable to GetGValue as in the code below, I get a return value of 55776. I see the problem with other color values as well.

            Can someone point out why I get different values?

            Code:
               ? Str$(GetGValue(D(0).altColor(1))) 'return 55776
               ? Str$(GetGValue(D(0).altColor(1)) AND 255) 'returns 224
            Like Michael said, you are picking up extra data beyond your color byte.
            Code:
            #COMPILE EXE
            #DIM ALL
            TYPE rgbbytes
                r AS BYTE
                g AS BYTE
                b AS BYTE
                a AS BYTE
            END TYPE
            
            FUNCTION PBMAIN () AS LONG
                LOCAL mycolor() AS LONG, trgba AS rgbbytes PTR
                REDIM mycolor(3)
                mycolor(0) = RGB(93, 224, 217)
            '    mycolor(0) = 14278749
                trgba = VARPTR(mycolor(0))
                ? "r =" + STR$(@trgba.r) + $CR + _
                "g =" + STR$(@trgba.g) + $CR + _
                "b =" + STR$(@trgba.b) + $CR + _
                "a =" + STR$(@trgba.a)
            END FUNCTION
            The world is strange and wonderful.*
            I reserve the right to be horrifically wrong.
            Please maintain a safe following distance.
            *wonderful sold separately.

            Comment


              #7
              extracted from LO Function Help:
              ... value may be up to twice the size of the data type specified by DataType. In the following example, n may be up to a 16-bit value (twice the size of a BYTE):

              b = LO(BYTE,n)
              The line
              Code:
              ? Str$(GetGValue(D(0).altColor(1)))
              forces a LONG (32 bits) into the
              Code:
              Macro GetGValue(nRGB) = Lo(Byte, nRGB \ 256)
              , which forces a 16 bit output from LO. Somehow literal numbers into LO allows an 8 bit output.

              Convert the numbers 14278749, 55776, and 224 to hex or binary, then follow the action.

              I think there should have been compile time error when trying to LO(byte, long val).

              Cheers,
              Dale

              Comment


                #8
                Thanks for the responses, guys.

                ... picking up extra data beyond your color byte.
                But why would that be? How would LO(BYTE, ... return other than a single byte?

                And why only with a UDT but not a non-UDT element?

                And why not with the GetR and GetB macros?

                And why hasn't it been discovered years ago, I wonder (and fixed)?

                And what would be the appropriate fix for the includes?

                Deviating from the C headers on such a simple macro seems almost blasphemous, given that the rest of the world uses it too. I didn't find any extensive reference to such an issue in the Internet.

                Just wondering about it all ....

                Comment


                  #9
                  Dale,
                  Just saw your post. Thanks for pointing out the "may be twice the size", which a LONG breaks. I've been using the Macro forever and not seen the problem until recently, when I started using the UDT from my example.

                  Help doesn't clarify what happens when we break that rule.

                  Plus, it doesn't clarify for me why it works on a variable but not a UDT element. Can I be certain that just avoiding the UDT element will avoid the problem in the future?

                  I guess it is an easy enough problem to avoid but still a bit of mystery in the result.

                  Comment


                    #10
                    Another datapoint...
                    When I compile with PBWIN, I get the same result as Gary.
                    If I compile with PBCC, the answer is always printed as 224.
                    I tried this using PB and Jose's includes.

                    No, I don't know what this means (yet).

                    Comment


                      #11
                      Gary,
                      I think I wasn't clear enough. A Literal (a number in the source code) works.
                      Like in your OP - ? Str$(GetGValue(14278749)) 'returns 224

                      While a member of a UDT is a variable.

                      Cheers,
                      Dale

                      Comment


                        #12
                        Nice catch, Dale.
                        Rod
                        In some future era, dark matter and dark energy will only be found in Astronomy's Dark Ages.

                        Comment


                          #13
                          Dale, yes I used an in line value in the opening post. So I'm not sure what you meant for me to take away from your last post. Sorry to be slow but would you clarify?

                          Comment


                            #14
                            If I use a variable that is not a member of a UDT the macro seems to work just fine. So what's magic about using a UDT variable over a non UDT variable?

                            Comment


                              #15
                              Since PBCC gets this right regardless of constants / variables, I decided to have a look at the assembler generated by PBWIN and PBCC.
                              Surprisingly, the assembler generated by the 2 compilers is not the same.

                              Both compilers try to cater for the original operand size by inserting an
                              instruction to assure a byte result but in the PBWIN structured variable case, I believe the compiler gets it wrong by using the wrong register (ie it's a bug). PBCC generates the correct code for variables and for constants.

                              The instruction required to make a byte result is MOVZX EAX,AL which keeps only the bottom 8 bits of the EAX register to be used in a function call. In PBWIN case, it uses ECX instead of EAX.

                              I'll continue to poke about a bit more.

                              Comment


                                #16
                                Well, as nobody is going to fix the compiler's bug, I'm going to replace the macros in my headers with the following functions:

                                Code:
                                FUNCTION GetRValue(BYVAL clrRGB AS DWORD) AS BYTE
                                   FUNCTION = (clrRGB AND &H000000FF???)
                                END FUNCTION
                                
                                FUNCTION GetGValue(BYVAL clrRGB AS DWORD) AS BYTE
                                   SHIFT RIGHT clrRGB, 8
                                   FUNCTION = (clrRGB AND &H000000FF???)
                                END FUNCTION
                                
                                FUNCTION GetBValue(BYVAL clrRGB AS DWORD) AS BYTE
                                   SHIFT RIGHT clrRGB, 16
                                   FUNCTION = (clrRGB AND &H000000FF???)
                                END FUNCTION
                                Forum: http://www.jose.it-berater.org/smfforum/index.php

                                Comment


                                  #17
                                  In my computer with Windows 8.1 of 64 bits this return 224 in both cases.
                                  I am using PBWIN10

                                  Code:
                                   #DEBUG ERROR ON
                                  #DEBUG DISPLAY ON
                                  #INCLUDE "Win32API.inc"
                                  TYPE TestA
                                     altColor(3) AS LONG
                                  END TYPE
                                  FUNCTION PBMAIN() AS LONG
                                     REDIM D(0) AS TestA
                                     D(0).altColor(1) = 14278749
                                     ? STR$(GetGValue(D(0).altColor(1))) 'return 55776
                                     ? STR$(GetGValue(14278749))         'returns 224
                                  END FUNCTION

                                  Comment


                                    #18
                                    I am using WIN32API.INC of PBWIN9 with PBWIN10 because with PBWIN10 was changed structure...and working fine...but if I change to WIN32API.INC of
                                    PBWIN10 this return 55776 and 224 respectively.
                                    Last edited by Israel Vega Alvarez 2; 11 Aug 2015, 11:14 AM.

                                    Comment


                                      #19
                                      Also if I change AS LONG by AS QUAD in UDT structure (using WIN32API of PBWIN10) this working fine returning 224 in both cases.

                                      Comment


                                        #20
                                        So...
                                        The problem is associated with indexed variables. No TYPE is needed, a local array can provoke the problem.
                                        It also seems to require an integer division as part of the scenario (CDQ, IDIV sequence).
                                        I've made a program based on Gary's with some more test cases which show where the error occurs. See below.
                                        It seems quite a specific case and Israel's Quad example being Ok supports that.

                                        The error is that under these specific circumstances, the PBWIN compiler plants a..
                                        MOVZX ECX, CL
                                        ..instead of the required..
                                        MOVZX EAX, AL

                                        This means that the EAX register will not be truncated to 8 bits.

                                        In the test case below where a 'normal' division is used, the compiler uses the math coprocessor and the problem does not occur.
                                        Code:
                                        #Debug Error On
                                        #Debug Display On
                                        #Include "Win32API.inc"
                                        
                                        Type TestB
                                            StructColor As Long
                                        End Type
                                        
                                        Function PBMain() As Long
                                           Dim Altcolor(3) as Local Long
                                           Local acol as Long
                                           Local scol As TestB
                                        
                                           altColor(1) = 14278749
                                           aCol = 14278749
                                           sCol.StructColor = 14278749
                                           ? Str$(GetGValue(altColor(1)))           'return 55776
                                           ? Str$(GetGValue(aCol))                  'return 224
                                           ? Str$(GetGValue(14278749))              'return 224
                                           ? Str$(LO(BYTE, scol.StructColor\256))   'return 224
                                           ? Str$(LO(BYTE, altColor(1)))            'return 93 - correct
                                           ? Str$(LO(BYTE, altColor(1)\256))        'return 55776 - this is the basic problem case
                                           ? Str$(LO(BYTE, altColor(1)/256))        'return 224
                                           ? Str$(HI(BYTE, LO(WORD, altColor(1))))  'return 224
                                        End Function

                                        Comment

                                        Working...
                                        X
                                        😀
                                        🥰
                                        🤢
                                        😎
                                        😡
                                        👍
                                        👎