En primer lugar, solicita la interpolación lineal, pero no especifica que el color B viva en la línea entre el color A y el color C; esto es necesario. En segundo lugar, no especificó, pero voy a hacer una suposición simplificadora de que el color B es el punto medio de la línea entre el color A y el color C; el siguiente código se modifica fácilmente si esto no es cierto. Por último, cambié tu suposición de que el parámetro es un número entero entre cero y cien para ser un doble entre cero y uno. El código es más fácil de escribir y más fácil de entender en el último caso, y aún puede usarse con el primero (divida sus entradas entre cien).
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);
}
}
¿Cómo se modifica esto si el color B no es el punto medio entre el color A y el color C? La forma más fácil es la siguiente. Si el parámetro (lo que llamo "lambda
") es menor que 0.5
, multiplique lambda
por dos y devuelva el color interpolado entre el color A y el color B. Si el parámetro es mayor que 0.5
, multiplique lambda
por dos y reste uno (este mapa [0.5, 1]
en [0, 1]
) y devuelve el color interpolado entre el color B y el color C.
Si no le gusta el requisito de que el color B viva en la línea entre el color A y el color C, puede usar exactamente la modificación que Acabo de describir una interpolación lineal por partes entre los colores.
Finalmente, no especificó si quiere interpolar el llamado valor alfa (la 'A' en "ARGB"). El código anterior se modifica fácilmente para manejar esta situación también. Agregue uno más ComponentSelector
definido como color => color.A
, use InterpolateComponent
para interpolar este valor y use la sobrecarga Color.FromArgb(int, int, int, int)
de Color.FromArgb
.
no puede ser lineal con tres puntos al azar – RBarryYoung