As the title of the question says, I'm trying to extract a specific icon layer from file then save it as ico file with transparency (as the source icon have).
There are many questions related to icon extraction, but this is specific to the following code that I'm applying with the usage of SHDefExtractIcon function.
The problem I have is that the colors of the generated .ico file are wrong, it generated a kind of half and horrible transparency, on the other side, the generated .png file is perfectlly saved.
This is the resulting PNG file:
This is the resulting ICO file:
Is this a limitation of Windows API, or I'm doing something wrong?.
C#:
[DllImport("Shell32.dll", SetLastError = false)]
public static extern int SHDefExtractIcon(string iconFile, int iconIndex, uint flags, ref IntPtr hiconLarge, ref IntPtr hiconSmall, uint iconSize);
IntPtr hiconLarge = default(IntPtr);
SHDefExtractIcon("C:\\file.exe", 0, 0, hiconLarge, null, 256);
// ToDO: Handle HRESULT.
Icon ico = Icon.FromHandle(hiconLarge);
Bitmap bmp = ico.ToBitmap();
// Save as .png with transparency. success.
bmp.Save("C:\\ico.png", ImageFormat.Png);
// 1st intent: Save as .ico with transparency. failure.
//' Transparency is ok but it generates a false icon, it's .png with modified extension to .ico.
bmp.Save("C:\\ico1.ico", ImageFormat.Icon);
// 2nd intent: Save as .ico with transparency. failure. Wrong transparency.
using (MemoryStream ms = new MemoryStream()) {
ico.Save(ms);
using (FileStream fs = new FileStream("C:\\ico2.ico", FileMode.CreateNew)) {
ms.WriteTo(fs);
}
// ToDO: Destroy hiconLarge here with DestroyIcon function.
}
VB.NET:
Imports System.Drawing.Imaging
Imports System.Runtime.InteropServices
<DllImport("Shell32.dll", SetLastError:=False)>
Public Shared Function SHDefExtractIcon(ByVal iconFile As String,
ByVal iconIndex As Integer,
ByVal flags As UInteger,
ByRef hiconLarge As IntPtr,
ByRef hiconSmall As IntPtr,
ByVal iconSize As UInteger
) As Integer
End Function
Dim hiconLarge As IntPtr
SHDefExtractIcon("C:\file.exe", 0, 0, hiconLarge, Nothing, 256)
' ToDO: Handle HRESULT.
Dim ico As Icon = Icon.FromHandle(hiconLarge)
Dim bmp As Bitmap = ico.ToBitmap()
' Save as .png with transparency. success.
bmp.Save("C:\ico.png", ImageFormat.Png)
' 1st intent: Save as .ico with transparency. failure.
' Transparency is ok but it generates a false icon, it's .png with modified extension to .ico.
bmp.Save("C:\ico1.ico", ImageFormat.Icon)
' 2nd intent: Save as .ico with transparency. failure. Wrong transparency.
Using ms As New MemoryStream
ico.Save(ms)
Using fs As New FileStream("C:\ico2.ico", FileMode.CreateNew)
ms.WriteTo(fs)
End Using
End Using
' ToDO: Destroy hiconLarge here with DestroyIcon function.
SHDefExtractIcon
API call isn't working? Also, could you elaborate on what you mean by 'failure' (a screenshot would be helpful). (Side Node: IfImage.Save
can't find a codec to use for its save, it uses png by default.) – theBico.Save(fs)
the Icon type knows how to save themselves to file. – Ňɏssa PøngjǣrdenlarpToBitmap
doesn't preserve transparency, more than likely your issue you are facing. – Trevor