[Edit: C# Code as requested]
Ok, well, in C# it actually could be done more-or-less like the link I gave, but there's really no reason to do all the masking and shifting, since you can already access a System.Drawing.Color
's ARGB values directly in C#. (Oh, by the way, I wasn't sure whether to average the Alpha value, I went with "yes".)
If your source data is in int
s instead Color
, you can always just convert the values with the function Color.FromArgb
with a single int
argument. (It supports also creating it from individual values, as shown in the example code's return
s.)
The LINQ version looks a loot easier to understand to me, but I gave the other one since it's basically a C# port of the original code I linked.
LINQ version:
public Color AverageColorsWithLINQ(Color[] ColorsToAverage)
{
// the LINQ way
int AlphaAverage = (int)ColorsToAverage.Average(c => c.A);
int RedAverage = (int)ColorsToAverage.Average(c => c.R);
int GreenAverage = (int)ColorsToAverage.Average(c => c.G);
int BlueAverage = (int)ColorsToAverage.Average(c => c.B);
return Color.FromArgb(
AlphaAverage, RedAverage, GreenAverage, BlueAverage
);
}
Loop, sum, and divide version:
public Color AverageColorsWithFor(Color[] ColorsToAverage)
{
int AlphaTotal = 0;
int RedTotal = 0;
int GreenTotal = 0;
int BlueTotal = 0;
foreach (Color AColor in ColorsToAverage)
{
AlphaTotal += AColor.A;
RedTotal += AColor.R;
GreenTotal += AColor.G;
BlueTotal += AColor.B;
}
double NumberOfColors = ColorsToAverage.Length;
int AlphaAverage = (int)(AlphaTotal / NumberOfColors);
int RedAverage = (int)(RedTotal / NumberOfColors);
int GreenAverage = (int)(GreenTotal / NumberOfColors);
int BlueAverage = (int)(BlueTotal / NumberOfColors);
return Color.FromArgb(
AlphaAverage, RedAverage, GreenAverage, BlueAverage
);
}
Well, I would check out How do I adjust the brightness of a color? which covers several different ways of doing it.
I'm not really sure what model Windows 7 is using to do it, but basically there are different models you can use to pick a color out of colorspace, and, in particular, HSL and HSV (http://en.wikipedia.org/wiki/HSL_and_HSV) can both be used to increase and decrease the perceived brightness of the color without altering it too much.
Upon re-reading your question I think I may have misunderstood. If you actually mean to average a block of colors, I would give this a shot: http://blog.soulwire.co.uk/code/actionscript-3/extract-average-colours-from-bitmapdata . It looks like it's doing it via RGB, though, and I'm not familiar enough to know whether that gives good results (for instance, it doesn't do a good job of raising or lowering brightness of a color to adjust the colors proportionally...)
So, if that doesn't give you good results, I would recommend trying converting all the colors to either HSV or HSL, averaging those values together instead, and then converting back to RGB.