C# 如何在.NET中检测位图是否具有Alpha通道
有人可以推荐一种更好的方法来检测位图是否具有Alpha通道以及是否使用了它?这种方法对我来说很有效,但如果图像非常大,则可能效率低下,因为在最坏的情况下,它会循环所有像素:C# 如何在.NET中检测位图是否具有Alpha通道,c#,.net,image,bitmap,alpha,C#,.net,Image,Bitmap,Alpha,有人可以推荐一种更好的方法来检测位图是否具有Alpha通道以及是否使用了它?这种方法对我来说很有效,但如果图像非常大,则可能效率低下,因为在最坏的情况下,它会循环所有像素: private static bool IsAlphaBitmap(Bitmap bmp, out BitmapData bmpData) { Rectangle bmpBounds = new Rectangle(0, 0, bmp.Width, bmp.Height); bmpData = bmp.Lo
private static bool IsAlphaBitmap(Bitmap bmp, out BitmapData bmpData)
{
Rectangle bmpBounds = new Rectangle(0, 0, bmp.Width, bmp.Height);
bmpData = bmp.LockBits(bmpBounds, ImageLockMode.ReadOnly, bmp.PixelFormat);
try
{
for (int y = 0; y <= bmpData.Height - 1; y++)
{
for (int x = 0; x <= bmpData.Width - 1; x++)
{
Color pixelColor = Color.FromArgb(
Marshal.ReadInt32(
bmpData.Scan0, (bmpData.Stride * y) + (4 * x)));
if (pixelColor.A > 0 & pixelColor.A < 255)
{
return true;
}
}
}
}
finally
{
bmp.UnlockBits(bmpData);
}
return false;
}
private static bool IsAlphaBitmap(位图bmp,out位图数据bmpData)
{
矩形bmpBounds=新矩形(0,0,bmp.Width,bmp.Height);
bmpData=bmp.LockBits(bmpBounds,ImageLockMode.ReadOnly,bmp.PixelFormat);
尝试
{
for(int y=0;y没有尝试此方法,但其思想是使用指针:
unsafe
{
byte* ptrAlpha = ((byte*)bmpData.Scan0.ToPointer()) + 3;
for (int i = bmpData.Width * bmpData.Height; i > 0; --i) // prefix-- should be faster
{
if ( *ptrAlpha < 255 )
return true;
ptrAlpha += 4;
}
}
不安全
{
字节*ptrAlpha=((字节*)bmpData.Scan0.ToPointer())+3;
对于(int i=bmpData.Width*bmpData.Height;i>0;--i)//前缀--应该更快
{
如果(*ptrAlpha<255)
返回true;
ptrAlpha+=4;
}
}
没有尝试此方法,但其想法是使用指针:
unsafe
{
byte* ptrAlpha = ((byte*)bmpData.Scan0.ToPointer()) + 3;
for (int i = bmpData.Width * bmpData.Height; i > 0; --i) // prefix-- should be faster
{
if ( *ptrAlpha < 255 )
return true;
ptrAlpha += 4;
}
}
不安全
{
字节*ptrAlpha=((字节*)bmpData.Scan0.ToPointer())+3;
对于(int i=bmpData.Width*bmpData.Height;i>0;--i)//前缀--应该更快
{
如果(*ptrAlpha<255)
返回true;
ptrAlpha+=4;
}
}
以下是基于您的示例
private static bool IsAlphaBitmap(Bitmap bmp, out BitmapData bmpData)
{
var bmpBounds = new Rectangle(0, 0, bmp.Width, bmp.Height);
bmpData = bmp.LockBits(bmpBounds, ImageLockMode.ReadOnly, bmp.PixelFormat);
try
{
var rowDataLength = bmpData.Width * 4; // for 32ARGB bitmap
var buffer = new byte[rowDataLength];
for (var y = 0; y < bmpData.Height; y++)
{
Marshal.Copy((IntPtr) ((int)bmpData.Scan0 + bmpData.Stride*y), buffer, 0, rowDataLength);
for (int p = 0; p < rowDataLength; p += 4)
{
if (buffer[p] > 0 && buffer[p] < 255)
return true;
}
}
}
finally
{
bmp.UnlockBits(bmpData);
}
return false;
}
private static bool IsAlphaBitmap(位图bmp,out位图数据bmpData)
{
var bmpBounds=新矩形(0,0,bmp.Width,bmp.Height);
bmpData=bmp.LockBits(bmpBounds,ImageLockMode.ReadOnly,bmp.PixelFormat);
尝试
{
var rowDataLength=bmpData.Width*4;//用于32ARGB位图
var buffer=新字节[rowDataLength];
对于(变量y=0;y0&&buffer[p]<255)
返回true;
}
}
}
最后
{
bmp.UnlockBits(bmpData);
}
返回false;
}
以下是基于您的示例
private static bool IsAlphaBitmap(Bitmap bmp, out BitmapData bmpData)
{
var bmpBounds = new Rectangle(0, 0, bmp.Width, bmp.Height);
bmpData = bmp.LockBits(bmpBounds, ImageLockMode.ReadOnly, bmp.PixelFormat);
try
{
var rowDataLength = bmpData.Width * 4; // for 32ARGB bitmap
var buffer = new byte[rowDataLength];
for (var y = 0; y < bmpData.Height; y++)
{
Marshal.Copy((IntPtr) ((int)bmpData.Scan0 + bmpData.Stride*y), buffer, 0, rowDataLength);
for (int p = 0; p < rowDataLength; p += 4)
{
if (buffer[p] > 0 && buffer[p] < 255)
return true;
}
}
}
finally
{
bmp.UnlockBits(bmpData);
}
return false;
}
private static bool IsAlphaBitmap(位图bmp,out位图数据bmpData)
{
var bmpBounds=新矩形(0,0,bmp.Width,bmp.Height);
bmpData=bmp.LockBits(bmpBounds,ImageLockMode.ReadOnly,bmp.PixelFormat);
尝试
{
var rowDataLength=bmpData.Width*4;//用于32ARGB位图
var buffer=新字节[rowDataLength];
对于(变量y=0;y0&&buffer[p]<255)
返回true;
}
}
}
最后
{
bmp.UnlockBits(bmpData);
}
返回false;
}
您找不到比这更好的解决方案,我花了几个小时优化:
public bool IsAlphaBitmap(ref System.Drawing.Imaging.BitmapData BmpData)
{
byte[] Bytes = new byte[BmpData.Height * BmpData.Stride];
Marshal.Copy(BmpData.Scan0, Bytes, 0, Bytes.Length);
for (p = 3; p < Bytes.Length; p += 4) {
if (Bytes[p] != 255) return true;
}
return false;
}
public bool IsAlphaBitmap(参考System.Drawing.Imaging.bitmap数据BmpData)
{
字节[]字节=新字节[BmpData.Height*BmpData.Stride];
Marshal.Copy(BmpData.Scan0,Bytes,0,Bytes.Length);
对于(p=3;p
您找不到比这更好的解决方案,我花了几个小时优化:
public bool IsAlphaBitmap(ref System.Drawing.Imaging.BitmapData BmpData)
{
byte[] Bytes = new byte[BmpData.Height * BmpData.Stride];
Marshal.Copy(BmpData.Scan0, Bytes, 0, Bytes.Length);
for (p = 3; p < Bytes.Length; p += 4) {
if (Bytes[p] != 255) return true;
}
return false;
}
public bool IsAlphaBitmap(参考System.Drawing.Imaging.bitmap数据BmpData)
{
字节[]字节=新字节[BmpData.Height*BmpData.Stride];
Marshal.Copy(BmpData.Scan0,Bytes,0,Bytes.Length);
对于(p=3;p
你试过Image.isalphapixelformatal似乎你的问题在StackOverflow上已经解决了:@Digvijay:IsAlphaPixelFormat对我不起作用,因为我不仅需要在位图有alpha通道的情况下,还需要在位图使用alpha通道的情况下使用它。@Digvijay:你提供的链接也会循环所有像素。我要问的是是否存在e任何其他不循环像素的解决方案。谢谢,您不需要将int32值转换为颜色,所以只需对每个Y进行扫描线,并循环所有Alpha字节(稍微修改vulkanino建议的内容)。你试过Image.IsAlphaPixelFormatAlso看起来你的问题在StackOverflow上已经解决了:@Digvijay:IsAlphaPixelFormat对我不起作用,因为我需要的不仅仅是位图是否有alpha通道,还有位图是否被使用。@Digvijay:你提供的链接也会循环所有像素。我想问的是是否有任何像素另一种解决方案是不循环像素。谢谢你不需要将int32值转换为颜色,所以只需对每个Y进行扫描线,并循环所有Alpha字节(稍微修改vulkanino的建议)。在我的公司不可能编译不安全的,抱歉,所以这个答案对我无效,最好执行ani API调用。在我的公司不可能编译不安全的,抱歉,所以这个答案对我无效,最好执行ani API调用。我不是位图操作专家,但如果BmpDat,这将引发异常a、 Stride属性的值为负值。我尝试了使用16x16的本机hBitmaps和alpha通道的代码,该代码是通过调用IShellItemImageFactory.GetImage()获得的,stride为-64。另一方面,这个解决方案对我来说非常适合:我不是位图操作专家,但如果BmpData.stride属性的值为负值,这将引发异常。我已经使用16x16的本机hBitmaps和alpha通道尝试了该代码,我通过调用IShellItemImageFactory.GetImage()获得了该代码,stride为-64。另一方面,这个解决方案对我来说非常适合: