Different results for Bitmap.Maketransparent funct

2019-02-21 02:33发布

问题:

My problem is that i want to make an image background transparent. And the following function works fine for me but while testing on a different machine I found out that there are a lot of artifact colors and the transparency is not as clear as it is on my machine and some other machines. I was working with the debug build and the test was done on release build. But even with release build we see different results on different machines.

Image CreateTransparentBackgroundImage(Image image)
        {
            using (Bitmap tempBitmap = new Bitmap(image.Width, image.Height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb))
            {
                var g = Graphics.FromImage(tempBitmap);
                Rectangle rec = new Rectangle(0 ,0,image.Width, image.Height);
                g.DrawImage(image,rec, 0, 0,image.Width,image.Height, GraphicsUnit.Pixel);
                tempBitmap.MakeTransparent(System.Drawing.Color.White);
                g.Dispose();
                return (Image)tempBitmap.Clone();
            }
        }

Any help would be really appreciated.

回答1:

Your problem seems to come from very slightly differing sources with very slight differences in the target color.

MakeTransparent doesn't provide for any tolerance.

Here is a function with the necessary tolerance. It will make every pixel transparent that is closer than delta to the target color. (The distance is the simple sum of the three channels' deltas..)

public static Bitmap MakeTransparent(Bitmap bmp, Color col, int delta)
{
    // 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)
    {
        int dist = Math.Abs(data[i + 0] - col.B);
        dist += Math.Abs(data[i + 1] - col.G);
        dist += Math.Abs(data[i + 2] - col.R);
        if (dist <= delta) data[i + 3] = 0;
    }
    Marshal.Copy(data, 0, bmpData.Scan0, data.Length);
    bmp.UnlockBits(bmpData);
    return bmp;
}

Here are four images: 1) the source you gave and 2) - 3) results of calling the function with deta values of 5, 10 and 50. I have put them on top of a solid red background so you can see the tranparent pixels..: