简体   繁体   中英

C# get from binary Image to transparent Bitmap

I got a binary Image(from EMGU) A and I want to get out a bitmap that is transparent everywhere where A is black and a transparent red everywhere, where A is white. For the beginning I wanted to at least make the black part invisible, which already failed:

I tried to do so by the following:

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

    //...
}

how do I do it with the white to red - part? is there a easier/more efficient way to do it maybe by using EMGU?

Here is a fast routine that should do what you asked for:

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

Note that this a) expects the Bitmap to come as 32bpp images and b) does not have any tolerance : If the black & white pixels are not 100% black & white they will not be changed.

Also note that the physical pixels we address here, are ordered BGRA , so data[i+3 ] is the Alpha channel, data[i+2] is Red etc..

To add tolerance you may want to study the linked post !

As an alternative to locking the bits and manipulating pixels one at a time (which is admittedly faster), you could also use a color transformation matrix to achieve the same affect. The matrix approach is fairly flexible, and your original image doesn't have to be perfect; this approach still works if the original image is noisy.

For your specific case (black => transparent, white => red/50%) the code would look like this:

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

From the color matrix above we get:

  • New red value = 1
  • New green value = 1 - old green value
  • New blue value = 1 - old blue value
  • New alpha value = 0.5 * old red value

The new red value is calculated from the 1st column in the matrix. Green is calculated from the 2nd column, etc...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM