Creating+a+PNG+file+from+a+Windows+icon

//by Richard Russell, February 2018//

Both Windows icons and PNG (Portable Network Graphics) files support transparency - an alpha channel if you prefer - so it may be useful to convert the former to the latter. For example Android and Mac OS icons use PNG format, so if you want to convert a Windows icon to be suitable for those operating systems this is what you need. The **PROCpngfromhicon** procedure listed below performs the required conversion; its parameters are the path and filename of the PNG file to be created, a handle to the icon and the width and height of the icon (the routine could have discovered the dimensions itself, but in the program for which it was written they were already known). If you need to resize the icon the **CopyImage** API will do that.

The procedure has a dependency on GDIPlus so you will need to include this code in the initialisation section of your program:

code format="bb4w" INSTALL @lib$ + "GDIPLIB" PROC_gdipinit SYS "GetModuleHandle", "GDIPLUS.DLL" TO gdip% SYS "GetProcAddress", gdip%, "GdipCreateBitmapFromScan0" TO `GdipCreateBitmapFromScan0` SYS "GetProcAddress", gdip%, "GdipSaveImageToFile"      TO `GdipSaveImageToFile` code

and this code should be executed on exit:

code format="bb4w" PROC_gdipexit code

Here is the procedure itself:

code format="bb4w" DEF PROCpngfromhicon(png$, hicon%, w%, h%) LOCAL I%, bitmap%, wide%, ole32%, cfs% LOCAL pixel%, alpha%, bmi{}, ii{}, clsid{} DIM wide% LOCAL MAX_PATH * 2 DIM bmi{Size%, Width%, Height%, Planes{l&,h&}, BitCount{l&,h&}, \ \      Compression%, SizeImage%, XPelsPerMeter%, YPelsPerMeter%, \ \      ClrUsed%, ClrImportant%} DIM ii{fIcon%, xHotspot%, yHotspot%, hbmMask%, hbmColor%} DIM clsid{a%, b%, c%, d%, e%, f%, g%, h%}

SYS "LoadLibrary", "OLE32" TO ole32% SYS "GetProcAddress", ole32%, "CLSIDFromString" TO cfs% SYS "MultiByteToWideChar", 0, 0, "{557CF406-1A04-11D3-9A73-0000F81EF32E}", -1, wide%, MAX_PATH SYS cfs%, wide%, clsid{}

SYS "GetIconInfo", hicon%, ii{}

bmi.Size% = DIM(bmi{}) bmi.Width% = w%     bmi.Height% = -h% bmi.Planes.l& = 1 bmi.BitCount.l& = 32 bmi.Compression% = BI_RGB

DIM pixel%(w% * h% - 1) SYS "GetDIBits", @memhdc%, ii.hbmColor%, 0, h%, ^pixel%(0), bmi{}, DIB_RGB_COLORS FOR I% = 0 TO h%*w% - 1 IF pixel%(I%) AND &FF000000 EXIT FOR NEXT IF I% >= h%*w% THEN DIM alpha%(w% * h% - 1) SYS "GetDIBits", @memhdc%, ii.hbmMask%, 0, h%, ^alpha%(0), bmi{}, DIB_RGB_COLORS FOR I% = 0 TO h%*w% - 1 IF alpha%(I%)=FALSE pixel%(I%) OR= &FF000000 NEXT ENDIF

SYS `GdipCreateBitmapFromScan0`, w%, h%, 4*w%, &26200A, ^pixel%(0), ^bitmap% SYS "MultiByteToWideChar", CP_ACP, 0, png$, -1, wide%, MAX_PATH SYS `GdipSaveImageToFile`, bitmap%, wide%, clsid{}, 0

SYS !(!bitmap%+8), bitmap% : REM Bitmap::Release SYS "FreeLibrary", ole32% ENDPROC code