这里有一个更简单的方法:
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 相对较慢,但仅当您在大型位图上逐个像素地使用它时。在这里调用一次没什么大不了的。
使用 LockBits 确实很快,但一些 Windows 用户有防止执行“不安全”代码的安全策略。我之所以提到这一点,是因为这个事实最近让我很不爽。
更新:将 InterpolationMode 设置为 HighQualityBicubic,此方法所需的时间大约是使用 LockBits 进行平均的两倍;使用 HighQualityBilinear,它只需要比 LockBits 稍长的时间。因此,除非您的用户有禁止unsafe 代码的安全策略,否则绝对不要使用我的方法。
更新 2:随着时间的推移,我现在意识到为什么这种方法根本行不通。即使是最高质量的插值算法也只包含几个相邻像素,因此在不丢失信息的情况下可以压缩多少图像是有限度的。无论您使用什么算法,将图像压缩到一个像素都远远超出了这个限制。
做到这一点的唯一方法是逐步缩小图像(可能每次缩小一半),直到将其缩小到一个像素的大小。我无法用语言来表达写这样的东西是多么浪费时间,所以我很高兴我一想到它就停下来了。 :)
请不要再为这个答案投票 - 这可能是我有史以来最愚蠢的想法。