Re: Gdi+ and XP Icons -- A Solution
bill barry <[email protected]> Wed, 11 May 2005 18:30:22 -0400
| Newsgroups | gmane.comp.windows.shell-shocked.devel |
|---|---|
| Message-ID | <[email protected]> |
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. >=20 > At its most basic level, compositing a pixel with an alpha channel onto a > pixel with an alpha channel works as follows: >=20 > C =3D bB + (1-b)aA >=20 > Where C is the composite color obtained by placing a pixel with color B a= nd > alpha b over a pixel with color A and alpha a. (This equation is valid o= n > the range [0, 1], and is applied to each channel of the color.) >=20 > Working with an icon one has access to B and C, and can chose A and a. T= his > is adequate information to back calculate b. Selecting A and a as 255 an= d > 255 and plugging into the equation results in: >=20 > b =3D (C-1)/(B-1) >=20 > This back calculation is carried out by the extremely rough code at the e= nd. >=20 > The question this leaves me with is the following, why doesn't Gdi+ do th= is > and why couldn't I find this on Google? Is there a better way--why > shouldn't I do this? >=20 > Currently my code to draw an icon onto a Gdiplus::Bitmap is horrendous, b= ut > it works. This seems like an ideal replacement to me. >=20 > Eric >=20 > // CODE ----------------------------------------- > #include <iostream> > #include <windows.h> > #include <math.h> > #include <gdiplus.h> > using namespace std; >=20 > bool GetEncoderClsid(const WCHAR* format, CLSID* pClsid) > { > using namespace Gdiplus; > UINT num =3D 0; // number of image encoders > UINT size =3D 0; // size of the image encoder > array in bytes >=20 > ImageCodecInfo* pImageCodecInfo =3D NULL; >=20 > GetImageEncodersSize(&num, &size); > if(size =3D=3D 0) > return false; // no codecs installed. >=20 > pImageCodecInfo =3D (ImageCodecInfo*)(malloc(size)); > if(pImageCodecInfo =3D=3D NULL) > return false; // out of memory >=20 > GetImageEncoders(num, size, pImageCodecInfo); >=20 > for(UINT j =3D 0; j < num; ++j) > { > if( wcscmp(pImageCodecInfo[j].MimeType, format) =3D=3D 0 = ) > { > *pClsid =3D pImageCodecInfo[j].Clsid; > free(pImageCodecInfo); > return true; // Success > } > } >=20 > free(pImageCodecInfo); > return false; // codec doesn't exist > } >=20 > int main() > { > class UsingGdiplus > { > public: > UsingGdiplus() > { > Gdiplus::GdiplusStartupInput gpsi; > Gdiplus::GdiplusStartup(&token, &gpsi, NULL); > } > ~UsingGdiplus() { Gdiplus::GdiplusShutdown(token); } > private: > ULONG_PTR token; > } ugp; >=20 > HICON ico =3D 0; > if(ExtractIconEx("c:\\windows\\system32\\shell32.dll",3, &ico, 0,= 1) > !=3D 1) > { > cout << "extraction failed" << endl; > exit(0); > } >=20 > BITMAPINFOHEADER bmpInfo32; > bmpInfo32.biSize =3D sizeof(BITMAPINFOHEADER); > bmpInfo32.biWidth =3D 32; > bmpInfo32.biHeight =3D 32; > bmpInfo32.biPlanes =3D 1; > bmpInfo32.biBitCount =3D 24; > bmpInfo32.biCompression =3D BI_RGB; > bmpInfo32.biSizeImage =3D 0; > bmpInfo32.biXPelsPerMeter =3D 0; > bmpInfo32.biYPelsPerMeter =3D 0; > bmpInfo32.biClrUsed =3D 0; > bmpInfo32.biClrImportant =3D 0; >=20 > DWORD* bits; >=20 > HDC dc =3D CreateCompatibleDC(0); > HBITMAP bmp =3D 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 =3D (HBITMAP)SelectObject(dc,bmp); >=20 > HBRUSH brush =3D CreateSolidBrush(RGB(0xff,0xff,0xff)); > DrawIconEx(dc, 0, 0, ico, 0, 0, 0, brush, DI_NORMAL); > DeleteObject(brush); >=20 > Gdiplus::Bitmap gpb(ico); > DestroyIcon(ico); >=20 > for(int i =3D 0; i < 32; ++i) > { > for(int j =3D 0; j < 32; ++j) > { > Gdiplus::Color gpc; > gpb.GetPixel(i,j,&gpc); > COLORREF B =3D gpc.ToCOLORREF(); > COLORREF C =3D GetPixel(dc,i,j); > if(B !=3D C && C !=3D RGB(0xff,0xff,0xff)) > { > double Br =3D (double)(GetRValue(B)-255); > double Bg =3D (double)(GetGValue(B)-255); > double Bb =3D (double)(GetBValue(B)-255); > double Cr =3D (double)(GetRValue(C)-255); > double Cg =3D (double)(GetGValue(C)-255); > double Cb =3D (double)(GetBValue(C)-255); >=20 > int alpha =3D (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 =3D (HBITMAP)SelectObject(dc, hbOld); > DeleteObject(bmp); > DeleteDC(dc); >=20 > CLSID pngClsid; > GetEncoderClsid(L"image/png", &pngClsid); > gpb.Save(L"g:\\fixed.png", &pngClsid); > return 0; > } >=20 > __________________________________________________ > Subscription options and archive: > http://www.freelists.org/list/shell-coding >=20 > __________________________________________________ Subscription options and archive: http://www.freelists.org/list/shell-coding