Web开发:使用C#的System.Drawing.Common将png图片转化为icon图片

1.安装第三方库

我的是.NET6,因此需要安装8.0.0版本的【System.Drawing.Common】,若版本太高会在.NET6平台跑不了

2.代码

cs 复制代码
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

namespace PngToIcoConverter
{
    class Program
    {
        static void Main(string[] args)
        {
            // 你的PNG和ICO文件路径
            string pngFilePath = @"F:\C_program\MSSQLBackUpTools\WinFormsApp1\WinFormsApp1\pics\backup.png";
            string icoOutputPath = @"F:\C_program\MSSQLBackUpTools\WinFormsApp1\WinFormsApp1\pics\backup.ico";

            try
            {
                // 调用转换方法
                ConvertPngToIco(pngFilePath, icoOutputPath);
                Console.WriteLine("PNG转换为ICO成功!");
            }
            catch (FileNotFoundException ex)
            {
                Console.WriteLine($"错误:找不到文件 - {ex.Message}");
            }
            catch (IOException ex)
            {
                Console.WriteLine($"文件操作错误:{ex.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"转换失败:{ex.Message}");
            }
        }

        /// <summary>
        /// 将PNG图片转换为ICO图标(包含多尺寸:16x16, 32x32, 48x48)
        /// </summary>
        /// <param name="pngPath">PNG文件路径</param>
        /// <param name="icoPath">ICO输出路径</param>
        public static void ConvertPngToIco(string pngPath, string icoPath)
        {
            // 验证输入文件是否存在
            if (!File.Exists(pngPath))
            {
                throw new FileNotFoundException("PNG源文件不存在", pngPath);
            }

            // 读取PNG图片
            using (Bitmap pngBitmap = new Bitmap(pngPath))
            {
                // 定义ICO需要的256尺寸
                int[] icoSizes = new[] { 256 };
                using (MemoryStream ms = new MemoryStream())
                {
                    // 创建ICO文件的编码器
                    IconEncoder encoder = new IconEncoder();
                    foreach (int size in icoSizes)
                    {
                        // 缩放图片到指定尺寸(保持比例)
                        using (Bitmap sizedBitmap = ResizeBitmap(pngBitmap, size, size))
                        {
                            encoder.AddFrame(sizedBitmap);
                        }
                    }
                    // 将ICO数据写入文件
                    encoder.Save(ms);
                    File.WriteAllBytes(icoPath, ms.ToArray());
                }
            }
        }

        /// <summary>
        /// 缩放Bitmap到指定尺寸(保持宽高比,居中裁剪)
        /// </summary>
        private static Bitmap ResizeBitmap(Bitmap original, int width, int height)
        {
            Bitmap resized = new Bitmap(width, height);
            using (Graphics g = Graphics.FromImage(resized))
            {
                // 高质量缩放设置
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
                g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;

                // 计算居中绘制的位置
                float scale = Math.Max((float)width / original.Width, (float)height / original.Height);
                int newWidth = (int)(original.Width * scale);
                int newHeight = (int)(original.Height * scale);
                int x = (width - newWidth) / 2;
                int y = (height - newHeight) / 2;

                g.Clear(Color.Transparent); // 保留透明背景
                g.DrawImage(original, x, y, newWidth, newHeight);
            }
            return resized;
        }
    }

    // 辅助类:用于生成多尺寸ICO文件
    public class IconEncoder : IDisposable
    {
        private MemoryStream _stream = new MemoryStream();
        private BinaryWriter _writer;
        private int _imageCount = 0;
        private List<byte[]> _imageData = new List<byte[]>();

        public IconEncoder()
        {
            _writer = new BinaryWriter(_stream);
        }

        public void AddFrame(Bitmap bitmap)
        {
            if (bitmap.Width > 256 || bitmap.Height > 256)
                throw new ArgumentException("图标尺寸不能超过256x256");

            _imageCount++;
            using (MemoryStream ms = new MemoryStream())
            {
                bitmap.Save(ms, ImageFormat.Png);
                _imageData.Add(ms.ToArray());
            }
        }

        public void Save(Stream stream)
        {
            // 写入ICO文件头
            _writer.Write((short)0); // 保留
            _writer.Write((short)1); // ICO类型
            _writer.Write((short)_imageCount); // 图像数量

            long offset = 6 + 16 * _imageCount;
            for (int i = 0; i < _imageCount; i++)
            {
                byte[] data = _imageData[i];
                int width = data.Length > 0 ? new Bitmap(new MemoryStream(data)).Width : 0;
                int height = data.Length > 0 ? new Bitmap(new MemoryStream(data)).Height : 0;

                _writer.Write((byte)(width == 256 ? 0 : width));
                _writer.Write((byte)(height == 256 ? 0 : height));
                _writer.Write((byte)0); // 颜色数(0表示真彩色)
                _writer.Write((byte)0); // 保留
                _writer.Write((short)1); // 调色板
                _writer.Write((short)32); // 位深度
                _writer.Write(data.Length); // 图像数据大小
                _writer.Write((int)offset); // 图像数据偏移量
                offset += data.Length;
            }

            foreach (byte[] data in _imageData)
            {
                _writer.Write(data);
            }

            _stream.Seek(0, SeekOrigin.Begin);
            _stream.CopyTo(stream);
        }

        public void Dispose()
        {
            _writer?.Dispose();
            _stream?.Dispose();
        }
    }
}

3.Winform嵌入Icon

相关推荐
EasyGBS几秒前
从接入到稳定播放:无插件直播H5视频流媒体播放器EasyPlayer.js如何撑起Web端流媒体
开发语言·前端·javascript
FfHUCisI2 分钟前
GMP 调度器:Go 并发的心脏是如何跳动的
开发语言·golang·php
Java小白笔记9 分钟前
Java 实现阿里云 OSS 文件上传链路:普通上传、秒传、分片与断点续传
java·开发语言·数据库·spring·阿里云
传奇开心果编程11 分钟前
【Rust入门知识点学与练】第9课:Vec 动态数组
开发语言·学习·rust
卢锡荣14 分钟前
单芯掌控多口互联|乐得瑞 LDR6020 PD3.1 多通道 Type‑C 控制 SOC 芯片
c语言·开发语言
2333!!!!!14 分钟前
rocket新手一些常见问题
java·开发语言
yume_sibai16 分钟前
02-Rust 所有权与借用深入解析(底层原理 + 借用检查器 + 生命周期 + 内部可变性)
开发语言·后端·rust
xxwxx__18 分钟前
深入理解 C++ STL:stack、queue 与 deque 从使用到底层实现全解析
开发语言·c++·算法
Highcharts.js19 分钟前
甘特图纵向任务、横向时间显示图表可视化开发|Highcharts甘特图示例
开发语言·前端·javascript·可视化·甘特图·数据可视化·highcharts
郝学胜-神的一滴27 分钟前
C++11 工程级应用 08:Lambda表达式与Tuple元组
开发语言·jvm·c++·python·程序人生·开源