#Include <GDIPlus.au3>
#Include <WinAPIEx.au3>
Opt('MustDeclareVars', 1)
Global $Path = FileOpenDialog('Select Image File', @ScriptDir, 'All Images (*.bmp;*.dib;*.jpe;*.jpeg;*.jpg;*.png)', 1 + 2)
If Not $Path Then
Exit
EndIf
Global $hIcon[5] = [256, 64, 48, 32, 16]
Global $hBitmap, $Result = 1
_GDIPlus_Startup()
For $i = 0 To UBound($hIcon) - 1
$hBitmap = _GDIPlus_ImageLoadFromFile($Path)
$hIcon[$i] = _GDIPlus_BitmapCreate32BitHICONFromBitmap($hBitmap, $hIcon[$i], $hIcon[$i])
_GDIPlus_ImageDispose($hBitmap)
If Not $hIcon[$i] Then
$Result = 0
ExitLoop
EndIf
Next
_GDIPlus_Shutdown()
If $Result Then
_WinAPI_SaveHICONToFile(_WinAPI_PathRenameExtension($Path, '.ico'), $hIcon)
EndIf
For $i = 0 To UBound($hIcon) - 1
If IsPtr($hIcon[$i]) Then
_WinAPI_DestroyIcon($hIcon[$i])
EndIf
Next
Func _GDIPlus_BitmapCreate32BitHICONFromBitmap($hBitmap, $iX = -1, $iY = -1, $iARGB = 0)
Local $tBIHDR, $K1, $K2, $Size, $tData, $pBits, $hGraphics, $hPng, $hIcon, $hMask, $hResult = 0
$Size = DllCall($ghGDIPDll, 'uint', 'GdipGetImageDimension', 'ptr', $hBitmap, 'float*', 0, 'float*', 0)
If (@error) Or ($Size[0]) Then
Return 0
EndIf
If $iX = -1 Then
$iX = $Size[2]
EndIf
If $iY = -1 Then
$iY = $Size[3]
EndIf
$K1 = $iX / $Size[2]
$K2 = $iY / $Size[3]
If $K1 > $K2 Then
$K1 = $K2
EndIf
$Size[2] *= $K1
$Size[3] *= $K1
$hPng = DllCall($ghGDIPDll, 'uint', 'GdipCreateBitmapFromScan0', 'int', $iX, 'int', $iY, 'int', 0, 'int', $GDIP_PXF32ARGB, 'ptr', 0, 'ptr*', 0)
$hGraphics = _GDIPlus_ImageGetGraphicsContext($hPng[6])
_GDIPlus_GraphicsClear($hGraphics, $iARGB)
_GDIPlus_GraphicsDrawImageRect($hGraphics, $hBitmap, ($iX - $Size[2]) / 2, ($iY - $Size[3]) / 2, $Size[2], $Size[3])
_GDIPlus_GraphicsDispose($hGraphics)
Do
$tData = _GDIPlus_BitmapLockBits($hPng[6], 0, 0, $iX, $iY, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
$pBits = DllStructGetData($tData, 'Scan0')
If Not $pBits Then
ExitLoop
EndIf
$tBIHDR = DllStructCreate($tagBITMAPINFOHEADER)
DllStructSetData($tBIHDR, 'biSize', DllStructGetSize($tBIHDR))
DllStructSetData($tBIHDR, 'biWidth', $iX)
DllStructSetData($tBIHDR, 'biHeight', $iY)
DllStructSetData($tBIHDR, 'biPlanes', 1)
DllStructSetData($tBIHDR, 'biBitCount', 32)
DllStructSetData($tBIHDR, 'biCompression', $BI_RGB)
$hResult = _WinAPI_CreateDIBSection(0, $tBIHDR, $DIB_RGB_COLORS, $pBits)
If @error Then
ExitLoop
EndIf
_WinAPI_SetBitmapBits($hResult, $iX * $iY * 4, DllStructGetData($tData, 'Scan0'))
_GDIPlus_BitmapUnlockBits($hBitmap, $tData)
Until 1
_GDIPlus_BitmapDispose($hPng[6])
If Not $hResult Then
Return 0
EndIf
$hMask = _WinAPI_CreateBitmap($iX, $iY, 1, 1)
$hIcon = _WinAPI_CreateIconIndirect($hResult, $hMask)
_WinAPI_DeleteObject($hResult)
_WinAPI_DeleteObject($hMask)
Return $hIcon
EndFunc ;==>_GDIPlus_BitmapCreate32BitHICONFromBitmap
Func _WinAPI_SaveHICONToFile($sFile, $aIcon, $iStart = 0, $iEnd = -1)
Local $Icon, $Count = 1
If IsArray($aIcon) Then
If UBound($aIcon, 2) Then
Return SetError(2, 0, 0)
EndIf
If $iStart < 0 Then
$iStart = 0
EndIf
If ($iEnd < 0) Or ($iEnd > UBound($aIcon) - 1) Then
$iEnd = UBound($aIcon) - 1
EndIf
$Count = $iEnd - $iStart + 1
If $Count < 1 Then
Return SetError(1, 0, 0)
EndIf
Dim $Icon[$Count]
For $i = 0 To $Count - 1
$Icon[$i] = $aIcon[$iStart + $i]
Next
Else
Dim $Icon[1] = [$aIcon]
EndIf
Local $hFile = _WinAPI_CreateFileEx($sFile, 2, 0x40000000, 0)
If @error Then
Return SetError(1, 0, 0)
EndIf
Local $tData, $W, $H, $Info, $Bytes, $Error, $Result = 0
Local $tIco = DllStructCreate('ushort Reserved;ushort Type;ushort Count;byte Data[' & (16 * $Count) & ']')
Local $Lenght = DllStructGetSize($tIco)
Local $pIco = DllStructGetPtr($tIco)
Local $tBI = DllStructCreate($tagBITMAPINFOHEADER)
Local $pBI = DllStructGetPtr($tBI)
Local $tDIB = DllStructCreate($tagDIBSECTION)
Local $Size = DllStructGetSize($tDIB)
Local $pDIB = DllStructGetPtr($tDIB)
Local $Offset = $Lenght
DllStructSetData($tIco, 'Reserved', 0)
DllStructSetData($tIco, 'Type', 1)
DllStructSetData($tIco, 'Count', $Count)
DllStructSetData($tBI, 'biSize', 40)
DllStructSetData($tBI, 'biPlanes', 1)
DllStructSetData($tBI, 'biBitCount', 32)
DllStructSetData($tBI, 'biCompression', 0)
DllStructSetData($tBI, 'biXPelsPerMeter', 0)
DllStructSetData($tBI, 'biYPelsPerMeter', 0)
DllStructSetData($tBI, 'biClrUsed', 0)
DllStructSetData($tBI, 'biClrImportant', 0)
Do
If Not _WinAPI_WriteFile($hFile, $pIco, $Lenght, $Bytes) Then
ExitLoop
EndIf
For $i = 0 To $Count - 1
$Info = _WinAPI_GetIconInfo($Icon[$i])
If Not IsArray($Info) Then
ExitLoop 2
EndIf
For $j = 4 To 5
$Info[$j] = _WinAPI_CopyImage($Info[$j], 0, 0, 0, BitOR(0x2000, 0x0008))
If _WinAPI_GetObject($Info[$j], $Size, $pDIB) Then
$Info[$j - 4] = DllStructGetData($tDIB, 'biSizeImage')
$Info[$j - 2] = DllStructGetData($tDIB, 'bmBits')
Else
$Info[$j - 4] = 0
$Info[$j - 2] = 0
EndIf
Next
$W = DllStructGetData($tDIB, 'bmWidth')
$H = DllStructGetData($tDIB, 'bmHeight')
$tData = DllStructCreate('byte Width;byte Height;byte Colors;byte Reserved;word Planes;word BPP;long Size;long Offset', $pIco + 6 + 16 * $i)
DllStructSetData($tData, 'Width', $W)
DllStructSetData($tData, 'Height', $H)
DllStructSetData($tData, 'Colors', 0)
DllStructSetData($tData, 'Reserved', 0)
DllStructSetData($tData, 'Planes', 1)
DllStructSetData($tData, 'BPP', 32)
DllStructSetData($tData, 'Size', 40 + $Info[0] + $Info[1])
DllStructSetData($tData, 'Offset', $Offset)
DllStructSetData($tBI, 'biWidth', $W)
DllStructSetData($tBI, 'biHeight', 2 * $H)
DllStructSetData($tBI, 'biSizeImage', $Info[0] + $Info[1])
$Offset += 40 + $Info[0] + $Info[1]
Do
$Error = 1
If Not _WinAPI_WriteFile($hFile, $pBI, 40, $Bytes) Then
ExitLoop
EndIf
For $j = 1 To 0 Step -1
If Not _WinAPI_WriteFile($hFile, $Info[$j + 2], $Info[$j], $Bytes) Then
ExitLoop 2
EndIf
Next
$Error = 0
Until 1
For $j = 4 To 5
_WinAPI_DeleteObject($Info[$j])
Next
If $Error Then
ExitLoop 2
EndIf
Next
_WinAPI_SetFilePointer($hFile, 0)
If Not _WinAPI_WriteFile($hFile, $pIco, $Lenght, $Bytes) Then
ExitLoop
EndIf
$Result = 1
Until 1
_WinAPI_CloseHandle($hFile)
If Not $Result Then
FileDelete($sFile)
EndIf
Return SetError(Number(Not $Result), 0, $Result)
EndFunc ;==>_WinAPI_SaveHICONToFile