JohnnyThrash Posted June 1, 2010 Posted June 1, 2010 (edited) Func ExtractIcons($file, $folder, $output) $Ret = DllCall("shell32","long","ExtractAssociatedIcon","int",0,"str",$file,"int*",(-1*-1)-1) $hIcon = $Ret[0] _GDIPlus_Startup() $pBitmap = DllCall($ghGDIPDll,"int","GdipCreateBitmapFromHICON", "ptr",$hIcon, "int*",0) $pBitmap = $pBitmap[2] _GDIPlus_ImageSaveToFileEx($pBitmap,@ScriptDir&"\temp\images\"&$folder&$output&".png", _GDIPlus_EncodersGetCLSID("PNG")) _GDIPlus_ImageDispose($pBitmap) _GDIPlus_Shutdown() _WinAPI_DestroyIcon($hIcon) ; return @ScriptDir&"\temp\images\"&$folder&$output&".png" EndFunc The above function will extract an icon from any file I need and save it as a png. But GDI won't load in the alpha channel for the icon. My understanding is that this is a known issue. I read somewhere that you could use the shell32.dll function "SHGetFileInfo" in order to get the alpha channel into gdi and then paint the color over it, but that is so very much beyond my comprehension or capabilites. Anybody have an ideas? Has anybody done this sucessfully? PS: The png I get from the icons do have transparency but it's like a gif in that it only has either opaque or non-opaque, there is no in between. EDIT: To better clarify what I mean I basically need my function to extract the icons as it already does but additionally with the icons alpha channel so my pngs can keep intact the effect which incorporate variable transparency such as the shadows and the like. Edited June 1, 2010 by JohnnyThrash
UEZ Posted June 1, 2010 Posted June 1, 2010 Did you try HICON to .ico file already?BR,UEZ 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!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
JohnnyThrash Posted June 1, 2010 Author Posted June 1, 2010 Did you try HICON to .ico file already?BR,UEZYes, i have looked at this code previously. However, I'm not sure it will do the trick. The code in the link seems to rely on the icon being saved as an icon and not png. Maybe it's exactly what I'm looking for but I don't think. Thanks for your help though. I think the key is probably going to be in dealing with GDI but i don't know exactly how.
UEZ Posted June 1, 2010 Posted June 1, 2010 I found this in my collection: ... ;transparent code by smashly / Malkey - modified by UEZ $hImage = _GDIPlus_BitmapCloneArea($Bitmap, 0, 0, $w, $h, $GDIP_PXF32ARGB) $tBitmapData = _GDIPlus_BitmapLockBits($hImage, 0, 0, $w, $h, $GDIP_ILMWRITE, $GDIP_PXF32ARGB) $iStride = DllStructGetData($tBitmapData, "stride") $iScan0 = DllStructGetData($tBitmapData, "Scan0") $tPixel = DllStructCreate("int", $iScan0 + (0 * $iStride) + (0 * 4)) $iFirstPixel = DllStructGetData($tPixel, 1) $iTransPixel = BitAND($iFirstPixel, 0x00FFFFFF) $iFirstPixel = StringRegExpReplace(Hex($iFirstPixel, 8), "(.{2})(.{2})(.{2})(.{2})", "\4\3\2\1") $iTransPixel = StringTrimRight($iFirstPixel, 2) & "00" $v_BufferA = DllStructCreate("byte[" & $h * $w * 4 & "]", $iScan0) ; Create DLL structure for all pixels $AllPixels = DllStructGetData($v_BufferA, 1) $sREResult1 = StringRegExpReplace(StringTrimLeft($AllPixels, 2), "(.{8})", "\1 ") $sPix = "0x" & StringStripWS(StringRegExpReplace($sREResult1, "(" & $iFirstPixel & ")", $iTransPixel), 8) $AllPixels = DllStructSetData($v_BufferA, 1, $sPix) _GDIPlus_BitmapUnlockBits($hImage, $tBitmapData) _GDIPlus_ImageSaveToFileEx($hImage, @ScriptDir & "\Test.PNG", _GDIPlus_EncodersGetCLSID("PNG")) _GDIPlus_ImageDispose($hImage) ... Maybe this will help you. It will create a transparency and save it as png. BR, UEZ 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!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
UEZ Posted June 1, 2010 Posted June 1, 2010 Here the example with your code from 1st post: expandcollapse popup#include <GDIPlus.au3> ExtractIcons("Test.exe") Func ExtractIcons($file) $Ret = DllCall("shell32","long","ExtractAssociatedIcon","int",0,"str",$file,"int*",(-1*-1)-1) $hIcon = $Ret[0] _GDIPlus_Startup() $Bitmap = DllCall($ghGDIPDll,"int","GdipCreateBitmapFromHICON", "ptr",$hIcon, "int*",0) $Bitmap = $Bitmap[2] $w = _GDIPlus_ImageGetWidth($Bitmap) $h = _GDIPlus_ImageGetHeight($Bitmap) ;transparent code by smashly / Malkey - modified by UEZ $hImage = _GDIPlus_BitmapCloneArea($Bitmap, 0, 0, $w, $h, $GDIP_PXF32ARGB) $tBitmapData = _GDIPlus_BitmapLockBits($hImage, 0, 0, $w, $h, $GDIP_ILMWRITE, $GDIP_PXF32ARGB) $iStride = DllStructGetData($tBitmapData, "stride") $iScan0 = DllStructGetData($tBitmapData, "Scan0") $tPixel = DllStructCreate("int", $iScan0 + (0 * $iStride) + (0 * 4)) $iFirstPixel = DllStructGetData($tPixel, 1) $iTransPixel = BitAND($iFirstPixel, 0x00FFFFFF) $iFirstPixel = StringRegExpReplace(Hex($iFirstPixel, 8), "(.{2})(.{2})(.{2})(.{2})", "\4\3\2\1") $iTransPixel = StringTrimRight($iFirstPixel, 2) & "00" $v_BufferA = DllStructCreate("byte[" & $h * $w * 4 & "]", $iScan0) ; Create DLL structure for all pixels $AllPixels = DllStructGetData($v_BufferA, 1) $sREResult1 = StringRegExpReplace(StringTrimLeft($AllPixels, 2), "(.{8})", "\1 ") $sPix = "0x" & StringStripWS(StringRegExpReplace($sREResult1, "(" & $iFirstPixel & ")", $iTransPixel), 8) $AllPixels = DllStructSetData($v_BufferA, 1, $sPix) _GDIPlus_BitmapUnlockBits($hImage, $tBitmapData) _GDIPlus_ImageSaveToFileEx($hImage, @ScriptDir & "\Test.PNG", _GDIPlus_EncodersGetCLSID("PNG")) _GDIPlus_ImageDispose($hImage) _GDIPlus_Shutdown() _WinAPI_DestroyIcon($hIcon) ; return 1 EndFunc Please try it with a transparent icon! BR, UEZ 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!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
JohnnyThrash Posted June 1, 2010 Author Posted June 1, 2010 I found this in my collection: ... ;transparent code by smashly / Malkey - modified by UEZ $hImage = _GDIPlus_BitmapCloneArea($Bitmap, 0, 0, $w, $h, $GDIP_PXF32ARGB) $tBitmapData = _GDIPlus_BitmapLockBits($hImage, 0, 0, $w, $h, $GDIP_ILMWRITE, $GDIP_PXF32ARGB) $iStride = DllStructGetData($tBitmapData, "stride") $iScan0 = DllStructGetData($tBitmapData, "Scan0") $tPixel = DllStructCreate("int", $iScan0 + (0 * $iStride) + (0 * 4)) $iFirstPixel = DllStructGetData($tPixel, 1) $iTransPixel = BitAND($iFirstPixel, 0x00FFFFFF) $iFirstPixel = StringRegExpReplace(Hex($iFirstPixel, 8), "(.{2})(.{2})(.{2})(.{2})", "\4\3\2\1") $iTransPixel = StringTrimRight($iFirstPixel, 2) & "00" $v_BufferA = DllStructCreate("byte[" & $h * $w * 4 & "]", $iScan0) ; Create DLL structure for all pixels $AllPixels = DllStructGetData($v_BufferA, 1) $sREResult1 = StringRegExpReplace(StringTrimLeft($AllPixels, 2), "(.{8})", "\1 ") $sPix = "0x" & StringStripWS(StringRegExpReplace($sREResult1, "(" & $iFirstPixel & ")", $iTransPixel), 8) $AllPixels = DllStructSetData($v_BufferA, 1, $sPix) _GDIPlus_BitmapUnlockBits($hImage, $tBitmapData) _GDIPlus_ImageSaveToFileEx($hImage, @ScriptDir & "\Test.PNG", _GDIPlus_EncodersGetCLSID("PNG")) _GDIPlus_ImageDispose($hImage) ... Maybe this will help you. It will create a transparency and save it as png. BR, UEZ I have to admit, I don't actually understand you code entirely. Also, I had to change the $W and $h to 32, since they weren't defined. Here's the code I came up with but it still produces the same results as before. As I've mentioned before I can sucessfully get a png from the icon with a transparent background, however I cannot get any variable transparency. Func ExtractIcons($file, $folder, $output) $Ret = DllCall("shell32","long","ExtractAssociatedIcon","int",0,"str",$file,"int*",(-1*-1)-1) ;$hIcon=getIconHandleByFile($file) $hIcon = $Ret[0] _GDIPlus_Startup() $pBitmap = DllCall($ghGDIPDll,"int","GdipCreateBitmapFromHICON", "ptr",$hIcon, "int*",0) $pBitmap = $pBitmap[2] ;transparent code by smashly / Malkey - modified by UEZ $hImage = _GDIPlus_BitmapCloneArea($pBitmap, 0, 0, 32, 32, $GDIP_PXF32ARGB) $tBitmapData = _GDIPlus_BitmapLockBits($hImage, 0, 0, 32, 32, $GDIP_ILMWRITE, $GDIP_PXF32ARGB) $iStride = DllStructGetData($tBitmapData, "stride") $iScan0 = DllStructGetData($tBitmapData, "Scan0") $tPixel = DllStructCreate("int", $iScan0 + (0 * $iStride) + (0 * 4)) $iFirstPixel = DllStructGetData($tPixel, 1) $iTransPixel = BitAND($iFirstPixel, 0x00FFFFFF) $iFirstPixel = StringRegExpReplace(Hex($iFirstPixel, 8), "(.{2})(.{2})(.{2})(.{2})", "\4\3\2\1") $iTransPixel = StringTrimRight($iFirstPixel, 2) & "00" $v_BufferA = DllStructCreate("byte[" & 32 * 32 * 4 & "]", $iScan0) ; Create DLL structure for all pixels $AllPixels = DllStructGetData($v_BufferA, 1) $sREResult1 = StringRegExpReplace(StringTrimLeft($AllPixels, 2), "(.{8})", "\1 ") $sPix = "0x" & StringStripWS(StringRegExpReplace($sREResult1, "(" & $iFirstPixel & ")", $iTransPixel), 8) $AllPixels = DllStructSetData($v_BufferA, 1, $sPix) _GDIPlus_BitmapUnlockBits($hImage, $tBitmapData) _GDIPlus_ImageSaveToFileEx($hImage, @ScriptDir&"\temp\images\"&$folder&$output&".png", _GDIPlus_EncodersGetCLSID("PNG")) _GDIPlus_ImageDispose($hImage) return @ScriptDir&"\temp\images\"&$folder&$output&".png" EndFunc I hope I'm not being a pain in the ass.
UEZ Posted June 1, 2010 Posted June 1, 2010 What are "variable transparency" icons? Can you upload one? BR, UEZ 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!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
JohnnyThrash Posted June 1, 2010 Author Posted June 1, 2010 What are "variable transparency" icons?Can you upload one?BR,UEZWell, really, I'm just throwing that term around. It means that there are varying levels of opacity. There's not just see-through and solid. There's also amounts in between. An example of an icon i can extract is this:You might be familiar with this icon. However, the icon you've seen has a subtle drop shadow effect, only here instead you see a thick black outline. That black area is an area that would be slightly see through but not entirely opaque or otherwise.
UEZ Posted June 2, 2010 Posted June 2, 2010 Indeed, it is not working properly... BR, UEZ 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!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
JohnnyThrash Posted June 2, 2010 Author Posted June 2, 2010 Indeed, it is not working properly... BR,UEZOut of ideas, huh? Well thanks for your help so far. Maybe somebody will come along yet and offer some more help for this. This is an integeral aspect of my application.
evilertoaster Posted June 2, 2010 Posted June 2, 2010 GDI might very well strip the alpha channel... Have you tried CreateIconFromResource() ?There's some rough examples of use, but you you'll have to do some work to get what you want:http://www.autoitscript.com/forum/index.php?showtopic=97548http://www.autoitscript.com/forum/index.php?showtopic=32476http://www.autoitscript.com/forum/index.php?showtopic=76658http://www.autoitscript.com/forum/index.php?showtopic=74621
JohnnyThrash Posted June 2, 2010 Author Posted June 2, 2010 GDI might very well strip the alpha channel... Have you tried CreateIconFromResource() ?There's some rough examples of use, but you you'll have to do some work to get what you want:http://www.autoitscript.com/forum/index.php?showtopic=97548http://www.autoitscript.com/forum/index.php?showtopic=32476http://www.autoitscript.com/forum/index.php?showtopic=76658http://www.autoitscript.com/forum/index.php?showtopic=74621Well that's exactly the way i understand it. When GDI loads an icon it does not load the alpha channel or it discards it.I have a concept, but I have no idea how to execute it. What if i got just the alpha channel and looped through all the pixels in the icon setting each to have the opacity that corresponds to the alpha channel? I've seen this done in other languages but not Autoit. Any ideas?
Moderators SmOke_N Posted June 2, 2010 Moderators Posted June 2, 2010 I've seen this done in other languages but not Autoit. Any ideas?It might be good to post the code you know works in other languages so someone can help you translate it to AutoIt? Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.
JohnnyThrash Posted June 2, 2010 Author Posted June 2, 2010 (edited) It might be good to post the code you know works in other languages so someone can help you translate it to AutoIt?Good idea, sorry, I should have thought of that.Below is a excerp from the following link : http://groups.google.com.ar/group/microsoft.public.win32.programmer.gdi/msg/fa5de1f2bc9a04d3I believe a translation of the following code *may* do what I am hoping.and for what it's worth, I have looked into doing the task myself but some of this goes way over my head (That's why I use autoit instead of a more complicated language =P)The Solution was to Get the ICONINFO from the icon, Create a bitmap using the ICONINFO’s bitmap handle, get the BitmapData from it, and use the BitmapData to create another bitmap which has the alpha channel. //get the icon info ICONINFO ii; GetIconInfo(hIcon, &ii); //create a bitmap from the ICONINFO so we can access the bitmapData Bitmap bmpIcon(ii.hbmColor, NULL); Rect rectBounds(0, 0, bmpIcon.GetWidth(), bmpIcon.GetHeight() ); //get the BitmapData BitmapData bmData; bmpIcon.LockBits(&rectBounds, ImageLockModeRead, bmpIcon.GetPixelFormat(), &bmData); // create a new 32 bit bitmap using the bitmapData Bitmap bmpAlpha(bmData.Width, bmData.Height, bmData.Stride, PixelFormat32bppARGB, (BYTE*)bmData.Scan0); bmpIcon.UnlockBits(&bmData); Now we have the icon with the alpha channel loaded into bmpAlpha! Note: my code only works for icons with an alpha channel. This solves my problem but it seems strange to me that directly creating a Bitmap from an HICON cusses the Alpha channel to be lost. Am I not understanding something, or is it possibly a bug?. If anyone can explain this I would love to know the reason. Another solution might be found here as well,http://blogs.msdn.com/b/andreww/archive/2007/10/10/preserving-the-alpha-channel-when-converting-images.aspx Edited June 2, 2010 by JohnnyThrash
JohnnyThrash Posted June 6, 2010 Author Posted June 6, 2010 UPDATE: I've also found this on the autohotkey forums. I hope this isn't taboo or anything =S. I figured since AutoHotKey and AutoIt were so similar this might help.The only issue is it's not entirely clear to me how the solution provided in this topic is applied.If anybody could offer any insight on this I would very much appreciate it.http://www.autohotkey.com/forum/topic53775.html(PS: I hope that in this situation double posting is not frowned upon. I figured if I merely had edit my last post people that may have previously read it would not notice there was updated content, hence this additional post... not to mention it's been quite a few days.)
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