Алгоритм Вопрос:Необходимо динамически увеличивать значение от 00FF00 до FF0000 с течением времени, C#/Java.

StackOverflow https://stackoverflow.com/questions/668263

  •  21-08-2019
  •  | 
  •  

Вопрос

Я хочу изменить цвет с ярко-зеленого на темно-красный с течением времени (240 часов).Лучший способ, который я вижу, — это изменить шестнадцатеричную комбинацию с 00FF00 на FF0000.

Я не знаю, как динамически считать до FF0000 от 00FF00 хоть убей.Я рассматриваю период в 10 дней, так что, скорее всего, приращение составит более 240 часов.

Может кто-нибудь мне помочь?

Я никогда не посещал курсы по алгоритмам, поэтому думаю, что это может иметь какое-то отношение к этой проблеме.

Если у вас есть лучший способ сделать это, дайте мне знать.

Я ищу здесь какой-то код.Спасибо ребята.Он может быть на любом языке, но неизбежно будет преобразован в C#.

Это было полезно?

Решение

Просто подумайте об этом с точки зрения компонентов.Хотя это выглядит как одно большое шестнадцатеричное число, на самом деле это три числа, расположенных рядом.

В начале красный — 0, зеленый — 255 (FF), синий — 0.
В конце красный — 255, зеленый — 0, синий — 0.

Итак, каждые (количество времени, которое у вас есть / 255), увеличивайте красный на 1 и уменьшайте зеленый на 1.

Другие советы

Если вы переходите от яркого цвета к яркому цвету, как предполагают шестнадцатеричные значения, вы можете выполнить интерполяцию в пространство 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, которое ближе к воспринимаемой яркости, как показано на рис. Кубическая спираль Дэйва Грина цветовые интерполяции.

time_remaining (значение варьируется от 0 до 239)

зеленый = 255 * (оставшееся_время / 239)
красный = 255 - зеленый
синий = 0

цвет = (красный, зеленый, синий)

вот быстрый ответ Java от красного до зеленого (конечно, вы можете это изменить), значение — текущее valueвовремя и all это сумма времени...

public static String progressiveColor(int value, int all){

    int red = 255 - (int)((float)(value*255)/(float)all);
    int green = (int)((float)(value*255)/(float)all);
    return String.format("#%06X", (0xFFFFFF & Color.argb(255, red, green, 0)));

}

Вот Java-код Пита, переведенный на C#, если кто-то его искал.Для моих целей он отлично подходит (от черного до темно-красного и обратно).

    static Color VectorInterpolate(float mix, Color c0, Color c1)
    {
        float alt = 1.0f - mix;

        double x0 = c0.R;
        double y0 = c0.G;
        double z0 = c0.B;

        double x1 = c1.R;
        double y1 = c1.G;
        double z1 = c1.B;

        double mag0 = Math.Sqrt(x0 * x0 + y0 * y0 + z0 * z0);
        double mag1 = Math.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 / Math.Sqrt(x * x + y * y + z * z);

        return Color.FromRgb(Clamp(x * scale), Clamp(y * scale), Clamp(z * scale));
    }

    static byte Clamp(double value)
    {
        var x = (int)Math.Round(value);

        if (x > 255) return 255;
        if (x < 0) return 0;
        return (byte) x;
    }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top