我试图弄清楚图像是否是彩色的。在这个PixelFormat
StackOverflow问题上,有一个回复说我应该检查Image
. 不幸的是,我的回答不是很清楚。检查是否image.PixelFormat
不同于PixelFormat.Format16bppGrayScale
认为它是彩色图像是否安全?枚举的其他值呢?MSDN 文档不是很清楚...
问问题
7719 次
3 回答
14
您可以通过避免使用 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;
}
}
于 2012-04-26T13:21:33.110 回答
0
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;
}
于 2018-07-19T12:12:16.190 回答
0
SimpleVar 的回答大部分是正确的:当源图像具有索引颜色格式时,该代码无法正确处理。
要解决这个问题,只需将外部using
块替换为:
using (var bmp = new Bitmap(image)) {
并完全移除内部using
,因为Graphics
不再需要该对象。无论原始图像的像素格式如何,这都会以非索引格式创建图像的完美副本。
于 2018-09-18T20:07:15.430 回答