Во-первых, вы запрашиваете линейную интерполяцию, но не указываете, что цвет B находится на линии между цветом A и цветом C; это необходимо Во-вторых, вы не указали, но я собираюсь сделать упрощающее предположение, что цвет B является средней точкой линии между цветом A и цветом C; следующий код легко модифицируется, если это не так. Наконец, я изменил ваше предположение, что параметр должен быть целым числом от нуля до ста, чтобы быть двойным числом от нуля до единицы. Код легче написать и легче понять в последнем случае, и он все еще может использоваться с первым (разделите ваши входные данные на сто).
class ColorInterpolator {
delegate byte ComponentSelector(Color color);
static ComponentSelector _redSelector = color => color.R;
static ComponentSelector _greenSelector = color => color.G;
static ComponentSelector _blueSelector = color => color.B;
public static Color InterpolateBetween(
Color endPoint1,
Color endPoint2,
double lambda) {
if (lambda < 0 || lambda > 1) {
throw new ArgumentOutOfRangeException("lambda");
}
Color color = Color.FromRgb(
InterpolateComponent(endPoint1, endPoint2, lambda, _redSelector),
InterpolateComponent(endPoint1, endPoint2, lambda, _greenSelector),
InterpolateComponent(endPoint1, endPoint2, lambda, _blueSelector)
);
return color;
}
static byte InterpolateComponent(
Color endPoint1,
Color endPoint2,
double lambda,
ComponentSelector selector) {
return (byte)(selector(endPoint1)
+ (selector(endPoint2) - selector(endPoint1)) * lambda);
}
}
Как изменить это, если цвет B не является средней точкой между цветом A и цветом C? Самый простой способ заключается в следующем. Если параметр (то, что я называю «lambda
») меньше 0.5
, умножьте lambda
на два и верните интерполированный цвет между цветом A и цветом B. Если параметр больше 0.5
, умножьте lambda
на два и вычтите одно (это отобразит [0.5, 1]
на [0, 1]
) и верните интерполированный цвет между цветом B и цветом C.
Если вам не нравится требование, чтобы цвет B находился на линии между цветом A и цветом C, то вы можете использовать именно ту модификацию, которую я только что описал, для выполнения кусочно-линейной интерполяции между цветами.
Наконец, вы не указали, хотите ли вы интерполировать так называемое альфа-значение («A» в «ARGB»). Приведенный выше код легко модифицируется, чтобы справиться и с этой ситуацией. Добавьте еще один ComponentSelector
, определенный как color => color.A
, используйте InterpolateComponent
для интерполяции этого значения и используйте перегрузку Color.FromArgb(int, int, int, int)
Color.FromArgb
.