C#生成多尺寸bmp格式ICO图标代码

news/2025/2/15 15:54:13/文章来源:https://www.cnblogs.com/MingKongLing/p/18717069

代码取自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的效果显示

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/884287.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CTA:回测执行引擎BacktestingEngine

回测执行引擎BacktestingEngine 回顾前面的文章CTA:回测综述,那里提到,真正执行回测的逻辑,写在BacktestingEngine中。 代码解读 BacktestingEngine定义在vnpy_ctastrategy -> backtesting.py中。 package from collections import defaultdict from datetime import da…

CTA:回测快速示例

设置工作目录 VNPY程序启动后,会产生一个工作目录,程序运行产生的数据、系统配置都会放在指定的.vntrader目录当中。 这一设置在vnpy -> utility.py -> _get_trader_dir函数中可以找到,工作目录由TRADER_DIR, TEMP_DIR确定。 def _get_trader_dir(temp_name: str) -&g…

VNPY体系结构

整体架构每个层次的模块只调用下层功能,并对上层提供接口。接口层负责对接行情和交易API,将行情数据推送到系统,发送交易指令。 引擎层向下对接交易接口、数据库,向上服务于各种上层应用。 应用层主要是面向用户的可视化界面,这一部分的代码主要为引擎功能与界面的连接。功…

【ABP】项目示例(2)——聚合根和实体

聚合根和实体 在上一章节中,已经完成了项目搭建的前置准备,在这一章节中,实现领域层的聚合根和实体 创建名称为General.Backend.Domain的标准类库,分别新建名称为Entities、Services、IRepositories和Specifications的文件夹,用于存放实体和聚合根、领域服务、仓储接口和规…

P1896 [SCOI2005] 互不侵犯(状态压缩)

位运算符好麻烦,没打括号被卡了半天 #include<iostream> #define int long long using namespace std; int f[12][100][1<<11]; int s[1<<11]; int num[1<<11]; signed main(){int n,k;cin>>n>>k;int cnt=0;for(int i=0;i<(1<<…

200N03-ASEMI豆浆机专用MOS管200N03

200N03-ASEMI豆浆机专用MOS管200N03编辑:ll 200N03-ASEMI豆浆机专用MOS管200N03 型号:200N03 品牌:ASEMI 封装:TO-252 批号:最新 最大漏源电流:200A 漏源击穿电压:30V RDS(ON)Max:1.8mΩ 引脚数量:3 芯片个数: 沟道类型:N沟道MOS管、中低压MOS管 漏电流:ua 特性:…

第七章-收益归因:Brinson模型

例子 现有一个投资组合,其基准组合为:70%中证800,20%债券,10%现金,如下:基金经理主动投资,对资产权重进行调整。假设基准组合收益率为\(r\)。若是看好股票,那就多配置一些股票,调整中证800权重为\(w_1^{\prime}\)。则收益调整为(\(w_1^{\prime}-w)(r_1-r)\)。会有两种情…

我用GPT干什么

有几天没有更新文章了,一方面因为感觉GPT出来了,写什么都不香了,非得写点关于GPT的才有资格出来和大家见面;另一方面,确实最近一段时间也在全面拥抱GPT:学习,总结,思考。所以今天就想随心所欲地说说GPT使用感受。其实GPT出来没多长时间,就注册账号,并体验了网页版,更…

金融期权

金融期权品种一览上海证券交易所品种 行权方式 上市日期华夏上证50ETF期权 欧式 2015-02-09华泰沪深300ETF期权 欧式 2019-12-23南方中证500ETF期权 欧式 2022-09-19华夏上证科创板50ETF期权 欧式 2023-06-05易方达上证科创板50ETF期权 欧式 2023-06-05深圳证券交易所品种 行权…

从ClickHouse中流式查询大数据

提示:本篇不适合手机阅读,主要为了提供代码实现。为了减速少大的Excel文件在内存中驻留,使用流的方式,边查询边组装,边下载文件相对来说是一个好的方式,下面是基于ClickHouse数据源的方式,下载100万条记录的处理方式,本地测试,内存只有100多M的使用,下载完后就会释放…

Axure9下载完美汉化及破解

一)Axure9下载 复制链接到浏览器,复制后需删除作者后面的部份才能打开!Windows系统: https://pan.baidu.com/s/1CF-lpmzzaevUX2lCZUmmiAMac新系统(M芯片) https://pan.baidu.com/s/1k73IJBAdlwUL1YPPRWXchA 提取码: 1323 注:M1版本自带破解,仅需汉化即可Mac旧系统(int…