Re: GdipCreateHBITMAPFromBitmap + PixelFormat32bppARGB
- From: "Michael Phillips, Jr." <mphillips53@xxxxxxxxxxxxxxx>
- Date: Wed, 13 Jul 2005 19:50:57 -0400
1) Since your bitmap has an alpha channel, the background color
that you specified in your test case will be blended with the
transparent areas of your bitmap. If you don't want this to
occur, specify Color.Black as your background and the colors
will not skew. You specified Color.LightGray so your background
blended with the transparent areas will give you a blue tint.
2) Your test case messed up on the bfsize of the BITMAPINFO header.
The bfSize = size of the image ( 500 * 500 * 3 ) + the size of all the
headers.
The size of the BITMAPINFOHEADER + size of the color table
= 40 + 4!
Your total size is 40 + 4 + 14 ( size of BITMAPINFO ) = 58. You have
54. That is why
your bitmap has a green tint!
"Jonathan Gilbert" <logiclrd@xxxxxxxxxxx> wrote in message
news:70DD2430-46C8-4F12-8020-B8B03078AAFA@xxxxxxxxxxxxxxxx
> The GDI+ function GdipCreateHBITMAPFromBitmap seems to be broken. When
> given
> an image with an alpha channel, it produces an HBITMAP with its colours
> oddly
> skewed. Only translucent pixels are skewed. This is evident, for instance,
> when adding 32-bit RGBA System.Drawing.Bitmap objects to
> System.Windows.Forms.ImageList controls in .NET. The
> ControlPaint.CreateHBitmapColorMask function uses Bitmap.GetHBitmap which
> calls the underlying GdipCreateHBITMAPFromBitmap function.
>
> To test that it was in fact GdipCreateHBITMAPFromBitmap producing the blue
> color skew clearly visible when ImageList is used with images with
> translucency, I made a simple test case. It can be downloaded at:
>
> http://israel.logiclrd.cx/GDIPlusBug.zip
>
> The odd thing is, my test case produces images with a green tint instead
> of
> blue. In both the case of ImageList and of my C++ test case which directly
> calls into GDI+, the "background" parameter passed in is achromatic (all 3
> channels have the same intensity -- gray), so I don't know where the
> colour
> is coming from.
>
> The only thing I can conclude based on the symptoms is that
> GdipCreateHBITMAPFromBitmap is assuming that HBITMAPs can't properly
> handle
> 32-bit data and perhaps is trying to convert the data to an alpha-free
> form.
> However, using a freeware DLL hooking library (madCHook), I was able to
> attach my own implementation of GdipCreateHBITMAPFromBitmap:
>
> GpStatus WINGDIPAPI
> FixedGdipCreateHBITMAPFromBitmap(GpBitmap* bitmap,
> HBITMAP* hbmReturn,
> ARGB background)
> {
> GpStatus status;
>
> UINT uWidth, uHeight;
>
> status = GdipGetImageWidth(bitmap, &uWidth);
>
> if (status != Ok)
> return status;
>
> status = GdipGetImageHeight(bitmap, &uHeight);
>
> if (status != Ok)
> return status;
>
> GpRect rect;
>
> rect.X = 0;
> rect.Y = 0;
> rect.Width = uWidth;
> rect.Height = uHeight;
>
> PixelFormat format;
>
> status = GdipGetImagePixelFormat(bitmap, &format);
>
> if (status != Ok)
> return status;
>
> int bits_per_pixel;
>
> switch (format)
> {
> case PixelFormat1bppIndexed: bits_per_pixel = 1; break;
> case PixelFormat4bppIndexed: bits_per_pixel = 4; break;
> case PixelFormat8bppIndexed: bits_per_pixel = 8; break;
> case PixelFormat16bppARGB1555:
> case PixelFormat16bppGrayScale:
> case PixelFormat16bppRGB555:
> case PixelFormat16bppRGB565: bits_per_pixel = 16; break;
> case PixelFormat24bppRGB: bits_per_pixel = 24; break;
> case PixelFormat32bppARGB:
> case PixelFormat32bppPARGB:
> case PixelFormat32bppRGB: bits_per_pixel = 32; break;
> case PixelFormat48bppRGB: bits_per_pixel = 48; break;
> case PixelFormat64bppARGB:
> case PixelFormat64bppPARGB: bits_per_pixel = 64; break;
> default:
> return InvalidParameter;
> }
>
> BitmapData data;
>
> status = GdipBitmapLockBits(bitmap, &rect, ImageLockModeRead, format,
> &data);
>
> if (status != Ok)
> return status;
>
> HBITMAP ret = CreateBitmap(uWidth, uHeight, 1, bits_per_pixel,
> data.Scan0);
>
> status = GdipBitmapUnlockBits(bitmap, &data);
>
> if (ret == NULL)
> return Win32Error;
>
> if (status != Ok)
> {
> DeleteObject(ret);
> return status;
> }
>
> *hbmReturn = ret;
> return Ok;
> }
>
> As you can see, it simply dumps the bits it gets from locking the GDI+
> Bitmap object into the GDI CreateBitmap function. In my limited testing,
> it
> worked fine, and it eliminated the ImageList problem when used within a
> .NET
> context :-)
>
> Any chance of getting this GDI+ bug fixed, perhaps through a Windows
> Update
> patch?
>
.
- Follow-Ups:
- Re: GdipCreateHBITMAPFromBitmap + PixelFormat32bppARGB
- From: Jonathan Gilbert
- Re: GdipCreateHBITMAPFromBitmap + PixelFormat32bppARGB
- Prev by Date: Re: *insert curse here*
- Next by Date: Which form event to use?
- Previous by thread: gdi+ book?
- Next by thread: Re: GdipCreateHBITMAPFromBitmap + PixelFormat32bppARGB
- Index(es):
Relevant Pages
|