Go to the FreeLists Home Page Home Signup Help Login
 



Browse shell-coding: This Month's ArchiveMain Archive PageRelated postsPrevious by DateNext by Date

[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.