0

I need to remove the black background color of a bitmap in C# VS2013.

It is just like that I draw some points on a canvas. The canvas is black and I just need to change the canvas to be transparent meanwhile keeping colorful points on it without any changes.

I got the solution at: How to remove white background color from Bitmap

Bitmap capcha = new Bitmap(@"C:/image.png");
capcha.MakeTransparent(Color.Black);

But, the background still have a gray color like a fog covering the points on the image.

How to remove it ?

UPDATE I used the code:

ImageAttribute imageAttribute = new ImageAttribute();
imageAttribute.SetGamma(0.5f, ColorAdjustType.Bitmap);
gr.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height),
            0, 0, img.Width, img.Height,    GraphicsUnit.Pixel, imageAttribute );

I got same thing.

More update of C# code to draw an image :

 System.Drawing.Bitmap canvasImage = new System.Drawing.Bitmap(xSize, ySize, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
 canvasImage.MakeTransparent(Color.Black);
 Graphics g = Graphics.FromImage(canvasImage);
 System.Drawing.Bitmap tempImage = myDrawImageFunction(myPoints);
 g.Clear(Color.Transparent);  // this only give me an empty image without any points on it. But, if I uncomment it, I will have an  image with black background.
 // my understanding about g.DrawImage() is to draw points on tempImage
 //  after clearing the background. But, the image still have a foggy covering on the image.
 g.DrawImage(tempImage, new System.Drawing.PointF(x_position, y_position));

I want to have a transparent background for "tempImage" before any points are drawn on it.

The example image has a back ground that needs to be removed but the colorful points on the image need to be kept without any changes.

image with the black background that needs to be removed but the colorful points need to be kept.

Community
  • 1
  • 1
user3601704
  • 753
  • 1
  • 14
  • 46
  • You could try to increase the __contrast__ and the __gamma__ before applying `MakeTransparent`. Google for this plus `ColorMatrix` and `c#`! - Or loop over the pixels or the channels and do it one by one using a theshold to decide.. – TaW Oct 17 '15 at 17:07
  • please see the update. – user3601704 Oct 17 '15 at 17:34
  • You need to play with the numbers a little (0.5f will not do a lot I guess), but depending on the images you may well need to do it on a pixel by pixel basis. See [Here](http://stackoverflow.com/questions/25976620/how-can-i-color-pixels-that-are-not-black-in-bitmap-in-yellow-using-lockbits/25977692?s=1|3.3089#25977692) for a basic example! For more speed look into `LockBits` – TaW Oct 17 '15 at 17:48
  • 1
    JPEG is a compressed lossy image format, its background is not going to be a solid black. The "fog" are the pixels that were *almost* black. You'll need to do some image processing to threshold the pixels, that isn't ever going to be perfect. Or just not use JPEG because it is the wrong image format, use PNG instead. – Hans Passant Oct 17 '15 at 18:02

1 Answers1

1

This will do the job:

public Color MakeTransparent(Color c, int threshold)
{   // calculate the weighed brightness:
    byte val = (byte)((c.R * 0.299f + c.G * 0.587f + c.B * 0.114f));
    return val < threshold ?  Color.FromArgb(0, c.R, c.G, c.B) : c;
}

You could use it in a double loop over the pixels, but for fast results you should call it from the code in this post (second part!) which uses LockBits.

Change this

ModifyHue hueChanger = new ModifyHue(MaxChannel);

to the new function:

ModifyHue hueChanger = new ModifyHue(MakeTransparent);

and call it with a suitable threshold, maybe 10 or 20..:

c = hueChanger(c, 20); 

The function skips the call to the system's MakeTransparent function and directly sets the alpha channel of each pixel to 0.

If you want to create a uniform color instead of a transparent one it should be easy to modify (e.g. by returning Color.FromArgb(255, 0, 0, 0) for solid black)

Do note that, while the code in the linked post takes both 24 and 32 bbp formats you should definitely not save as JPG, as this will re-introduce artifacts and the result will not work well with e.g. a TransparencyKey color..

Instead do save it as PNG, as Hans suggests!

I hope you can modify the button code to a function :-)

Community
  • 1
  • 1
TaW
  • 53,122
  • 8
  • 69
  • 111
  • thanks for your answer. I do save it as PNG. But, I only need to remove the foggy background not the points on the image. I do not want to change the color of the points. It is just like that I draw some points on a canvas. The canvas is black and I just need to change the canvas to be transparent meanwhile keeping colorful points on it. – user3601704 Oct 17 '15 at 20:50
  • I can't tell you what threshold will be best or what would be the best way to modify the code for your images, as I don't know them. The threshold will only 'remove' those pixels that are 'dark enough'. You need to test to find the best value for it! - If you mean that there are black/dark parts you need to keep, maybe you need to do a floodfill afterwards, but without seeing any example it is impossible to tell.. – TaW Oct 17 '15 at 21:01
  • I prefer a method that can make the canvas transparent before any points are drawn in it. This avoids that I need to loop over each pixel on the result image that has thousands points drawn on it. – user3601704 Oct 17 '15 at 21:18
  • If all you want is a blank slate why not simply clear it before drawing??? But in your question you clearly load an existing image, don't you?? So what images are we talking about? If there are colored pixels you want to keep you need to change all other ones. do try the lockbit method , it is very fast! – TaW Oct 17 '15 at 21:34
  • I have added more update. The image points were drawn by me. I have cleared the image before I draw points on it but it gave me an empty image. – user3601704 Oct 17 '15 at 23:15
  • Of course, you are drawing tempimage onto itself! But even when you change the last line to g.DrawImage(canvasImage,..) all you get is canvasImage again as that is what you draw onto tempimage! (Btw: Have a look into [compositingmode](https://msdn.microsoft.com/de-de/library/system.drawing.graphics.compositingmode(v=vs.110).aspx) - g.Clear(Color.Transparent); gives you an emtpy, transparent image. But you are not drawing points onto it, you are copying whole images.. – TaW Oct 18 '15 at 00:43
  • My understanding about g.DrawImage() is to draw points on tempImage after clearing the background. But, the image still have a foggy covering on the image. – user3601704 Oct 18 '15 at 02:23
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/92626/discussion-between-taw-and-user3750163). – TaW Oct 18 '15 at 06:54