patterncsharpMinor
Calculation of RGB values given min and max values
Viewed 0 times
calculationandminmaxvaluesrgbgiven
Problem
I made a start at translating the accepted answer's code here into C#. Any suggestions on the correctness of the translation and the correctness of the original code would be very much appreciated.
What is a bit worrying is that:
should really caclulate:
rather than:
I guess there is some rounding issue.
Any ideas?
public class RgbValues
{
public int Red { get; set; }
public int Green { get; set; }
public int Blue { get; set; }
}
public static RgbValues GetRgbValues(float minimumValue, float maximumValue, float value)
{
var rgbValues = new RgbValues();
var halfmax = (minimumValue + maximumValue) / 2.0;
rgbValues.Blue = (int) Math.Max(0.0, 255.0 * (1.0 - value/halfmax));
rgbValues.Red = (int)Math.Max(0.0, 255.0 * (value / halfmax - 1.0));
rgbValues.Green = 255 - rgbValues.Blue - rgbValues.Red;
return rgbValues;
}What is a bit worrying is that:
GetRgbValues(10, 10113, 10113)should really caclulate:
red = 255, green = 0, blue = 0rather than:
red = 254, green = 1, blue = 0I guess there is some rounding issue.
Any ideas?
Solution
Calculations like these can be hard to understand, so I would try to strive for something that is clearly correct, not just correct.
What I would do:
In code:
This code is longer than the original, but I think it's also clearer about what it does. I didn't figure out what your code did until I read the SO question, I think it's much more likely I would have succeeded with this code.
What I would do:
- normalize the value from \$[min, max]\$ to \$[0, 2]\$
- realize that the "strength" of a color is \$1 - |value - color|\$ (where \$color\$ is \$0\$ for blue, \$1\$ for green and \$2\$ for red), so compute that
- clip the computer strength to remove negative numbers
- finally multiply it by \$255\$ and convert to
int(while also rounding the value, to avoid bias towards smaller numbers)
In code:
public static RgbValues GetRgbValues(float minimum, float maximum, float value)
{
var normalizedValue = Normalize(minimum, maximum, value);
return new RgbValues
{
Blue = Distance(normalizedValue, 0),
Green = Distance(normalizedValue, 1),
Red = Distance(normalizedValue, 2)
};
}
private static float Normalize(float minimum, float maximum, float value)
{
return (value - minimum) / (maximum - minimum) * 2;
}
private static int Distance(float value, float color)
{
var distance = Math.Abs(value - color);
var colorStrength = 1 - distance;
if (colorStrength < 0)
colorStrength = 0;
return (int)Math.Round(colorStrength * 255);
}This code is longer than the original, but I think it's also clearer about what it does. I didn't figure out what your code did until I read the SO question, I think it's much more likely I would have succeeded with this code.
Code Snippets
public static RgbValues GetRgbValues(float minimum, float maximum, float value)
{
var normalizedValue = Normalize(minimum, maximum, value);
return new RgbValues
{
Blue = Distance(normalizedValue, 0),
Green = Distance(normalizedValue, 1),
Red = Distance(normalizedValue, 2)
};
}
private static float Normalize(float minimum, float maximum, float value)
{
return (value - minimum) / (maximum - minimum) * 2;
}
private static int Distance(float value, float color)
{
var distance = Math.Abs(value - color);
var colorStrength = 1 - distance;
if (colorStrength < 0)
colorStrength = 0;
return (int)Math.Round(colorStrength * 255);
}Context
StackExchange Code Review Q#64708, answer score: 5
Revisions (0)
No revisions yet.