PowerShell PNG 转 ICO

PowerShell PNG 转 ICO
狂犬主子使用 PowerShell 将 PNG 文件转换为 ICO 文件有多种方法,但是都不太方便,且不易理解。鉴于我们现在的操作系统版本大多已经在 Windows Vista 以上,无需考虑以前的 BMP 多分辨率多位数模式,可以直接使用 PNG 加上头信息构造出 ICO 文件。这样就可以非常方便的将 PNG 转换为 ICO,同时可以无损保留 PNG。
结构
这里我们不引入任何依赖,手动合成,因此首先需要了解一下 ICO 文件的结构。
参考:
简言之,ICO 格式由头文件和图片数据组成,其中头文件的十六进制数据结构如下:
1 | # ICONDIR 0x00 - 0x06 : 0x06 00 00 # 保留 01 00 # 图像类型,ico 为 1 01 00 # 图像数量,1 张 # ICONDIRENTRY 如有多张,每张图像来一个 0x06 - 0x16 : 0x10 (16 bytes) 00 # 宽度 00 # 高度 00 # 颜色,大于8bpp为0(无调色板) 00 # 保留 01 00 # 颜色平面 20 00 # 每像素位数(32bpp) 6F 48 00 00 # 图像文件大小(需要修改) 0x0e - 0x12 : 0x04 16 00 00 00 # 图像数据偏移量 # 总共: 22 bytes |
ICO 格式的字节序为 Little-Endian(如上方的 6F 48 00 00
为从右往左读作 48 6F
),Windows 下默认表现为 LE,通常编写 PowerShell 时无需在意这个问题,自动生成出来就是 LE 的。
由于我们只有一张图,且图片为 PNG 格式,因此我们只需要修改 ICONDIRENTRY
中的图像文件大小即可。
代码
1 | function Convert-PngToIco { param ( [string]$PngPath, [string]$IcoPath ) # 读取文件 $png = [System.IO.File]::ReadAllBytes($pngPath) # 生成头信息 $ico = [System.IO.MemoryStream]::new() $bin = [System.IO.BinaryWriter]::new($ico) # 写入ICONDIR结构 $bin.Write([uint16]0) # 保留 $bin.Write([uint16]1) # 图像类型,ico 为 1 $bin.Write([uint16]1) # 图像数量,1 张 # 写入ICONDIRENTRY结构 $bin.Write([sbyte]0) # 宽度 $bin.Write([sbyte]0) # 高度 $bin.Write([sbyte]0) # 颜色 $bin.Write([sbyte]0) # 保留 $bin.Write([uint16]1) # 颜色平面 $bin.Write([uint16]32) # 每像素位数(32bpp) $bin.Write([uint32]$png.Length) # 图像文件大小 $bin.Write([uint32]22) # 图像数据偏移量 # 写入图像数据 $bin.Write($png) [System.IO.File]::WriteAllBytes($icoPath, $ico.ToArray()) # 清理资源 $bin.Dispose() $ico.Dispose() } # 使用示例 $pngPath = ".\image.png" $icoPath = ".\image.ico" Convert-PngToIco -PngPath $pngPath -IcoPath $icoPath |
技巧
PNG 图片可以先使用 TinyPNG 压缩,这样制作出来的图标体积更小。
评论
匿名评论隐私政策
✅ 你无需删除空行,直接评论以获取最佳展示效果