14,970,844 members
Articles / General Programming / Algorithms
Article
Posted 26 Apr 2021

2.2K views

# Validation of Interpreted Colors

Rate me:
How well does the Interpolation of Colors match the Colors produced by Microsoft's Linear Gradient Brush?

## Introduction

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

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

## Validation Method

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.

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  have_colors = ( have_end_color &&
have_start_color );

if ( have_colors )
{
compare_BUT.Visible = true;
}

return ( have_colors );

```

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
```

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.

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.

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

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.

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.

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

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.

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.

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."

## Conclusion

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

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

 4/24/2021 Original article

## Share

 Software Developer (Senior) 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.

 First Prev Next
 Something to think about Gary R. Wheeler3-May-21 13:40 Gary R. Wheeler 3-May-21 13:40
 Re: Something to think about gggustafson4-May-21 3:09 gggustafson 4-May-21 3:09
 Excellent effort! MarkTX3-May-21 8:11 MarkTX 3-May-21 8:11
 Re: Excellent effort! gggustafson3-May-21 8:39 gggustafson 3-May-21 8:39
 color3 _yulen29-Apr-21 4:58 _yulen 29-Apr-21 4:58
 Re: color3 gggustafson29-Apr-21 5:43 gggustafson 29-Apr-21 5:43
 Re: color3 _yulen3-May-21 0:23 _yulen 3-May-21 0:23
 Re: color3 _yulen3-May-21 0:49 _yulen 3-May-21 0:49
 Re: color3 gggustafson3-May-21 6:02 gggustafson 3-May-21 6:02
 Re: color3 _yulen3-May-21 23:41 _yulen 3-May-21 23:41
 Re: color3 gggustafson4-May-21 3:07 gggustafson 4-May-21 3:07
 Re: color3 _yulen4-May-21 23:44 _yulen 4-May-21 23:44
 My vote of 5 BillWoodruff28-Apr-21 3:29 BillWoodruff 28-Apr-21 3:29
 Re: My vote of 5 gggustafson28-Apr-21 5:48 gggustafson 28-Apr-21 5:48
 My vote of 5 LightTempler26-Apr-21 10:33 LightTempler 26-Apr-21 10:33
 Re: My vote of 5 gggustafson27-Apr-21 14:54 gggustafson 27-Apr-21 14:54
 Last Visit: 31-Dec-99 18:00     Last Update: 24-Jul-21 7:55 Refresh 1