Click here to Skip to main content
14,970,844 members
Articles / General Programming / Algorithms
Article
Posted 26 Apr 2021

Tagged as

Stats

2.2K views

Validation of Interpreted Colors

Rate me:
Please Sign up or sign in to vote.
5.00/5 (6 votes)
26 Apr 2021CPOL5 min read
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)

Share

About the Author

gggustafson
Software Developer (Senior)
United States United States
In 1964, I was in the US Coast Guard when I wrote my first program. It was written in RPG (note no suffixing numbers). Programs and data were entered using punched cards. Turnaround was about 3 hours. So much for the "good old days!"

In 1970, when assigned to Washington DC, I started my MS in Mechanical Engineering. I specialized in Transportation. Untold hours in statistical theory and practice were required, forcing me to use the university computer and learn the FORTRAN language, still using punched cards!

In 1973, I was employed by the Norfolk VA Police Department as a crime analyst for the High Intensity Target program. There, I was still using punched cards!

In 1973, I joined Computer Sciences Corporation (CSC). There, for the first time, I was introduced to a terminal with the ability to edit, compile, link, and test my programs on-line. CSC also gave me the opportunity to discuss technical issues with some of the brightest minds I've encountered during my career.

In 1975, I moved to San Diego to head up an IR&D project, BIODAB. I returned to school (UCSD) and took up Software Engineering at the graduate level. After BIODAB, I headed up a team that fixed a stalled project. I then headed up one of the two most satisfying projects of my career, the Automated Flight Operations Center at Ft. Irwin, CA.

I left Anteon Corporation (the successor to CSC on a major contract) and moved to Pensacola, FL. For a small company I built their firewall, given free to the company's customers. An opportunity to build an air traffic controller trainer arose. This was the other most satisfying project of my career.

Today, I consider myself capable.

Comments and Discussions

 
QuestionSomething to think about Pin
Gary R. Wheeler3-May-21 13:40
MemberGary R. Wheeler3-May-21 13:40 
AnswerRe: Something to think about Pin
gggustafson4-May-21 3:09
professionalgggustafson4-May-21 3:09 
QuestionExcellent effort! Pin
MarkTX3-May-21 8:11
MemberMarkTX3-May-21 8:11 
AnswerRe: Excellent effort! Pin
gggustafson3-May-21 8:39
professionalgggustafson3-May-21 8:39 
Suggestioncolor3 Pin
_yulen29-Apr-21 4:58
Member_yulen29-Apr-21 4:58 
GeneralRe: color3 Pin
gggustafson29-Apr-21 5:43
professionalgggustafson29-Apr-21 5:43 
GeneralRe: color3 Pin
_yulen3-May-21 0:23
Member_yulen3-May-21 0:23 
GeneralRe: color3 Pin
_yulen3-May-21 0:49
Member_yulen3-May-21 0:49 
GeneralRe: color3 Pin
gggustafson3-May-21 6:02
professionalgggustafson3-May-21 6:02 
GeneralRe: color3 Pin
_yulen3-May-21 23:41
Member_yulen3-May-21 23:41 
GeneralRe: color3 Pin
gggustafson4-May-21 3:07
professionalgggustafson4-May-21 3:07 
GeneralRe: color3 Pin
_yulen4-May-21 23:44
Member_yulen4-May-21 23:44 
GeneralMy vote of 5 Pin
BillWoodruff28-Apr-21 3:29
mveBillWoodruff28-Apr-21 3:29 
GeneralRe: My vote of 5 Pin
gggustafson28-Apr-21 5:48
professionalgggustafson28-Apr-21 5:48 
GeneralMy vote of 5 Pin
LightTempler26-Apr-21 10:33
MemberLightTempler26-Apr-21 10:33 
GeneralRe: My vote of 5 Pin
gggustafson27-Apr-21 14:54
professionalgggustafson27-Apr-21 14:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.