-
December 29th, 2009, 09:28 AM
#1
Blending problem with 1bpp images in windows7
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
-
December 29th, 2009, 05:26 PM
#2
Re: Blending problem with 1bpp images in windows7
I would check out these tutorials see what distinctions you may fnd between the OS's ...
http://www.msdev.com/Directory/Searc...ows+7+graphics
Hope these help!
Larry D
MSAE
-
December 29th, 2009, 06:56 PM
#3
Re: Blending problem with 1bpp images in windows7
Hi Larry, Thanks for the reply.
I looked at the headlines, and I do not think they are relevant.
I did instead look at the documentation on MSDN.
I construct the image using, using the constructor where i specify the pixelformat, format = Format1bppIndexed
MSDN "Specifies that the pixel format is 1 bit per pixel and that it uses indexed color. The color table therefore has two colors in it."
Compatibility includes Window 7
Same goes for lockbits and unlockbits, Compatibility includes win7
There really shouldn't be more to it
Only issue here is that I am accessing the data using a byte*, this is for speed. I just tried the MSDN example way which does not require unsafe code
Code:
#region Safe alternative
// Get the address of the first line.
IntPtr ptr = bitmapData.Scan0;
// Declare an array to hold the bytes of the bitmap.
int bytes = bitmapData.Stride * bitmapData.Height;
byte[] origin = new byte[bytes];
// Copy the RGB values into the array.
System.Runtime.InteropServices.Marshal.Copy(ptr, origin, 0, bytes);
// Toggle bit.
int idx = y * bitmapData.Stride + (x >> 3); // Divide by 8 to get byte position
byte mask = (byte)(0x80 >> (x & 0x7)); // Remainder is bit offset.
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)
}
#endregion Safe alternative
The result is the same, what am I missing?
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|