如何计算位图的平均rgb颜色值

在我的C#(3.5)应用程序中,我需要获取位图的红色,绿色和蓝色通道的平均颜色值。 最好不使用外部库。 可以这样做吗? 如果是这样,怎么样? 提前致谢。

尝试使事情更精确:位图中的每个像素都有一定的RGB颜色值。 我想获得图像中所有像素的平均RGB值。

最快的方法是使用不安全的代码:

BitmapData srcData = bm.LockBits( new Rectangle(0, 0, bm.Width, bm.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); int stride = srcData.Stride; IntPtr Scan0 = srcData.Scan0; long[] totals = new long[] {0,0,0}; int width = bm.Width; int height = bm.Height; unsafe { byte* p = (byte*) (void*) Scan0; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { for (int color = 0; color < 3; color++) { int idx = (y*stride) + x*4 + color; totals[color] += p[idx]; } } } } int avgB = totals[0] / (width*height); int avgG = totals[1] / (width*height); int avgR = totals[2] / (width*height); 

注意:我没有测试这段代码...(我可能已经削减了一些角落)

此代码还可以提供32位图像。 对于24位图像。 将x * 4更改为x * 3

这是一个更简单的方法:

 Bitmap bmp = new Bitmap(1, 1); Bitmap orig = (Bitmap)Bitmap.FromFile("path"); using (Graphics g = Graphics.FromImage(bmp)) { // updated: the Interpolation mode needs to be set to // HighQualityBilinear or HighQualityBicubic or this method // doesn't work at all. With either setting, the results are // slightly different from the averaging method. g.InterpolationMode = InterpolationMode.HighQualityBicubic; g.DrawImage(orig, new Rectangle(0, 0, 1, 1)); } Color pixel = bmp.GetPixel(0, 0); // pixel will contain average values for entire orig Bitmap byte avgR = pixel.R; // etc. 

基本上,您使用DrawImage将原始位图复制到1像素位图。 然后,该1个像素的RGB值将表示整个原件的平均值。 GetPixel相对较慢,但只有当您在大型Bitmap上逐像素地使用它时才会如此。 在这里召唤一次并不重要。

使用LockBits确实很快,但是一些Windows用户具有防止执行“不安全”代码的安全策略。 我之所以提到这一点,是因为这个事实让我最近陷入了困境。

更新 :将InterpolationMode设置为HighQualityBicubic,此方法所需的时间大约是LockBits的平均值的两倍; 使用HighQualityBilinear,它只需要稍长于LockBits。 因此,除非您的用户拥有禁止unsafe代码的安全策略,否则绝对不要使用我的方法。

更新2:随着时间的推移,我现在意识到为什么这种方法根本不起作用。 即使是最高质量的插值算法也只包含几个相邻像素,因此在不丢失信息的情况下可以压缩多少图像是有限的。 无论您使用何种算法,将图像压缩到一个像素都远远超出此限制。

唯一的方法是逐步缩小图像(可能每次缩小一半),直到将其缩小到一个像素的大小。 我不能用单词表达完全浪费时间写这样的东西,所以我很高兴我在想到它时就停止了自己。 🙂

拜托,没有人再投票支持这个答案了 – 这可能是我最愚蠢的想法。

这种事情会起作用,但它可能不够快,不能那么有用。

 public static Color getDominantColor(Bitmap bmp) { //Used for tally int r = 0; int g = 0; int b = 0; int total = 0; for (int x = 0; x < bmp.Width; x++) { for (int y = 0; y < bmp.Height; y++) { Color clr = bmp.GetPixel(x, y); r += clr.R; g += clr.G; b += clr.B; total++; } } //Calculate average r /= total; g /= total; b /= total; return Color.FromArgb(r, g, b); }