C#从二进制图像到透明位图

C# get from binary Image to transparent Bitmap

我得到了一个二进制图像(来自 EMGU)A,我想得到一个位图,该位图在 A 为黑色的所有地方都是透明的,在所有地方都是透明的红色,其中 A 是白色的。一开始我想至少让黑色部分不可见,但已经失败了:

我尝试通过以下方式做到这一点:

private Graphics graphics;
private Bitmap bitmap;
private Image<Gray, Byte> mask;

//graphic, bitmap and mask are being initialized in the constructor of the object
public Bitmap getMask()
{
    //...
    graphics.clear(Color.FromArgb(0,0,0,0);
    graphics.DrawImage(mask.ToBitmap(), 0, 0);
    bitmap.makeTransparent(255, 0, 0, 0);

    //...
}

如何处理白色到红色部分? 有没有一种 easier/more 有效的方法可以通过使用 EMGU 来做到这一点?

这是一个快速例程,可以满足您的要求:

    public static Bitmap MakeSpecialTransparent(Bitmap bmp)
    {
        // we expect a 32bpp bitmap!
        var bmpData = bmp.LockBits(
                                new Rectangle(0, 0, bmp.Width, bmp.Height),
                                ImageLockMode.ReadWrite, bmp.PixelFormat);

        long len = bmpData.Height * bmpData.Stride;
        byte[] data = new byte[len];
        Marshal.Copy(bmpData.Scan0, data, 0, data.Length);

        for (int i = 0; i < len; i += 4)
        {
            if (data[i] == 0  && data[i+1] == 0  && data[i+2] == 0  )
            {
                data[i] = 0; data[i + 1] = 0; data[i + 2] = 0; data[i + 3] = 0;
            }
            else
            if (data[i] == 255  && data[i+1] == 255  && data[i+2] == 255  )
            {
                data[i] = 0; data[i + 1] = 0; data[i + 2] = 255; data[i + 3] = 0;
            }

        }
        Marshal.Copy(data, 0, bmpData.Scan0, data.Length);
        bmp.UnlockBits(bmpData);
        return bmp;
    }

请注意,此 a) 期望 Bitmap32bpp 图像的形式出现,并且 b) 没有任何 公差 :如果黑白像素不是 100% 黑白,它们不会改变。

另请注意,我们在这里处理的物理像素是有序的 BGRA,因此 data[i+3] 是 Alpha 通道,data[i+2]Red等..

要增加容忍度,您可能需要研究 !

作为锁定位和一次处理一个像素(公认更快)的替代方法,您还可以使用颜色变换矩阵来实现相同的效果。矩阵方法相当灵活,您的原始图像不必是完美的;如果原始图像有噪点,这种方法仍然有效。

对于您的特定情况(黑色 => 透明,白色 => red/50%),代码如下所示:

using System.Drawing;
using System.Drawimg.Imaging;
...
// Original image to be transformed
var src = Image.FromFile(@"c:\temp\test.png");

// Destination image to receive the transformation
var dest = new Bitmap(src.Width, src.Height, PixelFormat.32bppArgb);

using (var g = Graphics.FromImage(dest))
{
    var attr = new ImageAttributes();
    float[][] matElements = {
        new float[] { 0.0f, 0.0f, 0.0f, 0.5f, 0.0f },
        new float[] { 0.0f, -1.0f, 0.0f, 0.0f, 0.0f },
        new float[] { 0.0f, 0.0f, -1.0f, 0.0f, 0.0f },
        new float[] { 0.0f, 0.0f,  0.0f, 0.0f, 0.0f },
        new float[] { 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }
    };

    attr.SetColorMatrix(new ColorMatrix(matElements), ColorMatrixFlag.Default,
        ColorAdjustType.Bitmap);
    g.DrawImage(src, new Rectangle(0, 0, src.Width, src.Height), 0, 0,
        src.Width, src.Height, GraphicsUnit.Pixel, attr);
}

从上面的颜色矩阵我们得到:

  • 新的红色值 = 1
  • 新绿色值 = 1 - 旧绿色值
  • 新蓝色值 = 1 - 旧蓝色值
  • 新的 alpha 值 = 0.5 * 旧的红色值

新的红色值是从矩阵的第 1 列开始计算的。绿色是从第2列开始计算的,依此类推...