Blending problem with 1bpp images in windows7
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 3 of 3

Thread: Blending problem with 1bpp images in windows7

  1. #1
    Join Date
    Dec 2009
    Location
    Denmark
    Posts
    3

    Question 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

  2. #2
    Join Date
    Oct 2008
    Posts
    47

    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

  3. #3
    Join Date
    Dec 2009
    Location
    Denmark
    Posts
    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
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center