ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 199|回复: 0

[分享] 给大家分享一段将多个PNG合并为1个ICO文件的C#代码

[复制链接]

TA的精华主题

TA的得分主题

发表于 2024-6-19 11:29 | 显示全部楼层 |阅读模式
最近找到了画图标的免费软件,挺好用的,不过输出来的都是PNG文件,VS里面指定窗体图标都是ICO比较方便,另外,ICO还方便在不同大小显示不同的分辨率的图标。所以我就打算将多个分辨率的PNG转为ICO使用,在网上找了一圈,在线转的多数只能将单个PNG转为ICO,免费软件下载下来大多提示有病毒,Windows安全中心就给我干掉了,唯一能用的IconWorkshop是收费软件,我只是试用期用了一下,我现在懒得折腾,也懒得去找破解,就想着去Github上找找哪个大神会写个这个小程序,又不是编辑,只是合并一下而已。我也看了一下ICO的结构,大致明白了多个PNG是怎么存储,于是在GitHub网上找到了一段符合要求的代码(该代码的大神重写了很多库,所以他的代码多数方法用自己的库,如果我只截取他这一段是没法用的,要不然就用他整个库,我不想因为一小段挂一大堆不需要的,因此自己修改简化了一下,就可以用了)。代码如下,一个静态类IconFactory,一个静态方法Save,输入一个Image集合,给定一个ICO文件地址即可。

  1. using System.Collections.Generic;
  2.     using System.Drawing;
  3.     using System.IO;
  4.     using System.Linq;

  5.     /// <summary>
  6.     ///     Provides functions for handling the 'image/vnd.microsoft.icon' file format.
  7.     /// </summary>
  8.     public static class IconFactory
  9.     {
  10.         private const int SizeIconDir = 6;
  11.         private const int SizeIconDirEntry = 16;

  12.         /// <summary>
  13.         ///     Saves the specified sequence of <see cref="Image"/>'s as a single icon into
  14.         ///     the output stream.
  15.         /// </summary>
  16.         public static void Save(IEnumerable<Image> images, string path)
  17.         {
  18.             using Stream stream = new FileStream(path, FileMode.Create);
  19.             Image[] array = images.OrderByDescending(x => x.Width).ThenByDescending(x => x.Height).ToArray();
  20.             var bw = new BinaryWriter(stream);
  21.             try
  22.             {
  23.                 bw.Write((ushort)0);
  24.                 bw.Write((ushort)1);
  25.                 bw.Write((ushort)array.Length);
  26.                 Dictionary<uint, byte[]> buffers = new();
  27.                 uint offset = (uint)(6 + SizeIconDir + SizeIconDirEntry * array.Length);
  28.                 foreach (var image in array)
  29.                 {
  30.                     byte[] buffer = CreateBuffer(image);
  31.                     byte imageWidth = (byte)image.Width;
  32.                     byte imageHeight = (byte)image.Height;
  33.                     int pixelFormat = Image.GetPixelFormatSize(image.PixelFormat);
  34.                     bw.Write(imageWidth);
  35.                     bw.Write(imageHeight);
  36.                     bw.Write((byte)0);
  37.                     bw.Write((byte)0);
  38.                     bw.Write((ushort)1);
  39.                     bw.Write((ushort)pixelFormat);
  40.                     bw.Write((uint)buffer.Length);
  41.                     bw.Write(offset);
  42.                     buffers.Add(offset, buffer);
  43.                     offset += (uint)buffer.Length;
  44.                 }
  45.                 foreach (var buffer in buffers)
  46.                 {
  47.                     bw.BaseStream.Seek(buffer.Key, SeekOrigin.Begin);
  48.                     bw.Write(buffer.Value);
  49.                 }
  50.                 bw.Close();
  51.                 stream.Close();
  52.             }
  53.             finally
  54.             {
  55.                 foreach (var image in array)
  56.                     image.Dispose();
  57.                 bw.Dispose();
  58.             }
  59.         }

  60.         private static byte[] CreateBuffer(Image image)
  61.         {
  62.             using var ms = new MemoryStream();
  63.             image.Save(ms, image.RawFormat);
  64.             return ms.ToArray();
  65.         }
  66.     }
复制代码
自己套个UI,搞搞输入输出就好了。
我自己简单套了一下(UI太简陋,临时产品,就不分享了),但验证了上述代码可以使用。
需要注意的是,ICO文件一般存放正方形的,像素为8,16,24,32...最大到256的PNG图形,好像ICO最多存的图形个数也有限制,8个?,我这个代码没有做这方面的校验,因为是自己用,不是开放给用户,你自己要注意输入输出合法,不然允许会出错。

您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-9-8 09:12 , Processed in 0.037863 second(s), 9 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表