Hello world.

I need to draw a overlay on an image. I am using a single bit image with a pallete for the overlay. In windows XP/Vista, the pixel blending behaves as I would expect, but in Windows 7 it behaves different, even different on different machines, So either there is a bug in windows 7, Or I am doing something wrong.

The overlay, being single bit have a palette with two entries.

for example, the following colors;
* Transparent = 0x00FFFFFF shows as transparant on all my tests.
* Almost transparent = 0x01FFFFFF shows as opaque on my labtop (win7 (32bit)), but correct on my home machine (win7 (64bit)), (actaully all values besided 0 in alpha produces opaque white on my labtop (and coworkers labtop))
* Semi transparant red: 0x80FF0000 shows correct on W7 32bit, but in W7 64 bit it shows a semi transparant gray when used for Pallete.entry[1]

All the above examples shows correct on XP/Vista

I have made a simple example exposing the problem, In the example, an image is loaded from disk and shown, a 1bpp overlay image is then shown on top of this, when the image is clicked, the pixel in the overlay below the mouse will toggle.

My Setup is like this:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
imgFromFile = new Bitmap(Image.FromFile(@"img.png"));
overlay = new Bitmap(100, 100, PixelFormat.Format1bppIndexed);
Click += new EventHandler(DrawImageWithOverlay_Click);
}

My paint is overriden like this, so basically I assume that windows knows how to handle my images.
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
RectangleF dstRect = new RectangleF(0, 0, Width, Height);
RectangleF srcRect = new RectangleF(0, 0, imgFromFile.Width, imgFromFile.Height);
e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;
e.Graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;
e.Graphics.DrawImage(imgFromFile, dstRect, srcRect, GraphicsUnit.Pixel); // ebs alternative

srcRect = new RectangleF(0, 0, overlay.Width, overlay.Height);
e.Graphics.DrawImage(overlay, dstRect, srcRect, GraphicsUnit.Pixel); // ebs alternative
}

I update my pallete, Just as MSDN shows.
public void UpdatePalette(Color fg, Color bg)
{
ColorPalette p = overlay.Palette;
p.Entries[0] = bg;
p.Entries[1] = fg;
overlay.Palette = p;
}

And I acces the invidual pixels like this, cx and cy are local coordinates in the client window.
private void Toggle(int cx, int cy)
{
int y = (int)Math.Round((float)(cy * overlay.Height) / (float)Height);
int x = (int)Math.Round((float)(cx * overlay.Width) / (float)Width);

// Clamp values
y = Math.Max(0, Math.Min(overlay.Height - 1, y));
x = Math.Max(0, Math.Min(overlay.Width - 1, x));

BitmapData bitmapData = overlay.LockBits(new Rectangle(0, 0, overlay.Width, overlay.Height), ImageLockMode.ReadWrite, PixelFormat.Format1bppIndexed);
unsafe
{
byte* origin = (byte*)bitmapData.Scan0;
int idx = y * bitmapData.Stride + (x >> 3); // Divide by 8 to get byte position
byte mask = (byte)(0x80 >> (x & 0x7)); // Remainder is bit offset.

// Toggle bit.
if ((byte)(origin[idx] & mask) != mask) // Check if it is turned on
{
origin[idx] |= mask; // Turn on
}
else
{
origin[idx] &= (byte)(mask ^ 0xff); // Turn of (AND with inverted)
}
}
overlay.UnlockBits(bitmapData);
}

So my question is, Am I doint something wrong? Or is there an error in windows 7 when using 1bpp images for some blend modes?

If you have windows 7, you can download, test and fix my sollution from
http://videometer.com/download/ImageOverlayTesting.zip
Or you can simply grap the binary to see the behavior:
http://videometer.com/download/Image...esting.Bin.zip