如何检测位图是否在.NET中具有Alpha通道

时间:2012-02-15 10:29:15

标签: 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.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;
}
  1. 这是继续进行还是有最佳解决方案?
  2. 这个解决方案对于非常大的文件是否足够快?
  3. 非常感谢

3 个答案:

答案 0 :(得分:2)

你找不到比这更好的解决方案,我花了几个小时来优化:

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;
}

答案 1 :(得分:1)

没试过这个,但想法是使用指针:

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;
   }
}

答案 2 :(得分:1)

以下是基于你的例子。

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;
}