代码取自deepseek,且已经过本地执行测试
//.cs 文件类型,便于外部编辑时使用
// 引用必要的命名空间
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;// Quicker将会调用的函数。可以根据需要修改返回值类型。
public static void Exec(Quicker.Public.IStepContext context)
{//var oldValue = context.GetVarValue("varName"); // 读取动作里的变量值//MessageBox.Show(oldValue as string);//context.SetVarValue("varName", "从脚本输出的内容。"); // 向变量里输出值//MessageBox.Show("Hello World!");List<string> Paths = new List<string> { @"D:\SoftwareCache\Microsoft VS Code\图标\合成\16X16.png",@"D:\SoftwareCache\Microsoft VS Code\图标\合成\32X32.png",@"D:\SoftwareCache\Microsoft VS Code\图标\合成\48X48.png"};IcoConverter.SaveAsLegacyIco(Paths,@"D:\SoftwareCache\Microsoft VS Code\图标\合成\test.ico");
}
//bmp格式写入
public static class IcoConverter
{// ICO文件头结构 [[2]][StructLayout(LayoutKind.Sequential)]private struct IconDir{public ushort Reserved;public ushort Type;public ushort Count;}// ICO目录项结构 [[2]][StructLayout(LayoutKind.Sequential, Pack = 1)]private struct IconDirEntry{public byte Width;public byte Height;public byte ColorCount;public byte Reserved;public ushort Planes;public ushort BitCount;public uint BytesInRes;public uint ImageOffset;}/// <summary>/// 将多个BMP合并为多帧ICO文件/// </summary>public static void SaveAsLegacyIco(IEnumerable<string> bitmapPaths, string outputPath){var entries = new List<IconDirEntry>();var imageDataList = new List<byte[]>();uint currentOffset = 6 + (uint)(16 * bitmapPaths.Count()); // 头部长度 [[2]]// 生成所有图标的BMP数据foreach (string bmpPath in bitmapPaths){ using (Bitmap bmp = new Bitmap(bmpPath)) //保证使用后即释放资源{var data = GetBitmapData(bmp);var entry = new IconDirEntry{Width = (byte)(bmp.Width >= 256 ? 0 : bmp.Width),Height = (byte)(bmp.Height >= 256 ? 0 : bmp.Height),ColorCount = 0,Planes = 1,BitCount = 32,BytesInRes = (uint)data.Length,ImageOffset = currentOffset};entries.Add(entry);imageDataList.Add(data);currentOffset += (uint)data.Length;}}// 写入文件using (var fs = new FileStream(outputPath, FileMode.Create))using (var writer = new BinaryWriter(fs)){// 写入ICO头部 [[2]]writer.Write((ushort)0); // Reservedwriter.Write((ushort)1); // Type=ICOwriter.Write((ushort)entries.Count); // Image count// 写入目录项foreach (var entry in entries){writer.Write(entry.Width);writer.Write(entry.Height);writer.Write(entry.ColorCount);writer.Write(entry.Reserved);writer.Write(entry.Planes);writer.Write(entry.BitCount);writer.Write(entry.BytesInRes);writer.Write(entry.ImageOffset);}// 写入图像数据 [[11]]foreach (var data in imageDataList){writer.Write(data);}}}/// <summary>/// 将Bitmap转为ICO兼容的BMP格式数据/// </summary>private static byte[] GetBitmapData(Bitmap bmp){var formattedBmp = new Bitmap(bmp.Width, bmp.Height, PixelFormat.Format32bppArgb);using (var g = Graphics.FromImage(formattedBmp)){g.DrawImage(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height));}var bmpData = formattedBmp.LockBits(new Rectangle(0, 0, formattedBmp.Width, formattedBmp.Height),ImageLockMode.ReadOnly,formattedBmp.PixelFormat);try{int width = bmp.Width;int height = bmp.Height;int stride = bmpData.Stride;// BMP信息头var infoHeader = new byte[40];using (var ms = new MemoryStream(infoHeader))using (var writer = new BinaryWriter(ms)){writer.Write(40); // 信息头大小writer.Write(width); // 宽度writer.Write(height * 2); // 高度(颜色+掩码)writer.Write((ushort)1); // 位面数writer.Write((ushort)32); // 位深writer.Write(0); // 压缩方式(无压缩)writer.Write(stride * height + ((width + 31) / 32 * 4) * height); // 图像数据大小writer.Write(0); // 水平分辨率writer.Write(0); // 垂直分辨率writer.Write(0); // 调色板颜色数writer.Write(0); // 重要颜色数}// 计算掩码参数int maskStride = (width + 31) / 32 * 4;int maskDataSize = maskStride * height;int colorDataSize = stride * height;var buffer = new byte[infoHeader.Length + colorDataSize + maskDataSize];// 复制信息头Buffer.BlockCopy(infoHeader, 0, buffer, 0, infoHeader.Length);// 复制颜色数据(逆序行)byte[] colorData = new byte[colorDataSize];Marshal.Copy(bmpData.Scan0, colorData, 0, colorDataSize);int colorOffset = infoHeader.Length;for (int y = 0; y < height; y++){int srcIndex = y * stride;int destIndex = colorOffset + (height - 1 - y) * stride;Buffer.BlockCopy(colorData, srcIndex, buffer, destIndex, stride);}// 生成并复制掩码数据byte[] maskData = GenerateMaskData(colorData, width, height, stride, maskStride);Buffer.BlockCopy(maskData, 0, buffer, infoHeader.Length + colorDataSize, maskDataSize);return buffer;}finally{formattedBmp.UnlockBits(bmpData);formattedBmp.Dispose();}}/// <summary>/// 生成AND掩码位图(1位/像素)/// </summary>private static byte[] GenerateMaskData(byte[] colorData, int width, int height, int colorStride, int maskStride){byte[] maskData = new byte[maskStride * height];for (int y = 0; y < height; y++){int srcY = y; // 原图的行 byte[] maskRow = new byte[maskStride];int bitPos = 7;int byteIndex = 0;for (int x = 0; x < width; x++){int pixelIndex = srcY * colorStride + x * 4;byte alpha = colorData[pixelIndex + 3]; // Alpha通道if (alpha == 0)maskRow[byteIndex] |= (byte)(1 << bitPos);if (--bitPos < 0){bitPos = 7;byteIndex++;}}// 掩码行逆序存储int destY = height - 1 - y;Buffer.BlockCopy(maskRow, 0, maskData, destY * maskStride, maskStride);}return maskData;}
}
生成的ICO在VS的效果显示