将图标转换为Png

问题描述 投票:1回答:2

我正在使用以下代码(基于我在另一个答案中找到的内容)将图像(通常是添加到项目资源中的PNG)转换为图标,以用于表单标题等。

public static Icon IconFromImage(Image img)
{
    using (var bmp = new Bitmap(img))
    {
        Byte[] ba;
        using (var ms = new MemoryStream())
        {
            bmp.Save(ms, ImageFormat.Png);
            ms.Seek(0, SeekOrigin.Begin);
            ba = ms.ToArray();
        }

        using (var imgData = new MemoryStream())
        using (var writer = new BinaryWriter(imgData))
        {
            if (writer != null)
            {
                //Header (6 bytes)
                writer.Write((Byte)0);              // 0 reserved: set to 0
                writer.Write((Byte)0);              // 1 reserved: set to 0
                writer.Write((Int16)1);             // 2-3 image type: 1 = icon, 2 = cursor
                writer.Write((Int16)1);             // 4-5 number of images

                //Image entry #1 (16 bytes)
                writer.Write((Byte)bmp.Width);      // 0 image width
                writer.Write((Byte)bmp.Height);     // 1 image height
                writer.Write((Byte)0);              // 2 number of colors
                writer.Write((Byte)0);              // 3 reserved
                writer.Write((Int16)0);             // 4-5 color planes
                writer.Write((Int16)32);            // 6-7 bits per pixel
                writer.Write(ba.Length);            // 8-11 size of image data
                writer.Write(6 + 16);               // 12-15 offset to image data

                //Write image data
                writer.Write(ba);                   // PNG data must contain the whole PNG data file!

                writer.Flush();
                writer.Seek(0, SeekOrigin.Begin);

                return new Icon(imgData,16,16);
            }
        }
    }
    return null;
}

[从图像到图标,效果很好。但是在某些情况下,我需要获取该表单的标题图标并从中获取图像。当我使用实际的基于文件的ICO文件作为标题图像时,这种方法可以正常工作,但是现在我使用转换代码来获取表单的图标,因此生成的PNG看起来很恐怖。

表单标题图标:

enter image description here

使用Bitmap.FromHicon(new Icon(theForm.Icon, new Size(16, 16)).Handle)渲染的图像:(注意:以前使用theForm.Icon.ToBitmap(),但现在会出错)

enter image description here

[我在另一篇文章中读到一篇评论,其中用户说如果使用PNG派生图标,那么返回图像将是不好的,因为“ PNG具有不止一个透明度”。如果这是我遇到的问题,那么该怎么办?

c# .net image winforms gdi+
2个回答
1
投票

您可以使用IconBitmapDecoder获取保留像素格式的图标流,而使用PngBitmapEncoder将该流保存在png图像中:

using System.Drawing;
using System.Windows.Media.Imaging;
class IconHelper
{
    public static Bitmap PngFromIcon(Icon icon)
    {
        Bitmap png = null;
        using (var iconStream = new System.IO.MemoryStream())
        {
            icon.Save(iconStream);
            var decoder = new IconBitmapDecoder(iconStream,
                BitmapCreateOptions.PreservePixelFormat,
                BitmapCacheOption.None);

            using (var pngSteam = new System.IO.MemoryStream())
            {
                var encoder = new PngBitmapEncoder();
                encoder.Frames.Add(decoder.Frames[0]);
                encoder.Save(pngSteam);
                png = (Bitmap)Bitmap.FromStream(pngSteam);
            }
        }
        return png;
    }
}

要使用这些类,您需要添加对PresentationCoreWindowsBaseSystem.Xaml的引用。那么用法将是:

this.pictureBox1.Image = IconHelper.PngFromIcon(this.Icon);

并且结果与您用来创建图标的原始png相同。


0
投票

尝试Bitmap.FromHicon(this.Icon.Handle),您可能会获得更好的结果。如果png有压缩,至少ToBitmap()似乎会阻塞:Displaying an icon in a pictureboxhttp://community.sharpdevelop.net/forums/t/21851.aspx

© www.soinside.com 2019 - 2024. All rights reserved.