我想随着时间的推移(240 小时)将颜色从亮绿色更改为深红色。我能看到的最好方法是将十六进制组合从 00FF00 更改为 FF0000。
我不知道如何在我的一生中从 00FF00 动态地计数到 FF0000。我正在查看超过 10 天的时间段,因此很可能需要超过 240 小时才能增加。
谁能帮我吗?
我从来没有上过算法课,所以我认为这可能与这个问题有关。
如果您有更好的方法来做到这一点,请告诉我。
我在这里寻找某种代码。多谢你们。它可以是任何语言,但不可避免地会转换为 C#。
如果您按照十六进制值的建议从亮色变为亮色,那么您可能希望在HSV 空间而不是 RGB 空间中进行插值。HSV 空间近似于我们对颜色的看法——色调、饱和度和值。RGB 空间近似于我们眼睛中光敏细胞的工作方式。
上梯度是从 FF0000 到 00FF00 的线性 RGB 插值。它的中间值为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 空间,它更接近于感知亮度,如Dave Green 的立方体螺旋颜色插值所示。
只需从组件的角度考虑它。尽管它看起来像一个大的十六进制数,但它实际上是三个并排的。
开始时红色为 0,绿色为 255(FF),蓝色为 0。
最后,红色为 255,绿色为 0,蓝色为 0。
因此,每(您拥有的时间量 / 255),红色加 1,绿色减 1。
time_remaining(值从 0 到 239 不等)
绿色 = 255 * (time_remaining / 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)));
}
这是 Pete 翻译成 C# 的 Java 代码,以防万一有人在寻找它。它非常适合我的目的(黑色到深红色和背面)。
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;
}