4

I'm working on a Machine Learning problem at college and my first job is to convert images into black and white.

The problem is that my image has transparency, and I don't know how to remove it.

What I am trying:

public static Bitmap RemoveTransparency (Bitmap src)
{            
    Bitmap   target = new Bitmap (src.Size.Width, src.Size.Height);
    Graphics g      = Graphics.FromImage (target);

    g.Clear (Color.White);            
    g.DrawImage (src, 0, 0);

    return target;
}

An example of an input image:

My captcha image

An example of output image after "RemoveTransparency" call:

Output image

Does anyone know what's going on? Seems like background an the letters have the same color... and my my background is black if I'm coloring to white?

Thank you!

briba
  • 2,857
  • 2
  • 31
  • 59
  • What is the source of your `src` image? In what way does it "have transparency"? If it's actually e.g. a 32bpp bitmap where the transparent pixels have alpha values of 0, then the code you posted would work. So that it doesn't suggests you are leaving out some critical piece of information with respect to the original image. You should post a complete code example, including a self-contained initialization of a source bitmap. See http://stackoverflow.com/help/mcve – Peter Duniho Dec 01 '14 at 17:59
  • For the record: I downloaded the exact image included in the question, ran the code in the question, and saved the result to a new .png file. And it works fine, just as expected. The answer you got might be a work-around to offset some other bug you have in your code, but it's not really the right way to fix this if you expected the original bitmap as used to have transparency as found in the bitmap you've got in your question. – Peter Duniho Dec 01 '14 at 18:21
  • @PeterDuniho You are spreading misinformation here. I also downloaded the image. It has transparent black pixels. The default `CompositingMode` for the `Graphics` object is `SourceCopy`. "... and saved the result to a new .png file." Your PNG file has transparency, so your output just has transparent black pixels as well. Try saving to a JPG with no alpha channel. You will find your image is all black, because alpha blending was not used when drawing the transparent black pixels on top of the white background. – Timothy Shields Dec 01 '14 at 18:43
  • @PeterDuniho See here: http://en.wikipedia.org/wiki/Alpha_compositing – Timothy Shields Dec 01 '14 at 18:44
  • @TimothyShields: I'm "spreading misinformation" by stating _exactly what I did_? In my test, the saved bitmap has no transparent pixels and looks fine (i.e. white background with black lettering and the red line). – Peter Duniho Dec 01 '14 at 18:45

1 Answers1

5

You need to set the CompositingMode of your Graphics object to SourceOver before drawing the other image on top of it.

g.Clear(Color.White);
g.CompositingMode = CompositingMode.SourceOver;
g.DrawImage(src, 0, 0);

The default CompositingMode is SourceCopy, which is taking the transparent black (R=G=B=A=0) pixels in your src image and rendering them as black pixels. SourceOver will do alpha blending, which is what you're looking for.

See here for details: CompositingMode Enumeration

Timothy Shields
  • 75,459
  • 18
  • 120
  • 173
  • Thanks for your help @Timothy, can I continue using Bitmap? Or do I have to use Image? It continues returning black using Bitmap =/ – briba Dec 01 '14 at 17:56
  • @Crasher Using the `Bitmap` class here is fine. I am absolutely certain the problem and fix is what I described above. There must be something else wrong beside the problem you've described here. – Timothy Shields Dec 01 '14 at 17:59
  • @TimothyShields: if the original bitmap used RGB of 0,0,0 to represent transparent pixels, then why are the black numerals in the original bitmap visible? Note that the bitmap he posted in his article has true transparency and would work fine with the code he posted. – Peter Duniho Dec 01 '14 at 18:01
  • Image is a class that can contain either Bitmaps of a few other image formats like WMF or Icons. It is not an alternative to Bitmap at all but a for most uses the same thing, once, as one then always needs to do, one has cast to Bitmap! – TaW Dec 01 '14 at 18:03
  • @PeterDuniho "Why are the black numerals in the original bitmap visible?" Because Stack Overflow uses a white background and your browser does alpha blending (white background + transparent black on top = white). :) There is no such thing as "true transparency": every pixel has (R,G,B,A) and you can vary all of (R,G,B) while fixing A=0. This is why there is "transparent black", "transparent white", "transparent magenta", etc. – Timothy Shields Dec 01 '14 at 18:36
  • @TimothyShields: sorry, I clearly didn't explain my point well. My fault for being too oblique. I'm aware of everything you wrote. But the problem is, this normally works without having to set the `CompositingMode` explicitly; the default is `SourceOver` already. – Peter Duniho Dec 01 '14 at 18:47
  • @PeterDuniho I think it may be that in older versions of .NET the default was different. See version [3.5 documentation](http://msdn.microsoft.com/en-us/library/system.drawing.graphics.compositingmode(v=vs.90).aspx) vs. [4.0 documentation](http://msdn.microsoft.com/en-us/library/system.drawing.graphics.compositingmode(v=vs.100).aspx). You're correct though, `SourceOver` is definitely the default in 4.0+, and maybe it even is in earlier versions. – Timothy Shields Dec 01 '14 at 18:51