|
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件 ★ 免费下载 ★ ★ 使用帮助★
最近找到了画图标的免费软件,挺好用的,不过输出来的都是PNG文件,VS里面指定窗体图标都是ICO比较方便,另外,ICO还方便在不同大小显示不同的分辨率的图标。所以我就打算将多个分辨率的PNG转为ICO使用,在网上找了一圈,在线转的多数只能将单个PNG转为ICO,免费软件下载下来大多提示有病毒,Windows安全中心就给我干掉了,唯一能用的IconWorkshop是收费软件,我只是试用期用了一下,我现在懒得折腾,也懒得去找破解,就想着去Github上找找哪个大神会写个这个小程序,又不是编辑,只是合并一下而已。我也看了一下ICO的结构,大致明白了多个PNG是怎么存储,于是在GitHub网上找到了一段符合要求的代码(该代码的大神重写了很多库,所以他的代码多数方法用自己的库,如果我只截取他这一段是没法用的,要不然就用他整个库,我不想因为一小段挂一大堆不需要的,因此自己修改简化了一下,就可以用了)。代码如下,一个静态类IconFactory,一个静态方法Save,输入一个Image集合,给定一个ICO文件地址即可。
- using System.Collections.Generic;
- using System.Drawing;
- using System.IO;
- using System.Linq;
- /// <summary>
- /// Provides functions for handling the 'image/vnd.microsoft.icon' file format.
- /// </summary>
- public static class IconFactory
- {
- private const int SizeIconDir = 6;
- private const int SizeIconDirEntry = 16;
- /// <summary>
- /// Saves the specified sequence of <see cref="Image"/>'s as a single icon into
- /// the output stream.
- /// </summary>
- public static void Save(IEnumerable<Image> images, string path)
- {
- using Stream stream = new FileStream(path, FileMode.Create);
- Image[] array = images.OrderByDescending(x => x.Width).ThenByDescending(x => x.Height).ToArray();
- var bw = new BinaryWriter(stream);
- try
- {
- bw.Write((ushort)0);
- bw.Write((ushort)1);
- bw.Write((ushort)array.Length);
- Dictionary<uint, byte[]> buffers = new();
- uint offset = (uint)(6 + SizeIconDir + SizeIconDirEntry * array.Length);
- foreach (var image in array)
- {
- byte[] buffer = CreateBuffer(image);
- byte imageWidth = (byte)image.Width;
- byte imageHeight = (byte)image.Height;
- int pixelFormat = Image.GetPixelFormatSize(image.PixelFormat);
- bw.Write(imageWidth);
- bw.Write(imageHeight);
- bw.Write((byte)0);
- bw.Write((byte)0);
- bw.Write((ushort)1);
- bw.Write((ushort)pixelFormat);
- bw.Write((uint)buffer.Length);
- bw.Write(offset);
- buffers.Add(offset, buffer);
- offset += (uint)buffer.Length;
- }
- foreach (var buffer in buffers)
- {
- bw.BaseStream.Seek(buffer.Key, SeekOrigin.Begin);
- bw.Write(buffer.Value);
- }
- bw.Close();
- stream.Close();
- }
- finally
- {
- foreach (var image in array)
- image.Dispose();
- bw.Dispose();
- }
- }
- private static byte[] CreateBuffer(Image image)
- {
- using var ms = new MemoryStream();
- image.Save(ms, image.RawFormat);
- return ms.ToArray();
- }
- }
复制代码 自己套个UI,搞搞输入输出就好了。
我自己简单套了一下(UI太简陋,临时产品,就不分享了),但验证了上述代码可以使用。
需要注意的是,ICO文件一般存放正方形的,像素为8,16,24,32...最大到256的PNG图形,好像ICO最多存的图形个数也有限制,8个?,我这个代码没有做这方面的校验,因为是自己用,不是开放给用户,你自己要注意输入输出合法,不然允许会出错。
|
|