检查图像是否有颜色

我想弄清楚图像是否有颜色。 在这个 StackOverflow问题上,有一个回复说我应该检查ImagePixelFormat枚举。 不幸的是,回复对我来说不是很清楚。 检查image.PixelFormat是否与PixelFormat.Format16bppGrayScale不同,是否可以安全地认为它是彩色图像? 枚举的其他值怎么样? MSDN文档不是很清楚……

您可以通过避免使用Color.FromArgb并迭代字节而不是整数来改进这一点,但我认为这对您来说更具可读性,并且更容易理解为一种方法。

一般的想法是将图像绘制成已知格式的位图(32bpp ARGB),然后检查该位图是否包含任何颜色。

锁定位图的位允许您使用不安全的代码比使用GetPixel快几倍地迭代它的颜色数据。

如果像素的alpha为0,则显然是GrayScale,因为alpha 0表示它完全不透明。 除此之外 – 如果R = G = B,则它是灰色的(如果它们= 255,则为黑色)。

 private static unsafe bool IsGrayScale(Image image) { using (var bmp = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppArgb)) { using (var g = Graphics.FromImage(bmp)) { g.DrawImage(image, 0, 0); } var data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat); var pt = (int*)data.Scan0; var res = true; for (var i = 0; i < data.Height * data.Width; i++) { var color = Color.FromArgb(pt[i]); if (color.A != 0 && (color.R != color.G || color.G != color.B)) { res = false; break; } } bmp.UnlockBits(data); return res; } } 

SimpleVar的答案大多是正确的:当源图像具有索引颜色格式时,代码无法正确处理。

要解决此问题,只需将外部using块替换为:

 using (var bmp = new Bitmap(image)) { 

并完全删除内部,因为不再需要Graphics对象。 无论原始图像的像素格式如何,这都将以非索引格式创建完美的图像副本。

  private bool isGrayScale(Bitmap processedBitmap) { bool res = true; unsafe { System.Drawing.Imaging.BitmapData bitmapData = processedBitmap.LockBits(new Rectangle(0, 0, processedBitmap.Width, processedBitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, processedBitmap.PixelFormat); int bytesPerPixel = System.Drawing.Bitmap.GetPixelFormatSize(processedBitmap.PixelFormat) / 8; int heightInPixels = bitmapData.Height; int widthInBytes = bitmapData.Width * bytesPerPixel; byte* PtrFirstPixel = (byte*)bitmapData.Scan0; Parallel.For(0, heightInPixels, y => { byte* currentLine = PtrFirstPixel + (y * bitmapData.Stride); for (int x = 0; x < widthInBytes; x = x + bytesPerPixel) { int b = currentLine[x]; int g = currentLine[x + 1]; int r = currentLine[x + 2]; if (b != g || r != g) { res = false; break; } } }); processedBitmap.UnlockBits(bitmapData); } return res; }