根據您的意見,似乎你基本上試圖將位圖的全綵色調色板減少到只有比較提取RGB值你指定的12個。顯然,對於位圖中的每個像素,應該挑選出那些12箇中的「最佳匹配」。
我還是不明白爲什麼你需要HSV值,因爲它只是RGB組件的不同表示 - 它實際上並沒有改變問題或解決方案。
找到任何RGB顏色的最佳匹配的直接方法如下所示。
首先構建某種包含要匹配的顏色的列表。我已經使用了一個Map,因爲你提到你(也)想知道的名稱的顏色,而不僅僅是RGB值。
Map<String, Integer> mColors = new HashMap<String, Integer>();
mColors.put("red", Color.rgb(255, 0, 0));
mColors.put("pink", Color.rgb(255, 192, 203));
mColors.put("voilet", Color.rgb(36, 10, 64));
mColors.put("blue", Color.rgb(0, 0, 255));
mColors.put("green", Color.rgb(0, 255, 0));
mColors.put("yellow", Color.rgb(255, 255, 0));
mColors.put("orange", Color.rgb(255, 104, 31));
mColors.put("white", Color.rgb(255, 255, 255));
mColors.put("black", Color.rgb(0, 0, 0));
mColors.put("gray", Color.rgb(128, 128, 128));
mColors.put("tea", Color.rgb(193, 186, 176));
mColors.put("cream", Color.rgb(255, 253, 208));
然後,只是做一個方法,會告訴你最好的匹配。你可以在你的第二個for循環中調用它,並將它傳遞給當前的像素顏色。我已經添加了一些內嵌評論來解釋不同的步驟,但它確實很瑣碎。
private String getBestMatchingColorName(int pixelColor) {
// largest difference is 255 for every colour component
int currentDifference = 3 * 255;
// name of the best matching colour
String closestColorName = null;
// get int values for all three colour components of the pixel
int pixelColorR = Color.red(pixelColor);
int pixelColorG = Color.green(pixelColor);
int pixelColorB = Color.blue(pixelColor);
Iterator<String> colorNameIterator = mColors.keySet().iterator();
// continue iterating if the map contains a next colour and the difference is greater than zero.
// a difference of zero means we've found an exact match, so there's no point in iterating further.
while (colorNameIterator.hasNext() && currentDifference > 0) {
// this colour's name
String currentColorName = colorNameIterator.next();
// this colour's int value
int color = mColors.get(currentColorName);
// get int values for all three colour components of this colour
int colorR = Color.red(color);
int colorG = Color.green(color);
int colorB = Color.blue(color);
// calculate sum of absolute differences that indicates how good this match is
int difference = Math.abs(pixelColorR - colorR) + Math.abs(pixelColorG - colorG) + Math.abs(pixelColorB - colorB);
// a smaller difference means a better match, so keep track of it
if (currentDifference > difference) {
currentDifference = difference;
closestColorName = currentColorName;
}
}
return closestColorName;
}
使用一些預定義的顏色常數的用於快速測試的結果:
Color.RED (-65536) -> red (-65536)
Color.GREEN (-16711936) -> green (-16711936)
Color.BLUE (-16776961) -> blue (-16776961)
Color.BLACK (-16777216) -> black (-16777216)
Color.WHITE (-1) -> white (-1)
Color.GRAY (-7829368) -> gray (-8355712)
Color.YELLOW (-256) -> yellow (-256)
Color.MAGENTA (-65281) -> pink (-16181)
第一個數字其間括號是用於顏色恆定的實際int值,第二個是int值找到最佳匹配,並在名稱前面加上名稱。
Color.MAGENTA
的結果還說明了爲什麼不應該直接比較顏色的int值。實際的int值是-65281
,這與Color.RED
(-65536)的值非常接近。然而,基於不同組件的最佳匹配是「粉紅色」,其具有-16181值。顯然,這使得完整意義上知道一個顏色定義爲4個字節:
顏色表示爲包裝整數,由4個字節:alpha,紅色, 綠,藍。 (...)組件存儲如下(alpha < < 24) | (紅色< < 16)| (綠色< < 8)|藍色。
Source: android.graphics.Color reference.
//編輯:與HSV值似乎工作也沒關係。我確實得到了「洋紅色」的不同結果,儘管最接近的配對是紫羅蘭色,而不是粉紅色。您可能需要仔細檢查值和斷點。例如,我可以想象,將'H'部分標準化可能會更好。這取決於你...
private String getBestMatchingHsvColor(int pixelColor) {
// largest difference is 360(H), 1(S), 1(V)
float currentDifference = 360 + 1 + 1;
// name of the best matching colour
String closestColorName = null;
// get HSV values for the pixel's colour
float[] pixelColorHsv = new float[3];
Color.colorToHSV(pixelColor, pixelColorHsv);
Iterator<String> colorNameIterator = mColors.keySet().iterator();
// continue iterating if the map contains a next colour and the difference is greater than zero.
// a difference of zero means we've found an exact match, so there's not point in iterating further.
while (colorNameIterator.hasNext() && currentDifference > 0) {
// this colour's name
String currentColorName = colorNameIterator.next();
// this colour's int value
int color = mColors.get(currentColorName);
// get HSV values for this colour
float[] colorHsv = new float[3];
Color.colorToHSV(color, colorHsv);
// calculate sum of absolute differences that indicates how good this match is
float difference = Math.abs(pixelColorHsv[0] - colorHsv[0]) + Math.abs(pixelColorHsv[1] - colorHsv[1]) + Math.abs(pixelColorHsv[2] - colorHsv[2]);
// a smaller difference means a better match, so store it
if (currentDifference > difference) {
currentDifference = difference;
closestColorName = currentColorName;
}
}
return closestColorName;
}
要獲得最接近你的12種顏色之一的顏色,你必須基本上限定一些RGB值與每個顏色相匹配的程度。最直接的方法可能是計算三個顏色分量中的每一個的絕對差值並將它們相加。具有最小差異的顏色將是您最好的搭配。儘管這樣做可能會變得相當昂貴,因爲儘管一些優化是絕對有可能的,但你必須做這個'width * height * 12'次。 – 2011-12-24 02:38:30
我必須將RBG轉換爲HSV嗎? – 2011-12-24 02:54:58
我不確定你的意思。據我可以告訴你有12種顏色的RGB值,Rajdeep的答案顯示瞭如何獲得特定像素的三種顏色分量。你需要什麼HSV值? – 2011-12-24 03:21:21