Android 上的 HSV 转换不准确
Inaccurate HSV conversion on Android
我正在尝试创建壁纸,并且在 "android.graphics.color" class 中使用 HSV 转换。当我意识到将创建的具有指定色调 (0..360) 的 HSV 颜色转换为 rgb 颜色(整数)并反向转换为 HSV 颜色不会产生相同的色调时,我感到非常惊讶。这是我的代码:
int c = Color.HSVToColor(new float[] { 100f, 1, 1 });
float[] f = new float[3];
Color.colorToHSV(c, f);
alert(f[0]);
我从 100 度的色调开始,结果是 99.76471。
我想知道为什么会有那个(在我看来)比较大的错误。
但一个更大的问题是,当您再次将那个值放入代码中时,新的结果再次减少。
int c = Color.HSVToColor(new float[] { 99.76471f, 1, 1 });
float[] f = new float[3];
Color.colorToHSV(c, f);
alert(f[0]);
如果我从 99.76471 开始,我得到 99.52941。这对我来说是个问题。
我在 java 和 "java.awt.Color" class 中做了类似的事情,但我没有遇到这些问题。不幸的是,我不能在 android.
中使用这个 class
这是一个有趣的问题。由于浮点精度低,android class 无法避免。但是,我在javascript here.
中找到了类似的解决方案
如果您想要定义自己的 method/class 来进行转换,那么这里是一个 Java 转换,它应该会给您更好的精度:
@Size(3)
/** Does the same as {@link android.graphics.Color#colorToHSV(int, float[])} */
public double[] colorToHSV(@ColorInt int color) {
//this line copied vertabim
return rgbToHsv((color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF);
}
@Size(3)
public double[] rgbToHsv(double r, double g, double b) {
final double max = Math.max(r, Math.max(g, b));
final double min = Math.min(r, Math.min(g, b));
final double diff = max - min;
final double h;
final double s = ((max == 0d)? 0d : diff / max);
final double v = max / 255d;
if (min == max) {
h = 0d;
} else if (r == max) {
double tempH = (g - b) + diff * (g < b ? 6: 0);
tempH /= 6 * diff;
h = tempH;
} else if (g == max) {
double tempH = (b - r) + diff * 2;
tempH /= 6 * diff;
h = tempH;
} else {
double tempH = (r - g) + diff * 4;
tempH /= 6 * diff;
h = tempH;
}
return new double[] { h, s, v };
}
在这里我不得不承认我的无知 - 我已经完成了快速转换并且没有时间进行适当的测试。可能有更优化的解决方案,但这至少应该让您入门。
我正在尝试创建壁纸,并且在 "android.graphics.color" class 中使用 HSV 转换。当我意识到将创建的具有指定色调 (0..360) 的 HSV 颜色转换为 rgb 颜色(整数)并反向转换为 HSV 颜色不会产生相同的色调时,我感到非常惊讶。这是我的代码:
int c = Color.HSVToColor(new float[] { 100f, 1, 1 });
float[] f = new float[3];
Color.colorToHSV(c, f);
alert(f[0]);
我从 100 度的色调开始,结果是 99.76471。 我想知道为什么会有那个(在我看来)比较大的错误。
但一个更大的问题是,当您再次将那个值放入代码中时,新的结果再次减少。
int c = Color.HSVToColor(new float[] { 99.76471f, 1, 1 });
float[] f = new float[3];
Color.colorToHSV(c, f);
alert(f[0]);
如果我从 99.76471 开始,我得到 99.52941。这对我来说是个问题。 我在 java 和 "java.awt.Color" class 中做了类似的事情,但我没有遇到这些问题。不幸的是,我不能在 android.
中使用这个 class这是一个有趣的问题。由于浮点精度低,android class 无法避免。但是,我在javascript here.
中找到了类似的解决方案如果您想要定义自己的 method/class 来进行转换,那么这里是一个 Java 转换,它应该会给您更好的精度:
@Size(3)
/** Does the same as {@link android.graphics.Color#colorToHSV(int, float[])} */
public double[] colorToHSV(@ColorInt int color) {
//this line copied vertabim
return rgbToHsv((color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF);
}
@Size(3)
public double[] rgbToHsv(double r, double g, double b) {
final double max = Math.max(r, Math.max(g, b));
final double min = Math.min(r, Math.min(g, b));
final double diff = max - min;
final double h;
final double s = ((max == 0d)? 0d : diff / max);
final double v = max / 255d;
if (min == max) {
h = 0d;
} else if (r == max) {
double tempH = (g - b) + diff * (g < b ? 6: 0);
tempH /= 6 * diff;
h = tempH;
} else if (g == max) {
double tempH = (b - r) + diff * 2;
tempH /= 6 * diff;
h = tempH;
} else {
double tempH = (r - g) + diff * 4;
tempH /= 6 * diff;
h = tempH;
}
return new double[] { h, s, v };
}
在这里我不得不承认我的无知 - 我已经完成了快速转换并且没有时间进行适当的测试。可能有更优化的解决方案,但这至少应该让您入门。