Если вы переходите от яркого цвета к яркому цвету, как подсказывают шестнадцатеричные значения, то вы можете интерполировать в HSV-пространство , а не в RGB-пространство. Пространство HSV приблизительно соответствует нашему пониманию цвета - оттенка, насыщенности и ценности. Пространство RGB приблизительно соответствует тому, как работают светочувствительные клетки в наших глазах.
Верхний градиент - линейная RGB-интерполяция от FF0000 до 00FF00. Его среднее значение 7f7f00, мутный коричневый.
Средний градиент - это линейная интерполяция в пространстве HSV. Так как FF0000 и 00FF00 полностью насыщены и имеют одинаковое значение (яркость), интерполяция сохраняет одинаковую яркость и насыщенность во всем, поэтому центральное значение - ярко-желтый ffff00.
Третий вариант - это векторное вращение в пространстве RGB, которое будет означать, что среднее значение равно B4B400 (B4 hex = 180 dec = 255 / sqrt (2)), что находится где-то между этими двумя эффектами. Это делается путем вычисления величины каждой конечной точки, а затем масштабирования результата линейной интерполяции RGB, чтобы она была такой же величины, эффективно сместив вектор по дуге в плоскости двух цветов и начала координат. Поскольку мы на самом деле не взвешиваем разные цвета одинаково для яркости, или видим линейно, это не точно, но у него довольно равномерная интенсивность во время развертки, в то время как HSV немного светлее в середине, так как он имеет два значения на 100%.
удалена мертвая ссылка Imageshack
В Java, где у вас есть поддержка HSB, алгоритм прост - получить HSB конечных значений, линейно интерполировать их, как в других ответах RGB, а затем преобразовать, создать цвет со значениями h, s, v:
static Color hsvInterpolate ( float mix, Color c0, Color c1 ) {
float[] hsv0 = new float[3];
float[] hsv1 = new float[3];
float alt = 1.0f - mix;
Color.RGBtoHSB( c0.getRed(), c0.getGreen(), c0.getBlue(), hsv0 );
Color.RGBtoHSB( c1.getRed(), c1.getGreen(), c1.getBlue(), hsv1 );
float h = mix * hsv0 [ 0 ] + alt * hsv1 [ 0 ];
float s = mix * hsv0 [ 1 ] + alt * hsv1 [ 1 ];
float v = mix * hsv0 [ 2 ] + alt * hsv1 [ 2 ];
return Color.getHSBColor ( h, s, v );
}
Я не верю, что в C # встроены преобразования, поэтому код не очень полезен.
static Color vectorInterpolate ( float mix, Color c0, Color c1 ) {
float alt = 1.0f - mix;
double x0 = c0.getRed();
double y0 = c0.getGreen();
double z0 = c0.getBlue();
double x1 = c1.getRed();
double y1 = c1.getGreen();
double z1 = c1.getBlue();
double mag0 = sqrt( x0*x0 + y0*y0 + z0*z0 );
double mag1 = sqrt( x1*x1 + y1*y1 + z1*z1 );
double x = mix * x0 + alt * x1;
double y = mix * y0 + alt * y1;
double z = mix * z0 + alt * z1;
double mag = mix * mag0 + alt * mag1;
double scale = mag / sqrt( x*x + y*y + z*z );
return new Color (
clamp ( x * scale ),
clamp ( y * scale ),
clamp ( z * scale ) );
}
static int clamp ( double value ) {
int x = (int) round ( value );
if ( x > 255 ) return 255;
if ( x < 0 ) return 0;
return x;
}
Возможно, вы захотите найти пересечение вектора с краем куба RGB, а не просто зажать его, но в этом случае это не имеет значения в любом случае.
В качестве дополнения также стоит рассмотреть пространство HSY, которое ближе к воспринимаемой яркости, как показано спиралью куба Дэйва Грина цветными интерполяциями.