
|
[shell-coding] Gdi+ and XP Icons -- A Solution
- From: Hollow <hollow1@xxxxxxxxxxxxx>
- To: shell-coding@xxxxxxxxxxxxx
- Date: Sun, 08 May 2005 22:30:47 -0400
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
Other related posts:[shell-coding] Gdi+ and XP Icons -- A Solution [shell-coding] Re: Gdi+ and XP Icons -- A Solution [shell-coding] Re: Gdi+ and XP Icons -- A Solution [shell-coding] Re: Gdi+ and XP Icons -- A Solution
|

|

|
[ Home |
Signup |
Help |
Login |
Archives |
Lists
]
All trademarks and copyrights within the FreeLists archives are owned
by their respective owners. Everything else ©2008 Avenir Technologies, LLC.
|

|
|