Helpful Posts Helpful Posts:  0
Results 1 to 11 of 11

Thread: How to get RGB color, given (x,y) of a chart like these...

  1. #1

    How to get RGB color, given (x,y) of a chart like these...

    I have two charts, and need to get the <r,g,b> values when given (x,y) coordinates.

    This needs to be a forumla, not a read-back of pixel values.

    Whichever chart is easier is fine with me.

    If someone knows either formula, that would be fantastic.

    Thanks!

    How to get RGB color, given (x,y) of a chart like these...

    How to get RGB color, given (x,y) of a chart like these...

  2. #2
    Steaphany's Avatar
    Join Date
    Apr 2009
    Location
    The far off Country of Texas
    Posts
    827
    Real Name
    Steaphany

    Re: How to get RGB color, given (x,y) of a chart like these...

    From your examples, you are looking for HSV to RGB with the Saturation fixed at a specific value of 1 ( Maximum ).

    Here you go:
    if ( S == 0 ) //HSV from 0 to 1
    {
    R = V * 255
    G = V * 255
    B = V * 255
    }
    else
    {
    var_h = H * 6
    if ( var_h == 6 ) var_h = 0 //H must be < 1
    var_i = int( var_h ) //Or ... var_i = floor( var_h )
    var_1 = V * ( 1 - S )
    var_2 = V * ( 1 - S * ( var_h - var_i ) )
    var_3 = V * ( 1 - S * ( 1 - ( var_h - var_i ) ) )

    if ( var_i == 0 ) { var_r = V ; var_g = var_3 ; var_b = var_1 }
    else if ( var_i == 1 ) { var_r = var_2 ; var_g = V ; var_b = var_1 }
    else if ( var_i == 2 ) { var_r = var_1 ; var_g = V ; var_b = var_3 }
    else if ( var_i == 3 ) { var_r = var_1 ; var_g = var_2 ; var_b = V }
    else if ( var_i == 4 ) { var_r = var_3 ; var_g = var_1 ; var_b = V }
    else { var_r = V ; var_g = var_1 ; var_b = var_2 }

    R = var_r * 255 //RGB results from 0 to 255
    G = var_g * 255
    B = var_b * 255
    }
    For more check out Color conversion math and formulas HSV > RGB

  3. #3
    herbert's Avatar
    Join Date
    Oct 2010
    Location
    Sussex, UK
    Posts
    471
    Real Name
    Alex

    Re: How to get RGB color, given (x,y) of a chart like these...

    This is written from the perspective of building a computer program to convert mouse clicks on an image into RGB.

    Steaphany has shown you the formulas for a HSV to RGB conversion. So from your mouse click you still need the HSV values. The HSV space is actually a cylinder with the angle around the central vertical axis corresponds to Hue, the distance from the axis corresponds to Saturation, and the distance along the axis corresponds to Value.

    So from a 2D diagram you will only be able to get Hue and Saturation. You will need to have a separate input for Value. This is why you often see colour pickers like this where Hue/Saturation is adjusted in the 2D grid and a slider at the side adjusts the Value:

    How to get RGB color, given (x,y) of a chart like these...

    The following is assuming you actually want to convert the (a,b) of a mouse click on your image into the Hue/Saturation. These coordinates will have to be converted to a vector (x,y) specifying the distance from the centre of the image (the white in the middle of the diagram). The key to this is using half the image width, or the circle radius R.

    x = a - R
    y = b - R

    The Hue is the angle. So it will be equal to arctan2(Y/X) / (2*pi). This should be in the range 0 to 1 with 0 starting at the top (12 o'clock) on the image and increasing clockwise. The arctan2 function should be available in most programming languages. It returns the correct angle for all four possible XY quandrants. In this case I have assumed an output of radians and so divided by 2*pi to get a value from 0 to 1.

    The Saturation will be the distance from the centre. This will be square_root(X*X + Y*Y) / R. This should be clipped to maximum of 1 (e.g. if the use clicks outside the HSV image circle).

    E.g. Image is 400 x 400 and click on point (235,34)

    R = Image Width / 2 = 200
    X = 235 - 200 = 35
    Y = 34 - 200 = -166
    Hue = arctan2(-166/35) / (2*pi) = 0.467 (or 168 degrees)
    Saturation = sqrt(35*35 + 166*166) / R = sqrt(28781) / 200 = 0.848

    Note again that you will need a Value. If this is 1 your RGB output will be (255,255,255). If it is 0 your RGB will be (0,0,0) irrespective of Hue and Saturation. A Value of 0.5 should at least allow you to get some RGB output but I suggest you add a method to input the Value manually.

    You will also need to ensure that your image has the correct Hue at 0. If not then you will need to adjust the Hue value by adding a constant angle, in effect to rotate it.

    Hope this helps.

    Alex

  4. #4

    Re: How to get RGB color, given (x,y) of a chart like these...

    Alex, yes, thanks. I can easily do a value slider once I have R,G,B....

    I still need to get from (x,y) in one of those diagrams to R,G,B which Steaphany seems to have missed.

  5. #5

    Join Date
    Nov 2009
    Location
    Provence, France
    Posts
    915
    Real Name
    Remco

    Re: How to get RGB color, given (x,y) of a chart like these...

    Quote Originally Posted by donelson View Post
    Alex, yes, thanks. I can easily do a value slider once I have R,G,B....

    I still need to get from (x,y) in one of those diagrams to R,G,B which Steaphany seems to have missed.
    In short: you cannot do that...
    You want to go from a 2D space to a 3D space, so you end up with one coordinate unspecified...

    Your (x,y) diagrams are actually cuts through a 3D space, so that's where your 3rd coordinate is fixed. Then the problem is reduced to getting the other two from the (x,y) values from your mouse. Exactly how to do that, depends on your 2D image.

    In the circle you showed, I'd do something like: get the mouse points transformed to a vector relative to the centre of the circle, then the angle of that vector with a fixed axis gives you one of the missing values (Hue in your case), the length (or distance to the centre) gives you the second (Saturation). Value seems to be fixed at 1.0 in this case, but is NOT derived from the (x,y) coordinates of the point in the image.

    Again, you cannot go from (x,y) in an image to (RGB) without extra information, you need to get the third value from elsewhere (stated in image description, slider on the side, ...). The same goes for any 2D -> 3D transformation, btw, so (x,y)->(HSV) is equally impossible.

    Remco

  6. #6

    Re: How to get RGB color, given (x,y) of a chart like these...

    Thanks. I am going to use this color chart instead, along with a value slider.

    How to get RGB color, given (x,y) of a chart like these...

  7. #7

    Re: How to get RGB color, given (x,y) of a chart like these...

    I am seriously confused, probably due to coordinate systems orientations and scales...

    I am using this image:
    How to get RGB color, given (x,y) of a chart like these...



    with this code:
    Code:
    // Colour Picker based on
    // http://www.easyrgb.com/index.php?X=MATH&H=19#text19
    
    // Globals
    integer giHueSatFaceNum = 0;
    integer giLevelFaceNum = 4;
    integer giResultFaceNum = 2;
    
    // vectors dotted as v.x, v.y, v.z to extract values.
    vector gvHSL = <0.0, 0.0, 0.5>; // start at max saturation
    vector gvRGB;
    
    
    // Debug routine
    myDebug (string msg) {
        Say(msg);
    }
    
    
    // Function: Calculate a conversion parameter from HSL
    float hsl2param( float tf1, float tf2, float tfH ) {
       if ( tfH < 0.0 ) tfH += 1.0;
       if ( tfH > 1.0 ) tfH -= 1.0;
       if ( ( 6.0 * tfH ) < 1.0 ) return ( tf1 + ( tf2 - tf1 ) * 6.0 * tfH );
       if ( ( 2.0 * tfH ) < 1.0 ) return ( tf2 );
       if ( ( 3.0 * tfH ) < 2.0 ) return ( tf1 + ( tf2 - tf1 ) * ( ( 2 / 3 ) - tfH ) * 6.0 );
       return ( tf1 );
    }
    
    
    Main_Loop {
        
        touch (integer n) {  // allow continuous update until mouse-Up
        
            integer tiFaceNum = fTouchedFace( );
            vector tvXY = fTouchedXY( );
    
            myDebug("XY: " + (string)tvXY);
            
            if(tiFaceNum == giHueSatFaceNum)  { // Hue Saturation face
                gvHSL = <1.0 - tvXY.y, tvXY.x, gvHSL.z>; // use current Level            
                myDebug( "HS pick, new HSL = " + (string) gvHSL);
            }
            
            else if(tiFaceNum == giLevelFaceNum) { // Level face
                gvHSL = <gvHSL.x, gvHSL.y, tvXY.x>; // use current HS
                myDebug( "Level pick, new HSL = " + (string) gvHSL);
            }
            
            Sleep(0.1); // slow it down some
        }
        
        touch_end (integer n) {
            
            myDebug( "Final HSL color: " + (string) gvHSL );
            
            float tf1; float tf2;
            
            if ( gvHSL.y < 0.00001 ) gvRGB = <1.0, 1.0, 1.0>;
            else {
                if ( gvHSL.z < 0.5 ) tf2 = gvHSL.z * (1.0 + gvHSL.y);
                else tf2 = (gvHSL.z + gvHSL.y) - (gvHSL.y * gvHSL.z);
                
                tf1 = 2.0 * gvHSL.z - tf2;
                
                gvRGB = <   hsl2param(tf1, tf2, gvHSL.x + 0.3333333),
                            hsl2param(tf1, tf2, gvHSL.x),
                            hsl2param(tf1, tf2, gvHSL.x - 0.3333333)  >;
            }
            
            myDebug( "Final RGB color256: " + (string) (gvRGB * 256.0) );
        }
        
    }

  8. #8

    Re: How to get RGB color, given (x,y) of a chart like these...

    I am seriously confused, probably due to coordinate systems orientations and scales...

    I am using this image:
    How to get RGB color, given (x,y) of a chart like these...



    with this code:
    Code:
    // Colour Picker based on
    // http://www.easyrgb.com/index.php?X=MATH&H=19#text19
    
    // Globals
    integer giHueSatFaceNum = 0;
    integer giLevelFaceNum = 4;
    integer giResultFaceNum = 2;
    
    // vectors dotted as v.x, v.y, v.z to extract values.
    vector gvHSL = <0.0, 0.0, 0.5>; // start at max saturation
    vector gvRGB;
    
    
    // Debug routine
    myDebug (string msg) {
        Say(msg);
    }
    
    
    // Function: Calculate a conversion parameter from HSL
    float hsl2param( float tf1, float tf2, float tfH ) {
       if ( tfH < 0.0 ) tfH += 1.0;
       if ( tfH > 1.0 ) tfH -= 1.0;
       if ( ( 6.0 * tfH ) < 1.0 ) return ( tf1 + ( tf2 - tf1 ) * 6.0 * tfH );
       if ( ( 2.0 * tfH ) < 1.0 ) return ( tf2 );
       if ( ( 3.0 * tfH ) < 2.0 ) return ( tf1 + ( tf2 - tf1 ) * ( ( 2 / 3 ) - tfH ) * 6.0 );
       return ( tf1 );
    }
    
    
    Main_Loop {
        
        touch (integer n) {  // allow continuous update until mouse-Up
        
            integer tiFaceNum = fTouchedFace( );
            vector tvXY = fTouchedXY( );
    
            myDebug("XY: " + (string)tvXY);
            
            if(tiFaceNum == giHueSatFaceNum)  { // Hue Saturation face
                gvHSL = <1.0 - tvXY.y, tvXY.x, gvHSL.z>; // use current Level            
                myDebug( "HS pick, new HSL = " + (string) gvHSL);
            }
            
            else if(tiFaceNum == giLevelFaceNum) { // Level face
                gvHSL = <gvHSL.x, gvHSL.y, tvXY.x>; // use current HS
                myDebug( "Level pick, new HSL = " + (string) gvHSL);
            }
            
            Sleep(0.1); // slow it down some
        }
        
        touch_end (integer n) {
            
            myDebug( "Final HSL color: " + (string) gvHSL );
            
            float tf1; float tf2;
            
            if ( gvHSL.y < 0.00001 ) gvRGB = <1.0, 1.0, 1.0>;
            else {
                if ( gvHSL.z < 0.5 ) tf2 = gvHSL.z * (1.0 + gvHSL.y);
                else tf2 = (gvHSL.z + gvHSL.y) - (gvHSL.y * gvHSL.z);
                
                tf1 = 2.0 * gvHSL.z - tf2;
                
                gvRGB = <   hsl2param(tf1, tf2, gvHSL.x + 0.3333333),
                            hsl2param(tf1, tf2, gvHSL.x),
                            hsl2param(tf1, tf2, gvHSL.x - 0.3333333)  >;
            }
            
            myDebug( "Final RGB color256: " + (string) (gvRGB * 256.0) );
        }
        
    }

  9. #9

    Join Date
    Nov 2009
    Location
    Provence, France
    Posts
    915
    Real Name
    Remco

    Re: How to get RGB color, given (x,y) of a chart like these...

    Sorry, I can't say why you get coordinates in the range (0,1) returned, even after scaling the image: with the parameter names in the code as is, it's too much work to figure out what happens. What I can say is that you want the coordinates in a constant range, independent of image scale... And (0,1) is a convenient range to use, and can easily be converted to 0..255 if needed.

    Don't forget that the use of 0..255 is a convention, chosen for its compactness: 255 is the largest integer value that can be encoded in an (8-bit) byte, the standard information unit when PC's became available (and still sufficient fro display). Integers were used as working with them was much (as in 'orders of magnitude') faster than floating point numbers. With modern CPU's, floating point has become a lot faster, but it still needs more space (4 bytes/number minimum). And everyone is used to the 0..255 scale, so why change

  10. #10

    Re: How to get RGB color, given (x,y) of a chart like these...

    Revi, sorry, you misunderstand. I am saying that all coords are parametric, and lie between 0 and 1. This is what I expect, but not sure how to plug those into the formula from the EasyRGB website.

  11. #11
    herbert's Avatar
    Join Date
    Oct 2010
    Location
    Sussex, UK
    Posts
    471
    Real Name
    Alex

    Re: How to get RGB color, given (x,y) of a chart like these...

    Hi,

    The formula from the EasyRGB website expects HSV to be in the range of 0-1 so you should not have a problem. Surely something like this:

    Code:
    // Colour Picker based on
    // http://www.easyrgb.com/index.php?X=MATH&H=19#text19
    
    // Globals
    integer giHueSatFaceNum = 0;
    integer giLevelFaceNum = 4;
    integer giResultFaceNum = 2;
    
    // vectors dotted as v.x, v.y, v.z to extract values.
    vector gvHSL = <0.0, 0.0, 0.5>; // start at max saturation
    vector gvRGB;
    
    
    // Debug routine
    myDebug (string msg) {
        Say(msg);
    }
    
    
    // Function: Convert HSL to RGB
    vector hsl2rgb(float H, float S, float V) {
    	if ( S == 0 )
    	{
    		R = V;
    		G = V;
    		B = V;
    	}
    	else
    	{
    		var_h = H * 6;
    		if ( var_h == 6 ) var_h = 0; //H must be < 1
    		var_i = int( var_h );
    		var_1 = V * ( 1 - S );
    		var_2 = V * ( 1 - S * ( var_h - var_i ) );
    		var_3 = V * ( 1 - S * ( 1 - ( var_h - var_i ) ) );
    
    		if ( var_i == 0 ) { var_r = V ; var_g = var_3 ; var_b = var_1; }
    		else if ( var_i == 1 ) { var_r = var_2 ; var_g = V ; var_b = var_1; }
    		else if ( var_i == 2 ) { var_r = var_1 ; var_g = V ; var_b = var_3; }
    		else if ( var_i == 3 ) { var_r = var_1 ; var_g = var_2 ; var_b = V; }
    		else if ( var_i == 4 ) { var_r = var_3 ; var_g = var_1 ; var_b = V; }
    		else { var_r = V ; var_g = var_1 ; var_b = var_2; }
    
    		R = var_r;
    		G = var_g;
    		B = var_b;
    	}
            return <R,G,B>
    }
    
    
    Main_Loop {
        
        touch (integer n) {  // allow continuous update until mouse-Up
        
            integer tiFaceNum = fTouchedFace( );
            vector tvXY = fTouchedXY( );
    
            myDebug("XY: " + (string)tvXY);
            
            if(tiFaceNum == giHueSatFaceNum)  { // Hue Saturation face
                gvHSL = <1.0 - tvXY.y, tvXY.x, gvHSL.z>; // use current Level            
                myDebug( "HS pick, new HSL = " + (string) gvHSL);
            }
            
            else if(tiFaceNum == giLevelFaceNum) { // Level face
                gvHSL = <gvHSL.x, gvHSL.y, tvXY.x>; // use current HS
                myDebug( "Level pick, new HSL = " + (string) gvHSL);
            }
            
            Sleep(0.1); // slow it down some
        }
        
        touch_end (integer n) {
            
            myDebug( "Final HSL color: " + (string) gvHSL );
    
            gvRGB = hsl2rgb(gvHSL.x, gvHSL.y, gxHSL.z);
            
            myDebug( "Final RGB color256: " + (string) (gvRGB * 256.0) );
        }
    }
    I am not sure of the exact syntax needed but you get the idea. I think you just need to pass the HSL values to the conversion function.

    Alex

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •