Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / programming / algorithm

Validation of Interpreted Colors

5.00/5 (6 votes)
26 Apr 2021CPOL5 min read 9.1K  
How well does the Interpolation of Colors match the Colors produced by Microsoft's Linear Gradient Brush?

Table of Contents

The symbol Table of Contents returns the reader to the top of the Table of Contents.

Introduction Table of Contents

During the development of the Gradient Color Picker V2 [^] a significant modification to the algorithm used in the earlier version of the software occurred. In the original implementation, colors for the selection buttons were retrieved from a panel that contained a color gradient implemented using a LinearGradientBrush [^]. Two readers suggested the use of a different method, i.e., use colors obtained from an interpolation from a starting to an ending color.

The Question Table of Contents

How well does the interpolation method match the Microsoft's linear gradient brush?

Validation Method Table of Contents

The validation was limited to a small set of colors. Twenty colors participated in each test. The starting and ending colors were chosen using the Color Dialog [^]. For each test, colors were chosen from the following gradients.

color_choices

The validation method was:

  1. Start and end colors were chosen for a test.
  2. A linear gradient panel was filled based on the start and end colors.
    C#
    // ***************************************** fill_gradient_PAN
    
    bool fill_gradient_PAN ( )
        {
        bool  have_colors = ( have_end_color &&
                              have_start_color );
    
        if ( have_colors )
            {
            gradient_PAN.Visible = true;
            gradient_PAN.Invalidate ( );
            compare_BUT.Visible = true;
            }
    
        return ( have_colors );
    
        } // fill_gradient_PAN
    
    RO0
     
  3. On clicking Compare, the interpolated colors are computed; the selection color buttons are created, and the buttons are properly spaced along the interpolated gradient panel. get_interpolation_colors computed the interpolated colors.
     
    C#
    // **************************************************** MinMax
    
    int MinMax ( float start,
                 float difference,
                 float i )
        {
        int result = ( int ) ( start - ( i * difference ) + 0.5F );
    
        return ( Math.Max ( 0, Math.Min ( 255, result ) ) );
    
        } // MinMax
    
    // ********************************** get_interpolation_colors
    
    // See https://www.codeproject.com/Articles/5267129/
    //   Gradient-Color-Picker Bill Woodward comment modified
    
    List < Color > get_interpolation_colors (
                       Color   start_color,
                       Color   end_color,
                       int     number_of_colors )
        {
        List < Color > list = new List < Color > ( );
    
        float          count = ( float ) number_of_colors - 1.0F;
    
        float          start_R = ( float ) start_color.R;
        float          difference_R = ( start_R -
                                        ( float ) end_color.R ) /
                                        count;
    
        float          start_G = ( float ) start_color.G;
        float          difference_G = ( start_G -
                                        ( float ) end_color.G ) /
                                        count;
    
        float          start_B = ( float ) start_color.B;
        float          difference_B = ( start_B -
                                        ( float ) end_color.B ) /
                                        count;
    
        for ( int i = 0; ( i < number_of_colors ); i++ )
            {
            int B = MinMax ( start_B, difference_B, ( float ) i );
            int G = MinMax ( start_G, difference_G, ( float ) i );
            int R = MinMax ( start_R, difference_R, ( float ) i );
    
            list.Add ( Color.FromArgb ( R, G, B ) );
    
            }
    
        return ( list );
    
        } // get_interpolation_colors
    


    IvsLG

    The spacing of the selection color buttons must be correct because the centerline of the button will be used to determine what color in the linear gradient panel will be compared with the color of the selection color button.

    We now have enough information to perform the validation: the colors of the selection color buttons in the List interpolation_colors and the colors of the linear gradient pixels directly above the selection color buttons in the List pixel_colors.

  4. The results of the comparisons between the members of these two Lists is presented in a table-like form.

    RO

    Each pair of color values contains the linear gradient color (upper) and the interpolated color (lower). The difference between the two is computed by color_difference.
    C#
    // ****************************************** color_difference
    
    void color_difference (     Color   pixel_color,
                                Color   interpolation_color,
                            ref int     difference,
                            ref Color   difference_color )
        {
    
        difference = 0;
        difference_color = Color.Empty;
    
        if ( interpolation_color.R != pixel_color.R )
            {
            difference++;
            }
        if ( interpolation_color.G != pixel_color.G )
            {
            difference++;
            }
        if ( interpolation_color.B != pixel_color.B )
            {
            difference++;
            }
    
        if ( difference == 0 )
            {
            difference_color = Color.LightGreen;
            }
        else if ( difference > 1 )
            {
            difference_color = Color.Red;
            }
        else
            {
            difference_color = Color.Yellow;
            }
    
        } // color_difference
    
    If the components are equal, the background color of the difference box (to the right of the color pair) is LightGreen; if one component differs, the background color is Yellow; and if two or more components differ, the background color is Red. In all cases, the count of differing components is displayed as the difference box text.
    Image 9

The results of all tests follow. Note that each graphic is a thumbnail that when clicked presents a larger graphic.

RO OY
YG GB
BP WB  

In a perfect world the background color of the difference boxes would all be LightGreen. Since that is not the case we must seek out the reason why.

The first thing we should consider is the positioning of the buttons beneath the gradient panel. The coloring of these buttons is not dependent on the coloring in the gradient panel (unlike the algorithm used in the first version of the software). Rather, the button colors are dependent on the results of an interpolation calculation.

validation

The positioning of the buttons is determined through an integer computation. Thus rounding may become a factor especially because the horizontal position of the button centerline was computed using a division. As a result, the spacing was recalculated using floating point arithmetic.

C#
                            // compute initial spacing
                            // between buttons
spacing = ( int ) (
    ( float ) ( interpolation_button_PAN.Size.Width -
                ( BUTTON_WIDTH * number_of_colors ) ) /
    ( float ) ( number_of_colors - 1 ) + 0.5F );

Although this change improved the results (more difference boxes has a background color of LightGreen), there were still difference boxes with Yellow and Red background colors. This led to the hypothesis that the location of the pixel in the gradient panel was slightly to the left or right of the centerline of the appropriate selection color button.

To allow testing this hypothesis, the program was modified to allow the centerline of the button to be shifted left and right, using the arrow keys. First the selection color button of interest was clicked. This caused the borders of the selected button and associated report item to be highlighted.

RO1

Now the left and/or right arrow keys are pressed until the background color of the difference box is LightGreen.

RO2

The correction box displays the number of pixels moved and the direction of movement (Pink for leftward; PaleGreen for rightward). In this example, the centerline of the selection color button should have been positioned 2 pixels to the left.

The following are the results of all 6 tests.

RO_R OY_R
YG_R GB_R
BP_R WB_R  

In 5 of the 6 tests, a simple repositioning of the selection color button was sufficient to cause the linear gradient colors to match the interpolation colors. Although some may argue that the correction should be applied automatically, the Blue/Purple panel suggests otherwise. In the Blue/Purple test, there does not appear to be any simple left/right shift that would correct the positioning of the selection color buttons.

Note too that the human perception of the difference between interpolation and linear gradient colors is extremely small.

Answer Table of Contents

If we accept human perception as a factor, then the question "How well does the interpolation method match the Microsoft's linear gradient brush?" can be answered "Very Well."

References Table of Contents

Conclusion Table of Contents

This article has discussed the use of interpolated colors vs. the use of colors from a linear color gradient. The results of this study suggests that there is very little difference.

Development Environment Table of Contents

This project was developed in the following environment:

Microsoft Windows 7 Professional SP 1
Microsoft Visual Studio 2008 Professional SP1
Microsoft Visual C# 2008
Microsoft .Net Framework Version 3.5 SP1

History Table of Contents

4/24/2021 Original article

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)