Inaccurate HSV Conversion on Android

I am trying to create a wallpaper and use the HSV transform in the android.graphics.color class. I was very surprised when I realized that converting the created HSV color with the given hue (0..360) to rgb color (integer) and the reverse conversion to HSV color will not lead to the same hue. This is my code:

int c = Color.HSVToColor(new float[] { 100f, 1, 1 }); float[] f = new float[3]; Color.colorToHSV(c, f); alert(f[0]); 

I start with a hue of 100 degrees and the result is 99.76471. I wonder why there is (in my opinion) a relatively large inaccuracy.

But a much bigger problem is that when you add this value to the code again, the new result decreases again.

 int c = Color.HSVToColor(new float[] { 99.76471f, 1, 1 }); float[] f = new float[3]; Color.colorToHSV(c, f); alert(f[0]); 

If I start with 99.76471, I get 99.52941. This is a problem for me. I did something similar in java with the class "java.awt.Color" where I did not have these problems. Unfortunately, I cannot use this class in android.

+6
source share
1 answer

This is an interesting problem. This cannot be avoided with the android class due to the low accuracy of the float. However, I found a similar solution written in javascript here .

If it's important enough that you want to define your own method / class for the conversion, here is a Java conversion that should give you better accuracy:

 @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 }; } 

I have to admit ignorance here - I did a quick conversion and did not have time to check correctly. There may be a better solution, but that should make you start at least.

+1
source

All Articles