views:

112

answers:

5

Hello,

I have two 8bpp bitmaps. I want to do a bitwise AND of one to the other, but I don't see any obvious way to do this in .NET. Is it possible to do this without using non-.NET methods? Thanks!

+1  A: 

If performance is not important, use Bitmap.GetPixel and Bitmap.SetPixel

Pavel Alexeev
Unfortunately, these are very slow in .NET.
+3  A: 

I think you're looking for Bitmap.LockBits.

Matthew Flaschen
I may have to resort to this if I can't find a library method that does it. Unfortunately looping in C# probably will execute slower.
A: 

Similair question

Fredou
+3  A: 

You could try converting the Bitmap to a Byte array and then loop through the bytes anding them together

Edit : Ran a Time Test on the loop idea:

Example Code:

DateTime StartTime = DateTime.Now;
Image Image1 = Image.FromFile("C:\\Image1.bmp");
Image Image2 = Image.FromFile("C:\\Image2.bmp");
DateTime AfterLoad = DateTime.Now;
MemoryStream S = new MemoryStream();
Image1.Save(S, System.Drawing.Imaging.ImageFormat.Bmp);
Byte[] I1 = S.ToArray();
Image2.Save(S, System.Drawing.Imaging.ImageFormat.Bmp);
Byte[] I2 = S.ToArray();
DateTime AfterConvert = DateTime.Now;
DateTime AfterLoop = DateTime.Now;
if (I1.Length == I2.Length)
{
    Byte[] I3 = new Byte[I1.Length];
    for (int i = 0; i < I1.Length; i++)
        I3[i] = Convert.ToByte(I1[i] & I2[i]);
    AfterLoop = DateTime.Now;
    FileStream F = new FileStream("C:\\Users\\jamesb\\desktop\\Image3.bmp", FileMode.OpenOrCreate);
    F.Write(I3, 0, I3.Length);
    F.Close();
}
DateTime Finished = DateTime.Now;
MessageBox.Show("Load Time: " + (AfterLoad - StartTime).TotalMilliseconds.ToString() + " ms" + "\r\n" +
                "Convert Time: " + (AfterConvert - AfterLoad).TotalMilliseconds.ToString() + " ms"+ "\r\n" +
                "Loop Time: " + (AfterLoop - AfterConvert).TotalMilliseconds.ToString() + " ms"+ "\r\n" +
                "Save Time: " + (Finished - AfterLoop).TotalMilliseconds.ToString() + " ms"+ "\r\n" +
                "Total Time: " + (Finished - StartTime).TotalMilliseconds.ToString() + " ms");

with the following results :

Load Time: 30.003 ms
Convert Time: 94.0094 ms
Loop Time: 128.0128 ms
Save Time: 177.0177 ms
Total Time: 429.0429 ms

The images "Image1" and "Image2" were 4000 x 2250 (From a digital camera converted to 8 bit bmp)

JamesB
An interesting approach. Unfortunately looping is slow in C#.
+1  A: 

You can use the 'BitBlt' function, in which you can AND the source and destination (SRCAND), the pinvoke signature is here.

Here is an article on Codeproject that uses a BitBlt wrapper here.

Hope this helps, Best regards, Tom.

tommieb75
He asked to do it without using non-.NET methods.
Matthew Flaschen
@Matthew...unfortunately...there is a reliance on pinvoke to do some things that .NET cannot do....
tommieb75
There is no reason .NET can't do this.
Matthew Flaschen
@Matthew..is there a bitblt function in .NET?
tommieb75
I was hoping for a .NET mechanism. But using BitBlt would probably be faster than anything I could do purely in .NET. I may end up using this. Thanks.
The fact that there is no BitBit function in the .NET library does not mean the task can't be performed in .NET.
Matthew Flaschen
I tried it but the only raster ops that worked were WHITENESS and BLACKNESS. It might have been because one of the bitmaps I was using was an Aurigma bitmap (which handles the CMYK color space), which may not be 100% compatible with .NET bitmaps.
alankdkd: check out this conversion http://stackoverflow.com/questions/1259711/is-it-possible-to-draw-a-shape-with-a-cmyk-colour-fill-in-net from cymk to rgb...
tommieb75