Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Solution for DrawImage XP alpha icon bitmap drawing issues.

23 views
Skip to first unread message

dr21702

unread,
Jul 12, 2004, 11:57:54 AM7/12/04
to
I'm posting this to help anyone else out there with this issue that
has cost me a days work to research and figure out.

This will address all issues with alpha loss on Windows XP style icons
(32bppARGP format) with regard to Bitmap.FromHicon and
Graphics.DrawImage.

There appears to be a bug in GDI+ with regard to getting the bitmap
image of any icon which results in an image being use that is not the
correct pixel format. This seems to occur with any GDI+ function that
internally has to a convert an image to a bitmap. The solution below
addresses the issue by using GetIconInfo, creating a bitmap which will
contain the correct bits but wrong format, then copy the bitmap bits
to a new bitmap with the correctly format.

The resulting bitmap will work with DrawImage to the screen or to a
Bitmap Graphics object. I haven't tested this with ImageList, it is
likely that this will solve problems with that as well since adding an
icon to an image list requires the flawed internal conversion to a
bitmap.

Below is the C# code that can be added to a class for a simple static
method to return a good bitmap from an icon. I only performs the
special steps if the icon is 32 bit, otherwise it using Bitmap.HIcon
which appears to work for other format.

public struct ICONINFO
{
public int fIcon;
public int xHotspot;
public int yHotspot;
public IntPtr hbmMask;
public IntPtr hbmColor;
}

public struct BITMAP
{
public int bmType;
public int bmWidth;
public int bmHeight;
public int bmWidthBytes;
public short bmPlanes;
public short bmBitsPixel;
public int bmBits;
}

[DllImport("gdi32")]
public static extern int GetObject(IntPtr hObject, int nCount, out
BITMAP bitmap);

[DllImport("gdi32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr DeleteObject(IntPtr hObject);


public static Bitmap AlphaBitmapFromIcon(Icon icon)
{
// (Overcome Flaw #1: GDI+ Bitmap.FromHICON mangles the alpha so the
.NET Bitmap.FromHicon will not work)

// Call Win32 to get icon info with contains the icon bitmap, return
null if invalid

ICONINFO iconInfo;
if (GetIconInfo(icon.Handle, out iconInfo)==0)
return null;

// Get BITMAP struct from icon bitmap

BITMAP bitmapData;
GetObject(iconInfo.hbmColor, Marshal.SizeOf(typeof(Win32.BITMAP)),
out bitmapData);

// If not a 32bpp then ok to use Bitmap.FromHicon

if (bitmapData.bmBitsPixel!=32)
{
DeleteObject(iconInfo.hbmColor);
DeleteObject(iconInfo.hbmMask);
return Bitmap.FromHicon(icon.Handle);
}

// Create .NET wrapped bitmap from ICONINFO bitmap

Bitmap wrapBitmap=Bitmap.FromHbitmap(iconInfo.hbmColor);

// (Overcome Flaw #2: Bitmap.FromHbitmap creates a bitmap with the
correct bits but wrong pixel format)

// Copy bit form flawed bitmap to new bitmap with correct format

BitmapData bmData=wrapBitmap.LockBits(new Rectangle(0,0,
wrapBitmap.Width, wrapBitmap.Height),
ImageLockMode.ReadOnly, wrapBitmap.PixelFormat);
Bitmap dstBitmap=new Bitmap(bmData.Width, bmData.Height,
bmData.Stride, PixelFormat.Format32bppArgb, bmData.Scan0);
wrapBitmap.UnlockBits(bmData);

// Caller must dispose of bitmaps returned in ICONINFO from
GetIconInfo call

DeleteObject(iconInfo.hbmColor);
DeleteObject(iconInfo.hbmMask);

// Return corrected bitmap

return dstBitmap;

}

Michael Adams

unread,
Jul 25, 2004, 11:47:37 PM7/25/04
to
I've been trying to get .NET to save Truecolor icons I'm extracting from
Shell32.dll: apparently, the Icon.save may be whats rendering the output
so poorly (the Bitmaps are fine). This function hasn't fixed that
situation, but I did add/change two things to make this function work in
my app.

1. GetIconInfo was missing. I modified a variation I found online.

[DllImport("user32")]
public static extern int GetIconInfo(IntPtr hIcon, ref ICONINFO
piconinfo);

2. To avoid creating an Icon that may corrupt the processed image, I
changed the input parameter from an Icon to an IntPtr. You're calling
for an icon, when all you need is its handler: same as the output made
by "ExtractIcon" (shell32.dll function). Rather than create an icon
first, create a handler from a source Bitmap or icon handler.

Changed lines...

a. New function call: public static Bitmap AlphaBitmapFromIcon(IntPtr
iconHandle)

b. Change all the "icon.Handle" to "iconHandle"

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!

dr21702

unread,
Aug 1, 2004, 11:22:59 PM8/1/04
to
I'm not sure exactly what you're trying to do with Icon.Save, my post
was to address issues with making custom controls, in particular those
that use animation where the icons must be rendered to a Graphics
object derived from a bitmap. I wasn't able to figure out if Win32
GetIconInfo is causing the problem or the GDI+ bitmap class. The odd
part of this problem is the icon image gets drawn correctly when
Graphics is to the display, and incorrectly when Graphics is to a
bitmap.


Michael Adams <cwolf...@yahoo.com> wrote in message news:<#85MMNsc...@TK2MSFTNGP10.phx.gbl>...

Michael Adams

unread,
Aug 2, 2004, 3:05:55 AM8/2/04
to
Apparently, .NET has this cute bug where if you Icon.Save() an Icon
greater than 16-color, it saves it as a 16-color icon. You can check out
my icon extractor program here...

http://www.wolfsheep.com/map

(scroll to the bottom; I threw it with the "other" programs)

Anyhow, as you will see, I have your code "borged" in there to try to
avoid the bug, but to no avail. No doubt the Icon-Bitmap bug is related.

0 new messages