Conversion of HICON to ARGB Image - Icon2Image()


#1

Here is a function for converting any windows icon to an ARGB Image.
Enjoy. :slight_smile:

Thomas Arlt


Maker of the free google translate client "Transmiti"
http://www.transmiti.org


Image* Icon2Image(HICON hIcon) { BITMAP bm; ICONINFO iconInfo; GetIconInfo(hIcon, &iconInfo); GetObject(iconInfo.hbmColor, sizeof(BITMAP),&bm); int width = bm.bmWidth; int height = bm.bmHeight; int bytesPerScanLine = (width * 3 + 3) & 0xFFFFFFFC; int size = bytesPerScanLine * height; BITMAPINFO infoheader; infoheader.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); infoheader.bmiHeader.biWidth = width; infoheader.bmiHeader.biHeight = height; infoheader.bmiHeader.biPlanes = 1; infoheader.bmiHeader.biBitCount = 24; infoheader.bmiHeader.biCompression = BI_RGB; infoheader.bmiHeader.biSizeImage = size; // allocate Memory for Icon RGB data plus Icon mask plus ARGB buffer for the resulting image MemoryBlock* pMemBlock = new MemoryBlock((size*2+height*width*4)*sizeof(uint8)); uint8* pixelsIconRGB = (uint8*)pMemBlock->getData(); uint8* alphaPixels = (uint8*)(pixelsIconRGB+size); uint32* imagePixels = (uint32*)(alphaPixels+size); HDC hDC = CreateCompatibleDC(NULL); // Get Icon RGB data HBITMAP hBmpOld = (HBITMAP)SelectObject(hDC, (HGDIOBJ)iconInfo.hbmColor); if(!GetDIBits(hDC, iconInfo.hbmColor, 0, height, (LPVOID) pixelsIconRGB, &infoheader, DIB_RGB_COLORS)) return NULL; SelectObject(hDC, hBmpOld); // now get the mask if(!GetDIBits(hDC, iconInfo.hbmMask, 0,height,(LPVOID)alphaPixels, &infoheader, DIB_RGB_COLORS)) return NULL; int x=0; int currentSrcPos=0; int currentDestPos=0; int linePosSrc = 0; int linePosDest = 0; int lsSrc = width*3; int vsDest = height-1; for(int y=0; y<height; y++) { linePosSrc = (vsDest-y)*lsSrc; linePosDest = y*width; for(x=0; x<width; x++) { //pixels from Icon are stored in BGR vertical and horizontal flipped order currentDestPos = linePosDest+x; currentSrcPos = linePosSrc+x*3; // BGR -> ARGB imagePixels[currentDestPos]=(((uint32)((((pixelsIconRGB[currentSrcPos+2] << 0x10 /*Red*/) | (pixelsIconRGB[currentSrcPos+1] << 8 /*Green*/)) | pixelsIconRGB[currentSrcPos] /*Blue*/) | ((alphaPixels[currentSrcPos]?0:255) << 0x18))) & 0xffffffffL); } } Image *pImage = new Image(Image::ARGB, width, height,true); pImage->setPixelData (0, 0, width, height, (uint8*)imagePixels, width*4); deleteAndNull(pMemBlock) DeleteDC(hDC); return pImage; }


#2

Thanks Thomas!

Just one thing to note though - its return type should be a const Image, not an Image*. Images are designed to be pass-by-value these days.