views:

77

answers:

5

I want to replace all pixels in a rectangular region of a Bitmap with 'transparent white' - i.e., a=0, b=255, r=255, g=255.

FillRectangle doesnt do this - given a transparent brush, the existing pixels are unchanged.

Do I need to use SetPixel individually for each pixel in the rectangle?

+1  A: 

FillRectangle doesnt do this - given a transparent brush, the existing pixels are unchanged.

Makes sense, since you are drawing with 0% opacity. :)

A fast solution for a Control would be a color key. You can set the key color of the control to a specific color (i.e. magenta); all pixels that are of this color would then be rendered transparent. (If the control supports it, of course.)

That, or bitmap.MakeTransparent(color) for general purposes. The problem is, again, that the color specified would be transparent, so you'd have to choose a color that doesn't exist in the image. (There's another example here: http://msdn.microsoft.com/en-us/library/ms172507%28v=VS.80%29.aspx)

Edit: In the end, the LockBits() approach mentioned in the other comments could be what you seek. Once you understand how the width and stride values interact, it's easy to manipulate the image at the lowest possible level. Here's a general example: http://www.bobpowell.net/lockingbits.htm Just make sure the image supports transparency (see PixelFormat), then lock the image with an appropriate mode (i.e. PixelFormat.Format32bppArgb), loop over every pixel, read for bytes, write your new color, etc.

Markus
Yes, it totally makes sense :) I was just sayin. Other than that, I dont think your answer is relevant - I am working with a Bitmap, not a control. And although I could paint the rectangle a particular colour (and hope that that colour isnt present anywhere else in the image) and then make it transparent, can I specify 'transparent white'? I dont think so.
mackenir
yourBitmap.MakeTransparent(Color.White) should do that.The downside is that everything white is transparent then, that's true. A problem is that not every image format supports transparency, so it probably also depends on how your image object is created. Have a look at the PixelFormat enumeration and member.And then, of course, the approach to lock the bitmap to work in the "unsafe" pointer dimension. What Pete said. :)
Markus
+2  A: 

If you use the composite painting methods, then the alpha will be used to blend the colour, so nothing will happen.

If you want to set the bitmap, either create it from data with the background you want, or set the background using LockBits to manipulate the data en-masse.

You also might be able to do in using a bitblt method with the appropriate flags, but I don't know how to translate that to managed code.

Pete Kirkham
A: 

This little hack should do the trick:

Graphics g = Graphics.FromImage(myBitmap);
g.SetClip(new RectangleF(10, 10, 20, 20));
g.Clear(Color.Transparent);
g.RestoreClip();
g.Dispose();
deltreme
Nope. That sets the pixels to "transparent black": 0,0,0,0, not "transparent white": 0,255,255,255.
Guffa
You could change it to `g.Clear(Color.FromArgb(0, 255, 255, 255));` Although Hans Passant's answer is probably better
deltreme
+1  A: 

I believe that you need to use SetPixel (or equivalent method of setting the color values directly) to get the pixels to be "transparent white".

You can use the Graphics.Clear method to set the color or pixels, but you can't use it to set them to both transparent and a color. I tried this to set the pixels in a part of a bitmap:

using (Graphics g = Graphics.FromImage(theBitmap)) {
  g.Clip = new Region(new Rectangle(10, 10, 80, 80));
  g.Clear(Color.FromArgb(0, Color.White));
}

The pixels in the region end up as "transparent black": 0,0,0,0. Even drawing a solid white rectangle before clearing doesn't help. When the alpha is zero in a color, the other color components are also zero.

Using an almost transparent alpha like 1 works fine, the pixels end up as "almost transparent white": 1,255,255,255.

Guffa
+2  A: 

You'll have to set the Graphics.CompositingMode property. For example:

    protected override void OnPaint(PaintEventArgs e) {
        var img = Properties.Resources.Chrysanthemum;
        e.Graphics.DrawImage(img, 0, 0);
        e.Graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
        using (var br = new SolidBrush(Color.FromArgb(0, 255, 255, 255))) {
            e.Graphics.FillRectangle(br, new Rectangle(50, 50, 100, 100));
        }
    }

The actual color you use doesn't matter, you'll get a black rectangle with an alpha of 0.

Hans Passant
It's not *that* uncommon to use colour channels for data, say for a map of terrain in a game where water, roads, rocks, snow are ARGB. So you do sometimes want to be able to create bitmaps with zero alpha and non-zero RGB values.
Pete Kirkham
BTW the color in my case is relevant because of later processing that 'mixes' transparent areas colors with other areas colors.
mackenir