conversion of HICON to ARGB Image - Icon2Image()

2 posts / 0 new
Last post
Thomas Arlt
Offline
Last seen: 3 years 7 months ago
Joined: 7 Oct 2010 - 13:25
conversion of HICON to ARGB Image - Icon2Image()

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

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;
}

Edited by: Thomas Arlt on 14 Mar 2011 - 20:01
jules
Online
Last seen: 3 min 34 sec ago
Joined: 29 Apr 2013 - 18:37
Re: conversion of HICON to ARGB Image - Icon2Image()

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.