rcmaehl Posted July 16, 2021 Share Posted July 16, 2021 (edited) Hi all, I'm attempting to recolor both the foreground (single color) and background (transparency) of an icon. Currently I'm using an updated _SetBKIcon script Func _SetBkIcon($ControlID, $iBackground, $sIcon, $iIndex, $iWidth, $iHeight) Local Static $STM_SETIMAGE = 0x0172 Local $hDC, $hBackDC, $hBackSv, $hBitmap, $hImage, $hIcon, $hBkIcon $hIcon = _WinAPI_ShellExtractIcon($sIcon, $iIndex, $iWidth, $iHeight) $hDC = _WinAPI_GetDC(0) $hBackDC = _WinAPI_CreateCompatibleDC($hDC) $hBitmap = _WinAPI_CreateSolidBitmap(0, $iBackground, $iWidth, $iHeight) $hBackSv = _WinAPI_SelectObject($hBackDC, $hBitmap) _WinAPI_DrawIconEx($hBackDC, 0, 0, $hIcon, 0, 0, 0, 0, $DI_NORMAL) $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap) $hBkIcon = DllCall($__g_hGDIPDll, 'int', 'GdipCreateHICONFromBitmap', 'hWnd', $hImage, 'int*', 0) $hBkIcon = $hBkIcon[2] _GDIPlus_ImageDispose($hImage) GUICtrlSendMsg($ControlID, $STM_SETIMAGE, $IMAGE_ICON, _WinAPI_CopyIcon($hBkIcon)) _WinAPI_RedrawWindow(GUICtrlGetHandle($ControlID)) _WinAPI_SelectObject($hBackDC, $hBackSv) _WinAPI_DeleteDC($hBackDC) _WinAPI_ReleaseDC(0, $hDC) _WinAPI_DeleteObject($hBkIcon) _WinAPI_DeleteObject($hBitmap) _WinAPI_DeleteObject($hIcon) Return SetError(0, 0, 1) EndFunc ;==>_SetBkIcon and I see some GDI functions for recoloring but I don't see anywhere that they can be used. However, most of the recoloring uses _GDIPlus_ImageAttributesCreate() However, this isn't used in the existing function, so I don't see how it can be merged in. I think this is because the icon is just copied onto the existing specified color background in _SetBKIcon. I think it might be better to use _GDIPlus_ImageAttributesSetRemapTable() to change transparency in an icon to a specific color and the color of the icon to a different color, however it uses _GDIPlus_GraphicsCreateFromHWND() which specifies in documentation that it needs a Window Handle, not a control handle. Any advice is appreciated! Edited July 16, 2021 by rcmaehl My UDFs are generally for me. If they aren't updated for a while, it means I'm not using them myself. As soon as I start using them again, they'll get updated.My Projects WhyNotWin11Cisco Finesse, Github, IRC UDF, WindowEx UDF Link to comment Share on other sites More sharing options...
rcmaehl Posted July 18, 2021 Author Share Posted July 18, 2021 (edited) I've attempted to implement part of @UEZ's GDI+ Color Transformer v0.9.7 build 2016-04-23. The recoloring works within his executable, however I can't seem to reproduce the effect. My code is below: expandcollapse popup#include <GDIPlus.au3> #include <WinAPISysWin.au3> #include <WinAPIShellEx.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include "ResourcesEX.au3" Global Const $GDIP_COLORCURVEEFFECT = "{DD6A0022-58E4-4a67-9D9B-D48EB881A53D}" Global Const $tagCOLORCURVEEFFECTPARAMS = "int type;int channel;int value" Global Enum $iAdjustExposure = 0, $iAdjustDensity, $iAdjustContrast, $iAdjustHighlight, $iAdjustShadow, _ ;http://msdn.microsoft.com/en-us/library/windows/desktop/ms534098(v=vs.85).aspx $iAdjustMidtone, $iAdjustWhiteSaturation, $iAdjustBlackSaturation Global Enum $iCurveChannelAll = 0, $iCurveChannelRed, $iCurveChannelGreen, $iCurveChannelBlue ;http://msdn.microsoft.com/en-us/library/windows/desktop/ms534100(v=vs.85).aspx Global $tColorCurve = DllStructCreate($tagCOLORCURVEEFFECTPARAMS), $iType = $iAdjustExposure, $iChannel = $iCurveChannelAll Example_1() ;###################################################################################################################################### ; #FUNCTION# ==================================================================================================================== ; Name ..........: _GDIPlus_GraphicsGetDPIRatio ; Description ...: ; Syntax ........: _GDIPlus_GraphicsGetDPIRatio([$iDPIDef = 96]) ; Parameters ....: $iDPIDef - [optional] An integer value. Default is 96. ; Return values .: None ; Author ........: UEZ ; Modified ......: ; Remarks .......: ; Related .......: ; Link ..........: http://www.autoitscript.com/forum/topic/159612-dpi-resolution-problem/?hl=%2Bdpi#entry1158317 ; Example .......: No ; =============================================================================================================================== Func _GDIPlus_GraphicsGetDPIRatio($iDPIDef = 96) _GDIPlus_Startup() Local $hGfx = _GDIPlus_GraphicsCreateFromHWND(0) If @error Then Return SetError(1, @extended, 0) #forcedef $__g_hGDIPDll Local $aResult = DllCall($__g_hGDIPDll, "int", "GdipGetDpiX", "handle", $hGfx, "float*", 0) If @error Then Return SetError(2, @extended, 0) Local $iDPI = $aResult[2] Local $aResults[2] = [$iDPIDef / $iDPI, $iDPI / $iDPIDef] _GDIPlus_GraphicsDispose($hGfx) _GDIPlus_Shutdown() Return $aResults EndFunc ;==>_GDIPlus_GraphicsGetDPIRatio Func _GDIPlus_ColorCurve($tColorCurve, $iType, $iChannel, $iValue) If Not IsDllStruct($tColorCurve) Then Return SetError(1, @error, 0) DllStructSetData($tColorCurve, "type", $iType) DllStructSetData($tColorCurve, "channel", $iChannel) DllStructSetData($tColorCurve, "value", $iValue) Local $pEffect = _GDIPlus_EffectCreate($GDIP_COLORCURVEEFFECT) If @error Then Return SetError(2, @error, 0) _GDIPlus_EffectsSetParameters($pEffect, $tColorCurve) If @error Then Return SetError(3, @error, 0) Return $pEffect EndFunc ;==>_GDIPlus_ColorCurve Func _GDIPlus_EffectsSetParameters($pEffectObject, $tEffectParameters, $iSizeAdj = 1) Local $aSize = DllCall($__g_hGDIPDll, "uint", "GdipGetEffectParameterSize", "ptr", $pEffectObject, "uint*", 0) Local $iSize = $aSize[2] * $iSizeAdj Local $aResult = DllCall($__g_hGDIPDll, "uint", "GdipSetEffectParameters", "ptr", $pEffectObject, "struct*", $tEffectParameters, "uint", $iSize) If @error Then Return SetError(@error, @extended, 0) Return SetError($aResult[0], 0, $aResult[3]) EndFunc ;==>_GDIPlus_EffectsSetParameters Func _SetBkIcon($ControlID, $iBackground, $iForeground, $sIcon, $iIndex, $iWidth, $iHeight) Local Static $STM_SETIMAGE = 0x0172 Local $hDC, $hBackDC, $hBackSv, $hBitmap, $hImage, $hIcon, $hBkIcon Local $hEffect $hIcon = _WinAPI_ShellExtractIcon($sIcon, $iIndex, $iWidth, $iHeight) $hDC = _WinAPI_GetDC(0) $hBackDC = _WinAPI_CreateCompatibleDC($hDC) $hBitmap = _WinAPI_CreateSolidBitmap(0, $iBackground, $iWidth, $iHeight) $hBackSv = _WinAPI_SelectObject($hBackDC, $hBitmap) _WinAPI_DrawIconEx($hBackDC, 0, 0, $hIcon, 0, 0, 0, 0, $DI_NORMAL) $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap) $hBkIcon = DllCall($__g_hGDIPDll, 'int', 'GdipCreateHICONFromBitmap', 'hWnd', $hImage, 'int*', 0) $hBkIcon = $hBkIcon[2] Local $sForeground = Hex($iForeground) Local $iRed = Dec(StringRight(StringLeft($sForeground, 4), 2)) Local $iGreen = Dec(StringRight(StringLeft($sForeground, 6), 2)) Local $iBlue = Dec(StringRight(StringLeft($sForeground, 8), 2)) $hEffect = _GDIPlus_ColorCurve($tColorCurve, $iType, $iCurveChannelAll, 255) _GDIPlus_EffectDispose($hEffect) $hEffect = _GDIPlus_ColorCurve($tColorCurve, $iType, $iCurveChannelRed, $iRed) _GDIPlus_EffectDispose($hEffect) $hEffect = _GDIPlus_ColorCurve($tColorCurve, $iType, $iCurveChannelGreen, $iGreen) _GDIPlus_EffectDispose($hEffect) $hEffect = _GDIPlus_ColorCurve($tColorCurve, $iType, $iCurveChannelBlue, $iBlue) _GDIPlus_EffectDispose($hEffect) _GDIPlus_ImageDispose($hImage) GUICtrlSendMsg($ControlID, $STM_SETIMAGE, $IMAGE_ICON, _WinAPI_CopyIcon($hBkIcon)) _WinAPI_RedrawWindow(GUICtrlGetHandle($ControlID)) _WinAPI_SelectObject($hBackDC, $hBackSv) _WinAPI_DeleteDC($hBackDC) _WinAPI_ReleaseDC(0, $hDC) _WinAPI_DeleteObject($hBkIcon) _WinAPI_DeleteObject($hBitmap) _WinAPI_DeleteObject($hIcon) Return SetError(0, 0, 1) EndFunc ;==>_SetBkIcon Func Example_1() Local $hGui = GUICreate("GDI+", 200, 50) GUISetState(@SW_SHOW) _GDIPlus_Startup() GUICtrlCreateIcon("", -1, 10, 10, 32, 32) _SetBkIcon(-1, 0x000000, 0xFFFFFF, @ScriptDir & "\git.ico", -1, 32, 32) Do Until GUIGetMsg() = $GUI_EVENT_CLOSE GUIDelete($hGui) EndFunc ;==>Example_1 I'm 200% sure this is user error. ResourcesEx.au3 git.ico Edited July 18, 2021 by rcmaehl My UDFs are generally for me. If they aren't updated for a while, it means I'm not using them myself. As soon as I start using them again, they'll get updated.My Projects WhyNotWin11Cisco Finesse, Github, IRC UDF, WindowEx UDF Link to comment Share on other sites More sharing options...
UEZ Posted July 18, 2021 Share Posted July 18, 2021 As far as I can remember the recoloring aka HUE modification works only for color images. Your icon is nearly a b/w image. In this case you can do something like this here: expandcollapse popup#include <GDIPlus.au3> #include <WinAPISysWin.au3> #include <WinAPIShellEx.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> Example_1() Func _SetBkIcon($ControlID, $iForeground_old, $iForeground_new, $iBackground, $sIcon, $iIndex, $iWidth, $iHeight) Local Static $STM_SETIMAGE = 0x0172 Local $hBitmap, $hImage, $hIcon, $hBkIcon, $hGfx $hIcon = _WinAPI_ShellExtractIcon($sIcon, $iIndex, $iWidth, $iHeight) $hImage = _GDIPlus_BitmapCreateFromHICON($hIcon) Local $aRemapTable[2][2] $aRemapTable[0][0] = 1 $aRemapTable[1][0] = $iForeground_old $aRemapTable[1][1] = $iForeground_new Local $hImgAttr = _GDIPlus_ImageAttributesCreate() _GDIPlus_ImageAttributesSetRemapTable($hImgAttr, $aRemapTable) Local $iW = _GDIPlus_ImageGetWidth($hImage), $iH = _GDIPlus_ImageGetHeight($hImage) $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH) $hGfx = _GDIPlus_ImageGetGraphicsContext($hBitmap) _GDIPlus_GraphicsClear($hGfx, $iBackground) _GDIPlus_GraphicsDrawImageRectRect($hGfx, $hImage, 0, 0, $iW, $iH, 0, 0, $iW, $iH, $hImgAttr) $hBkIcon = _GDIPlus_HICONCreateFromBitmap($hBitmap) GUICtrlSendMsg($ControlID, $STM_SETIMAGE, $IMAGE_ICON, _WinAPI_CopyIcon($hBkIcon)) _WinAPI_RedrawWindow(GUICtrlGetHandle($ControlID)) _WinAPI_DeleteObject($hIcon) _WinAPI_DeleteObject($hBkIcon) _GDIPlus_GraphicsDispose($hGfx) _GDIPlus_ImageDispose($hImage) _GDIPlus_ImageDispose($hBitmap) _GDIPlus_ImageAttributesDispose($hImgAttr) Return SetError(0, 0, 1) EndFunc ;==>_SetBkIcon Func Example_1() Local $hGui = GUICreate("GDI+", 200, 50) GUISetState(@SW_SHOW) _GDIPlus_Startup() GUICtrlCreateIcon("", -1, 10, 10, 32, 32) _SetBkIcon(-1, 0xFF000000, 0xFFFFFFFF, 0xFF000000, @ScriptDir & "\git.ico", -1, 32, 32) Do Until GUIGetMsg() = $GUI_EVENT_CLOSE GUIDelete($hGui) EndFunc ;==>Example_1 It will change the foreground color from black to white and set the background color to black. rcmaehl 1 Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
rcmaehl Posted July 18, 2021 Author Share Posted July 18, 2021 (edited) 6 hours ago, UEZ said: As far as I can remember the recoloring aka HUE modification works only for color images. Your icon is nearly a b/w image. In this case you can do something like this here: It will change the foreground color from black to white and set the background color to black. Works good. Thanks! Anti-aliasing in the icons is missing them up a bit but I should be able to fix that using by adjusting the remap table. Edited July 18, 2021 by rcmaehl My UDFs are generally for me. If they aren't updated for a while, it means I'm not using them myself. As soon as I start using them again, they'll get updated.My Projects WhyNotWin11Cisco Finesse, Github, IRC UDF, WindowEx UDF Link to comment Share on other sites More sharing options...
rcmaehl Posted July 19, 2021 Author Share Posted July 19, 2021 (edited) I'm been unable to resolve the issue with anti-aliasing, the images are always going to be originally grayscale so I removed foreground_old, but I can't seem to get the aliased images to adjust. I tried defining all gray scale and adjusting the new color accordingly but that didn't work. I've also tried defining all transparency levels and the issue persists. I'm thinking it's an issue elsewhere as skipping the remap table causes the same issue. expandcollapse popup#include <Array.au3> #include <GDIPlus.au3> #include <WinAPISysWin.au3> #include <WinAPIShellEx.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> Example_1() Func _SetBkIcon($ControlID, $iForeground, $iBackground, $sIcon, $iIndex, $iWidth, $iHeight) Local Static $STM_SETIMAGE = 0x0172 Local $hBitmap, $hImage, $hIcon, $hBkIcon, $hGfx $hIcon = _WinAPI_ShellExtractIcon($sIcon, $iIndex, $iWidth, $iHeight) $hImage = _GDIPlus_BitmapCreateFromHICON($hIcon) If $iForeground <> 0 Then ; Skip Recoloring Foreground if Black Local Static $aRemapTable[65537][2] ; Cache Remap Table If Not $aRemapTable <> "" Then $aRemapTable[0][0] = 65536 For $iTransparency = 0 To 255 Step 1 For $iShade = 1 To 256 Step 1 $aRemapTable[(255 * $iTransparency) + $iShade][0] = "0x" & Hex($iTransparency) & Hex($iShade - 1, 2) & Hex($iShade - 1, 2) & Hex($iShade - 1, 2) $aRemapTable[(255 * $iTransparency) + $iShade][1] = "0x" & Hex($iTransparency) & Hex(Int($iForeground * ((255 - ($iShade - 1)) / 255)), 6) Next Next EndIf EndIf Local $hImgAttr = _GDIPlus_ImageAttributesCreate() If $iForeground <> 0 Then _GDIPlus_ImageAttributesSetRemapTable($hImgAttr, $aRemapTable) Local $iW = _GDIPlus_ImageGetWidth($hImage), $iH = _GDIPlus_ImageGetHeight($hImage) $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH) $hGfx = _GDIPlus_ImageGetGraphicsContext($hBitmap) _GDIPlus_GraphicsClear($hGfx, $iBackground) _GDIPlus_GraphicsDrawImageRectRect($hGfx, $hImage, 0, 0, $iW, $iH, 0, 0, $iW, $iH, $hImgAttr) $hBkIcon = _GDIPlus_HICONCreateFromBitmap($hBitmap) GUICtrlSendMsg($ControlID, $STM_SETIMAGE, $IMAGE_ICON, _WinAPI_CopyIcon($hBkIcon)) _WinAPI_RedrawWindow(GUICtrlGetHandle($ControlID)) _WinAPI_DeleteObject($hIcon) _WinAPI_DeleteObject($hBkIcon) _GDIPlus_GraphicsDispose($hGfx) _GDIPlus_ImageDispose($hImage) _GDIPlus_ImageDispose($hBitmap) _GDIPlus_ImageAttributesDispose($hImgAttr) Return SetError(0, 0, 1) EndFunc ;==>_SetBkIcon Func Example_1() Local $hGui = GUICreate("GDI+", 768, 256) GUISetState(@SW_SHOW) _GDIPlus_Startup() ; Original Icon GUICtrlCreateIcon(@ScriptDir & "\git.ico", -1, 0, 0, 256, 256) ; Only Recolor Background GUICtrlCreateIcon("", -1, 256, 0, 256, 256) _SetBkIcon(-1, 0x000000, 0xFFFFFFFF, @ScriptDir & "\git.ico", -1, 256, 256) ; Recolor Foreground and Background GUICtrlCreateIcon("", -1, 512, 0, 256, 256) _SetBkIcon(-1, 0xFF0000, 0xFF000000, @ScriptDir & "\git.ico", -1, 256, 256) Do Until GUIGetMsg() = $GUI_EVENT_CLOSE GUIDelete($hGui) EndFunc ;==>Example_1 Edited July 19, 2021 by rcmaehl My UDFs are generally for me. If they aren't updated for a while, it means I'm not using them myself. As soon as I start using them again, they'll get updated.My Projects WhyNotWin11Cisco Finesse, Github, IRC UDF, WindowEx UDF Link to comment Share on other sites More sharing options...
UEZ Posted July 22, 2021 Share Posted July 22, 2021 (edited) I found another way to change the color without loosing proper anti-aliasing. For this solution GDI+ v1.1 (Win7+) is required. expandcollapse popup#include <Array.au3> #include <GDIPlus.au3> #include <WinAPISysWin.au3> #include <WinAPIShellEx.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> Example_1() Func _SetBkIcon($ControlID, $iForeground, $iBackground, $sIcon, $iIndex, $iWidth, $iHeight) Local Static $STM_SETIMAGE = 0x0172 Local $hBitmap, $hGfx, $hImage, $hIcon, $hBkIcon $hIcon = _WinAPI_ShellExtractIcon($sIcon, $iIndex, $iWidth, $iHeight) $hImage = _GDIPlus_BitmapCreateFromHICON32($hIcon) Local $r = BitShift(BitAND($iForeground, 0xFF0000), 16), $g = BitShift(BitAND($iForeground, 0xFF00), 8), $b = BitAND($iForeground, 0xFF) Local $hEffect = _GDIPlus_EffectCreateColorCurve($GDIP_AdjustExposure, $GDIP_CurveChannelRed, $r) ;GDI+ v1.1 is needed -> Win7+ _GDIPlus_BitmapApplyEffect($hImage, $hEffect) _GDIPlus_EffectDispose($hEffect) $hEffect = _GDIPlus_EffectCreateColorCurve($GDIP_AdjustExposure, $GDIP_CurveChannelGreen, $g) _GDIPlus_BitmapApplyEffect($hImage, $hEffect) _GDIPlus_EffectDispose($hEffect) $hEffect = _GDIPlus_EffectCreateColorCurve($GDIP_AdjustExposure, $GDIP_CurveChannelBlue, $b) _GDIPlus_BitmapApplyEffect($hImage, $hEffect) _GDIPlus_EffectDispose($hEffect) If $iBackground Then $hBitmap = _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight) $hGfx = _GDIPlus_ImageGetGraphicsContext($hBitmap) _GDIPlus_GraphicsClear($hGfx, $iBackground) _GDIPlus_GraphicsDrawImageRect($hGfx, $hImage, 0, 0, $iWidth, $iHeight) _GDIPlus_ImageDispose($hImage) $hImage = _GDIPlus_ImageClone($hBitmap) _GDIPlus_GraphicsDispose($hGfx) _GDIPlus_ImageDispose($hBitmap) EndIf $hBkIcon = _GDIPlus_HICONCreateFromBitmap($hImage) GUICtrlSendMsg($ControlID, $STM_SETIMAGE, $IMAGE_ICON, $hBkIcon) _WinAPI_RedrawWindow(GUICtrlGetHandle($ControlID)) _WinAPI_DeleteObject($hIcon) _WinAPI_DeleteObject($hBkIcon) _GDIPlus_ImageDispose($hImage) Return SetError(0, 0, 1) EndFunc ;==>_SetBkIcon Func Example_1() Local $hGui = GUICreate("GDI+", 512, 256) GUISetState(@SW_SHOW) If Not _GDIPlus_Startup() Or @extended < 6 Then MsgBox($MB_SYSTEMMODAL, "ERROR", "GDIPlus.dll v1.1 not available") Return EndIf ; Original Icon GUICtrlCreateIcon(@ScriptDir & "\git.ico", -1, 0, 0, 256, 256) ; Only Recolor Background GUICtrlCreateIcon("", -1, 256, 0, 256, 256) _SetBkIcon(-1, 0xFFABCDEF, 0xFFFFFF00, @ScriptDir & "\git.ico", -1, 256, 256) Do Until GUIGetMsg() = $GUI_EVENT_CLOSE GUIDelete($hGui) EndFunc ;==>Example_1 Works best with monochrome like images. Btw, when you use $hImage = _GDIPlus_BitmapCreateFromHICON32($hIcon) in your example it will work, too. Edited July 22, 2021 by UEZ Earthshine and rcmaehl 2 Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now