在我的 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
GetPixel
的差别惊人。使用 GetPixel
两次循环遍历一个 500x600 的图像需要约 1000 毫秒,而使用这种方法只需要约 13 毫秒。 - mpendstData
是从哪里来的。它是srcData
的拼写错误还是发生了一些魔法? - prokilomer这样的方法可以起作用,但可能速度不够快,因此并没有那么有用。
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);
}
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.