下面的代码依赖于 .NET System.Drawing.Bitmap类和System.Drawing.Color类,但我相信 MonoTouch 都支持这些(至少基于我对Mono 文档的阅读)。
因此,假设您在名为bmp的System.Drawing.Bitmap对象中有一个图像。您可以使用如下代码获得该图像的平均色调:
float hue = 0;
int w = bmp.Width;
int h = bmp.Height;
for (int y = 0; y < bmp.Height; y++) {
for (int x = 0; x < bmp.Width; x++) {
Color c = bmp.GetPixel(x, y);
hue += c.GetHue();
}
}
hue /= (bmp.Width*bmp.Height);
这是对整个图像的迭代,对于大图像来说可能会很慢。如果性能是一个问题,您可能希望将评估的像素限制为图像的较小部分(如juhan_h建议的那样),或者只使用较小的图像开始。
然后给定平均色调,在 0 到 360 度的范围内,您可以将该数字映射到颜色名称,如下所示:
String[] hueNames = new String[] {
"red","orange","yellow","green","cyan","blue","purple","pink"
};
float[] hueValues = new float[] {
18, 54, 72, 150, 204, 264, 294, 336
};
String hueName = hueNames[0];
for (int i = 0; i < hueNames.Length; i++) {
if (hue < hueValues[i]) {
hueName = hueNames[i];
break;
}
}
我刚刚估计了hueValues和hueNames表的一些值,因此您可能需要调整这些表以满足您的要求。这些值是颜色似乎变为下一个名称的点(例如,红色和橙色之间的分界线出现在大约 18 度处)。
要了解色调值所代表的颜色范围,请查看下面的色轮。从顶部开始,它从红色/橙色(约 0° - 北)到黄色/绿色(约 90° - 东),再到青色(约 180° - 南),再到蓝色/紫色(约 270° - 西) .
但是,您应该注意,我们忽略了饱和度和亮度级别,因此在褪色和低光照条件下,此计算的结果将不太理想。但是,如果您只对墙壁的一般颜色感兴趣,我认为它可能足以满足您的需求。