Here is a straightforward, pure WPF solution, which directly accesses the pixel buffer of a BitmapSource. It works for the Bgr24
, Bgr32
, Bgra32
and Pbgra32
formats. In case of Pbgra32
all alpha values should be 255, otherwise you may have to divide each pixel's (pre-multiplied) color values by alpha / 255
.
public Color GetAverageColor(BitmapSource bitmap)
{
var format = bitmap.Format;
if (format != PixelFormats.Bgr24 &&
format != PixelFormats.Bgr32 &&
format != PixelFormats.Bgra32 &&
format != PixelFormats.Pbgra32)
{
throw new InvalidOperationException("BitmapSource must have Bgr24, Bgr32, Bgra32 or Pbgra32 format");
}
var width = bitmap.PixelWidth;
var height = bitmap.PixelHeight;
var numPixels = width * height;
var bytesPerPixel = format.BitsPerPixel / 8;
var pixelBuffer = new byte[numPixels * bytesPerPixel];
bitmap.CopyPixels(pixelBuffer, width * bytesPerPixel, 0);
long blue = 0;
long green = 0;
long red = 0;
for (int i = 0; i < pixelBuffer.Length; i += bytesPerPixel)
{
blue += pixelBuffer[i];
green += pixelBuffer[i + 1];
red += pixelBuffer[i + 2];
}
return Color.FromRgb((byte)(red / numPixels), (byte)(green / numPixels), (byte)(blue / numPixels));
}
As the Image control's Source
property is of type ImageSource
, you have to cast it to BitmapSource
before passing it to the method:
var bitmap = (BitmapSource)image.Source;
var color = GetAverageColor(bitmap);