5

時間の経過とともに (240 時間)、明るい緑から濃い赤に色を変更したいと考えています。私が見ることができる最善の方法は、16 進コンボを 00FF00 から FF0000 に変更することです。

私の人生では、00FF00からFF0000まで動的にカウントする方法がわかりません。私は 10 日間を見ているので、240 時間以上かかる可能性が高いです。

誰でも私を助けることができますか?

私はアルゴリズムのクラスを受講したことがないので、この問題に関係があるのではないかと思います。

これを行うためのより良い方法があれば、私に知らせてください。

ここである種のコードを探しています。みんなありがとう。どの言語でもかまいませんが、必然的に C# に変換されます。

4

5 に答える 5

29

16 進値が示すように明るい色から明るい色に移行する場合は、RGB 空間ではなくHSV 空間で補間することをお勧めします。HSV 空間は、色相、彩度、値など、私たちが色について考える方法に近似しています。RGB 空間は、私たちの目の光に敏感な細胞がどのように機能するかを近似しています。

上のグラデーションは、FF0000 から 00FF00 までの線形 RGB 補間です。その中間値は 7f7f00 で、濁った茶色です。

中間の勾配は、HSV 空間での線形補間です。FF0000 と 00FF00 の両方が完全に飽和しており、同じ値 (明るさ) を持っているため、補間は全体を通して同じ明るさと彩度を維持するため、中央の値は明るい黄色の ffff00 になります。

3 番目の選択肢は、RGB 空間でのベクトル回転です。これは、中間値が B4B400 ( B4 hex = 180 dec = 255 / sqrt(2) ) であることを意味し、これは 2 つの効果の中間にあります。これは、各終点の大きさを計算し、同じ大きさになるように RGB 線形補間の結果をスケーリングし、2 つの色と原点の平面内の円弧でベクトルを効果的にスイープすることによって行われます。実際には異なる色の明るさを均等に重み付けしたり、直線的に見たりするわけではないため、正確ではありませんが、スイープ全体でかなり均一な強度を持ちますが、HSV は 2 つの値があるため、中央が少し明るくなります。 100% で。

無効な Imageshack リンクを削除


HSB をサポートしている Java では、アルゴリズムは単純です。最終値の 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 立方体のエッジとの交点を見つけたいと思うかもしれませんが、この場合はどちらの方法でも問題ありません。


補遺として、 Dave Green の立方体らせん色補間で示されているように、知覚される明るさに近い HSY 空間も検討する価値があります。

于 2009-03-21T19:01:29.197 に答える
8

コンポーネントの観点から考えてみてください。1 つの大きな 16 進数のように見えますが、実際には 3 つ並んでいます。

最初は赤が 0、緑が 255 (FF)、青が 0
です。最後に、赤が 255、緑が 0、青が 0 です。

したがって、(時間数 / 255) ごとに、赤を 1 増やし、緑を 1 減らします。

于 2009-03-20T22:45:41.037 に答える
4

time_remaining (値は 0 から 239 まで変化します)

緑 = 255 * (time_remaining / 239)
赤 = 255 - 緑
青 = 0

color = (赤、緑、青)

于 2009-03-20T22:51:10.493 に答える