本文介绍了从文件中提取特定的图标层,然后将其保存为透明.ico文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于问题的标题说,我试图提取文件中的特定图标层,然后将其保存为透明ICO文件(如源图标有)。



有许多人图标提取相关的问题,但这是具体到下面的代码,我是功能。



我的问题是,所生成的.ico文件的颜色是错误的,它产生一种半和可怕透明度的,在另一侧,所生成的.png文件perfectlly保存



这是生成的PNG文件:





这是生成的ICO文件:





这是由于Windows API的限制,或者说我做得不对

C#?

 函数[DllImport(Shell32.dll中,SetLastError = FALSE)] 
公共静态外部INT SHDefExtractIcon(字符串ICONFILE,诠释iconIndex,UINT标志,楼盘的IntPtr hiconLarge,裁判IntPtr的hiconSmall,UINT iconSize);

IntPtr的hiconLarge =默认(IntPtr的);
SHDefExtractIcon(C:\\file.exe,0,0,hiconLarge,空,256);
// TODO:处理HRESULT。

ICO图标= Icon.FromHandle(hiconLarge);
BMP位图= ico.ToBitmap();

//保存透明度.png格式。成功。
bmp.Save(C:\\ico.png,ImageFormat.Png);

//第一个目的:为.ICO保存与透明度。失败。
//'透明度是确定,但它会产生一个错误的图标,它与修改扩展.ICO .png格式。
bmp.Save(C:\\ico1.ico,ImageFormat.Icon);

//第2个目的:为.ICO保存与透明度。失败。错误的透明度。使用(MemoryStream的毫秒=新的MemoryStream())
{
ico.Save(毫秒);
使用(的FileStream FS =新的FileStream(C:\\ico2.ico,FileMode.CreateNew)){
ms.WriteTo(FS);
}
// TODO:用DestroyIcon函数摧毁这里hiconLarge。
}



VB.NET:



<的DllImport(Shell32.dll中,SetLastError:= FALSE)>
公共共享功能SHDefExtractIcon(BYVAL ICONFILE作为字符串,
BYVAL iconIndex整数,
BYVAL标志作为UInteger,
为ByRef hiconLarge作为IntPtr的,
为ByRef hiconSmall作为IntPtr的,
BYVAL iconSize作为UInteger
)作为整数
端功能


尺寸hiconLarge作为IntPtr的
SHDefExtractIcon(C:\file。 EXE,0,0,hiconLarge,没什么,256)
'TODO:处理HRESULT。

尺寸ICO为图标= Icon.FromHandle(hiconLarge)
昏暗的BMP位图作为= ico.ToBitmap()

'另存为巴纽透明度。成功。
bmp.Save(C:\ico.png,ImageFormat.Png)

'1的意图:除.ICO与透明度。失败。
'透明度是确定,但它会产生一个错误的图标,它与修改扩展.ICO .png格式。
bmp.Save(C:\ico1.ico,ImageFormat.Icon)

'第二个目的:保存为.ICO与透明度。失败。错误的透明度。
使用MS作为新的MemoryStream
ico.Save(MS)
使用FS作为新的FileStream(C:\ico2.ico,FileMode.CreateNew)
ms.WriteTo (FS)
端使用
端使用

'TODO:用DestroyIcon函数摧毁这里hiconLarge。


解决方案

您需要一个工具



究其原因,没有人能重现该问题是它需要一个精心制作的,艺术的图标。一个简单的图标将在ICO到磁盘图像就好了行程,保留透明度。我们不知道你做了什么,以获得低质量的图像 - 这是一个JPG这里,所以某处有一个图标JPG转换



所以,我去寻找用于图像显示。该 crapware发现谷歌对我来说似乎不一样,所以我下载JDownloader其中确实有图标匹配评论图片链接:





不仅是失去了透明度,这很糟糕一路周围,在资源管理器中的图像它的观点是一样糟糕。我们都知道一个ICO文件是可容纳多个图像的容器,但事实证明,的并没有高品质的编码器的详细/复杂的图像。



IconLib



我发现的C / C ++代码来管理/缠斗图标相当数量,但也有一个NET LIB来为你做这个。这里有关于这个主题的(非常)几个岗位,但他们似乎都链接,死链接或商业产品。但是,似乎做你想做的。在源代码来创建/画出图标看着简单地说,它看起来非常像C / C ++代码。



它可以用来做萃取(S)和图标保存到一个集合。我忽略了的部分,因为问题似乎只关心 SHDefExtractIcon 。这可能是过时的一点,你可能要重新编译净4.xxx;但它似乎写出高质量的图标。代码开始与 SHDefExtractIcon 图标,将其保存到文件,并显示文件版本:





昏暗的文件作为字符串=C:\Temp\electro crapware\JDownloader2.exe

昏暗hiconLarge作为IntPtr的
NativeMethods.SHDefExtractIcon(文件,0,0,hiconLarge,没什么,256)

尺寸ICO为图标= Icon.FromHandle(hiconLarge)
尺寸为BMP位图= ico.ToBitmap()
pbIcoA.Image = BMP

'版本为png
bmp.Save(C:\Temp\electro.png的imageformat。 PNG)

''简单NET ICO保存:不工作! (==低质量的图像)
'使用FS作为新的FileStream(C:\Temp\electro.ico,FileMode.OpenOrCreate)
'ico.Save(FS)
结束使用

''进口System.Drawing.IconLib
昏暗myIcons作为新MultiIcon()
昏暗SICO作为SingleIcon = myIcons.Add(电子)

'从PInvoked ico.ToBitmap创建图标()
'注意,仅枚举云涨到Vista
sIco.CreateFrom(BMP,IconOutputFormat.Vista)
SICO .Save(C:\Temp\electro2.ico)

'现在可以显示从磁盘ICO $ b $图像b昏暗bmpX作为位图
使用icob作为新图标( C:\Temp\electro2.ico)
bmpX = icob.ToBitmap
端使用
pbIcoB.Image = bmpX

'TODO:处置

结果:





您也许可以在婴儿床 SingleIcon.CreateFrom 保存方法来创建自己的版本和或者到位的PInvoke使用它。我会喜欢,因为这样的背景下看起来像是来自超过透明度损失遭受进行测试蛇/蠕虫形象。






资源





的在CodeProject


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:

<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.
解决方案

You need a tool

The reason no one could reproduce the problem is that it requires an elaborate, artistic icon. A simple icon will make the trip from ico to disk to image just fine and preserve transparency. We also do not know what you did to get the poor quality image - it is a JPG here so somewhere there is an Icon to JPG transform.

So, I went looking for the image shown. The Plixia crapware Google found for me seems not to be the same, so I downloaded JDownloader which did have an icon matching an image link in comments:

Not only is the transparency lost, it looks bad all way around and the Image view of it in Explorer is just as bad. We all know an ICO file is a container which can hold a number of images, but as it turns out, Icons are complex critters and there is no high quality encoder for detailed/complex images.

IconLib

I found a fair amount of C/C++ code to manage/wrangle icons, but there is also a NET lib to do this for you. There are a (very) few posts here on this topic, but they all seem link to dead links or commercial products. However, IconLib from CodeProject seems to do what you want. Looking briefly at the source code to create/draw the icon, it looks very much like that C/C++ code.

It can be used to do the extraction(s) and save icons to a collection. I ignored that part since the question seems interested only in SHDefExtractIcon. It might be a little out of date and you may want to recompile it for NET 4.xxx; but it does seem to write out a high quality icon. Code to start with an icon from SHDefExtractIcon, save it to file and show the file version:

Dim file As String = "C:\Temp\electro crapware\JDownloader2.exe"

Dim hiconLarge As IntPtr
NativeMethods.SHDefExtractIcon(file, 0, 0, hiconLarge, Nothing, 256)

Dim ico As Icon = Icon.FromHandle(hiconLarge)
Dim bmp As Bitmap = ico.ToBitmap()
pbIcoA.Image = bmp

' png version
bmp.Save("C:\Temp\electro.png", ImageFormat.Png)

'' simple NET ico save: Doesnt Work! (== low quality image)
'Using fs As New FileStream("C:\Temp\electro.ico", FileMode.OpenOrCreate)
'    ico.Save(fs)
'End Using

'' Imports System.Drawing.IconLib
Dim myIcons As New MultiIcon()
Dim sIco As SingleIcon = myIcons.Add("electro")

' create Icon from the PInvoked ico.ToBitmap()
' note that enum only goes "up" to Vista
sIco.CreateFrom(bmp, IconOutputFormat.Vista)
sIco.Save("C:\Temp\electro2.ico")

' now display image from disk ico
Dim bmpX As Bitmap
Using icob As New Icon("C:\Temp\electro2.ico")
    bmpX = icob.ToBitmap
End Using
pbIcoB.Image = bmpX

' ToDo: Dispose

Results:

You could probably crib the SingleIcon.CreateFrom and Save methods to create your own versions and or maybe use it in place of PInvoke. I would have loved to test it on the snake/worm image because that background looks like it suffers from more than a loss of transparency.


Resources

Icons on MSDN

IconLib on CodeProject

这篇关于从文件中提取特定的图标层,然后将其保存为透明.ico文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 22:53