Re: Gdi+ and XP Icons -- A Solution
Hollow <[email protected]> Fri, 13 May 2005 02:53:17 -0400
| Newsgroups | gmane.comp.windows.shell-shocked.devel |
|---|---|
| Message-ID | <000001c55788$711f69a0$790aa8c0@hollow> |
Never mind. It seems that DrawIconEx actually places the alpha channel information in the unused channel of the bitmap if you use a 32-bit bitmap. So you don't have to calculate this, its given to you. So adding it to the Gdi+ bitmap becomes trivial. Still doesn't explain why I couldn't find any reference to this online or why Gdi+ doesn't pick it up. Eric -----Original Message----- From: [email protected] [mailto:[email protected]] On Behalf Of Hollow Sent: Wednesday, May 11, 2005 7:20 PM To: [email protected] Subject: [shell-coding] Re: Gdi+ and XP Icons -- A Solution I chose A and a. I know B and C from the icon (B) and the icon blended over A-a (C). I want b (the alpha channel of the icon) so that I can use the icon like any other bitmap in Gdi+. At first glance it looks like the Bitmap constructor that takes an HICON should work for this, but it doesn't bring in the alpha channel. So this is a way to get it. Eric -----Original Message----- From: [email protected] [mailto:[email protected]] On Behalf Of bill barry Sent: Wednesday, May 11, 2005 6:30 PM To: [email protected] Subject: [shell-coding] Re: Gdi+ and XP Icons -- A Solution why are you trying to get b? I thought you chose a, A, b, and B. On 5/8/05, Hollow <[email protected]> wrote: > I've been working with Gdi+ recently and is poor handling of XP icons has > been by far the most irksome aspect of it. I got to thinking about this > today, and came up with the following idea. > > At its most basic level, compositing a pixel with an alpha channel onto a > pixel with an alpha channel works as follows: > > C = bB + (1-b)aA > > Where C is the composite color obtained by placing a pixel with color B and > alpha b over a pixel with color A and alpha a. (This equation is valid on > the range [0, 1], and is applied to each channel of the color.) > > Working with an icon one has access to B and C, and can chose A and a. This > is adequate information to back calculate b. Selecting A and a as 255 and > 255 and plugging into the equation results in: > > b = (C-1)/(B-1) > > This back calculation is carried out by the extremely rough code at the end. > > The question this leaves me with is the following, why doesn't Gdi+ do this > and why couldn't I find this on Google? Is there a better way--why > shouldn't I do this? > > Currently my code to draw an icon onto a Gdiplus::Bitmap is horrendous, but > it works. This seems like an ideal replacement to me. > > Eric > > // CODE ----------------------------------------- > #include <iostream> > #include <windows.h> > #include <math.h> > #include <gdiplus.h> > using namespace std; > > bool GetEncoderClsid(const WCHAR* format, CLSID* pClsid) > { > using namespace Gdiplus; > UINT num = 0; // number of image encoders > UINT size = 0; // size of the image encoder > array in bytes > > ImageCodecInfo* pImageCodecInfo = NULL; > > GetImageEncodersSize(&num, &size); > if(size == 0) > return false; // no codecs installed. > > pImageCodecInfo = (ImageCodecInfo*)(malloc(size)); > if(pImageCodecInfo == NULL) > return false; // out of memory > > GetImageEncoders(num, size, pImageCodecInfo); > > for(UINT j = 0; j < num; ++j) > { > if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 ) > { > *pClsid = pImageCodecInfo[j].Clsid; > free(pImageCodecInfo); > return true; // Success > } > } > > free(pImageCodecInfo); > return false; // codec doesn't exist > } > > int main() > { > class UsingGdiplus > { > public: > UsingGdiplus() > { > Gdiplus::GdiplusStartupInput gpsi; > Gdiplus::GdiplusStartup(&token, &gpsi, NULL); > } > ~UsingGdiplus() { Gdiplus::GdiplusShutdown(token); } > private: > ULONG_PTR token; > } ugp; > > HICON ico = 0; > if(ExtractIconEx("c:\\windows\\system32\\shell32.dll",3, &ico, 0, 1) > != 1) > { > cout << "extraction failed" << endl; > exit(0); > } > > BITMAPINFOHEADER bmpInfo32; > bmpInfo32.biSize = sizeof(BITMAPINFOHEADER); > bmpInfo32.biWidth = 32; > bmpInfo32.biHeight = 32; > bmpInfo32.biPlanes = 1; > bmpInfo32.biBitCount = 24; > bmpInfo32.biCompression = BI_RGB; > bmpInfo32.biSizeImage = 0; > bmpInfo32.biXPelsPerMeter = 0; > bmpInfo32.biYPelsPerMeter = 0; > bmpInfo32.biClrUsed = 0; > bmpInfo32.biClrImportant = 0; > > DWORD* bits; > > HDC dc = CreateCompatibleDC(0); > HBITMAP bmp = CreateDIBSection(dc, (BITMAPINFO*)&bmpInfo32, > DIB_RGB_COLORS, (VOID**)&bits, NULL, 0); > if(!bmp) > { > cout << "creating dibsection failed" << endl; > DeleteDC(dc); > DestroyIcon(ico); > exit(0); > } > HBITMAP hbOld = (HBITMAP)SelectObject(dc,bmp); > > HBRUSH brush = CreateSolidBrush(RGB(0xff,0xff,0xff)); > DrawIconEx(dc, 0, 0, ico, 0, 0, 0, brush, DI_NORMAL); > DeleteObject(brush); > > Gdiplus::Bitmap gpb(ico); > DestroyIcon(ico); > > for(int i = 0; i < 32; ++i) > { > for(int j = 0; j < 32; ++j) > { > Gdiplus::Color gpc; > gpb.GetPixel(i,j,&gpc); > COLORREF B = gpc.ToCOLORREF(); > COLORREF C = GetPixel(dc,i,j); > if(B != C && C != RGB(0xff,0xff,0xff)) > { > double Br = (double)(GetRValue(B)-255); > double Bg = (double)(GetGValue(B)-255); > double Bb = (double)(GetBValue(B)-255); > double Cr = (double)(GetRValue(C)-255); > double Cg = (double)(GetGValue(C)-255); > double Cb = (double)(GetBValue(C)-255); > > int alpha = (int)((floor(255*Cr/Br) + > floor(255*Cg/Bg) + floor(255*Cb/Bb))/3.0); > gpb.SetPixel(i,j, Gdiplus::Color(alpha, > gpc.GetR(), gpc.GetG(), gpc.GetB())); > } > } > } > bmp = (HBITMAP)SelectObject(dc, hbOld); > DeleteObject(bmp); > DeleteDC(dc); > > CLSID pngClsid; > GetEncoderClsid(L"image/png", &pngClsid); > gpb.Save(L"g:\\fixed.png", &pngClsid); > return 0; > } > > __________________________________________________ > Subscription options and archive: > http://www.freelists.org/list/shell-coding > > __________________________________________________ Subscription options and archive: http://www.freelists.org/list/shell-coding __________________________________________________ Subscription options and archive: http://www.freelists.org/list/shell-coding __________________________________________________ Subscription options and archive: http://www.freelists.org/list/shell-coding