WPF中是否有IconBitmapEncoder?

3

我正在使用BitmapEncoder在WPF中创建各种格式的图像。例如,要从FrameworkElement创建png图像,我使用以下代码:

        BitmapEncoder imgEncoder = new PngBitmapEncoder();
        RenderTargetBitmap renderBitmap = new RenderTargetBitmap(32, 32, 96d, 96d, PixelFormats.Pbgra32);
        renderBitmap.Render(controlToConvert);
        imgEncoder.Frames.Add(BitmapFrame.Create(renderBitmap));

我想以相同的方式创建一个.ico文件,但是我在WPF中找不到任何IconBitmapEncoder。还有其他的方法吗?
问候,
Jawahar
4个回答

2

这里没有。

我曾经尝试过将图像保存为*.ico格式,但其他.NET类并没有真正帮助我(如果我没记错的话,它们只能解码而不能编码;但也许是我做错了什么)。*.ico可以作为PNG图像的容器(虽然可能存在向后兼容性问题),因此您可以在其中添加正确标头的完整PNG图像,相关信息可以在维基百科上找到。

示例实现:

public static class PngToIcoConverter
{
    public static byte[] Convert(byte[] data)
    {
        Image source;
        using (var inStream = new MemoryStream(data))
        {
            source = Image.FromStream(inStream);
        }
        byte[] output;
        using (var outStream = new MemoryStream())
        {
            // Header
            {
                // Reserved
                outStream.WriteByte(0);
                outStream.WriteByte(0);
                // File format (ico)
                outStream.WriteByte(1);
                outStream.WriteByte(0);
                // Image count (1)
                outStream.WriteByte(1);
                outStream.WriteByte(0);
            }

            // Image entry
            {
                // Width
                outStream.WriteByte((byte)source.Width);
                // Height
                outStream.WriteByte((byte)source.Height);
                // Number of colors (0 = No palette)
                outStream.WriteByte(0);
                // Reserved
                outStream.WriteByte(0);
                // Color plane (1)
                outStream.WriteByte(1);
                outStream.WriteByte(0);
                // Bits per pixel
                var bppAsLittle = IntToLittle2(Image.GetPixelFormatSize(source.PixelFormat));
                outStream.Write(bppAsLittle, 0, 2);
                // Size of data in bytes
                var byteCountAsLittle = IntToLittle4(data.Length);
                outStream.Write(byteCountAsLittle, 0, 4);
                // Offset of data from beginning of file (data begins right here = 22)
                outStream.WriteByte(22);
                outStream.WriteByte(0);
                outStream.WriteByte(0);
                outStream.WriteByte(0);
                // Data
                outStream.Write(data, 0, data.Length);
            }
            output = outStream.ToArray();
        }
        return output;
    }

    private static byte[] IntToLittle2(int input)
    {
        byte[] b = new byte[2];
        b[0] = (byte)input;
        b[1] = (byte)(((uint)input >> 8) & 0xFF);
        return b;
    }
    private static byte[] IntToLittle4(int input)
    {
        byte[] b = new byte[4];
        b[0] = (byte)input;
        b[1] = (byte)(((uint)input >> 8) & 0xFF);
        b[2] = (byte)(((uint)input >> 16) & 0xFF);
        b[3] = (byte)(((uint)input >> 24) & 0xFF);
        return b;
    }
}

2

MSDN表示没有"IcoBitmapEncoder"。我建议您从BitmapFrame中获取Bitmap,然后将其转换为图标,就像这样:

    BitmapEncoder imgEncoder = new PngBitmapEncoder();
    RenderTargetBitmap renderBitmap = new RenderTargetBitmap(32, 32, 96d, 96d, PixelFormats.Pbgra32);
    renderBitmap.Render(comboBox1);
    var frame = BitmapFrame.Create(renderBitmap);

    Bitmap bitmap = GetBitmap(frame);
    bitmap.SetResolution(72, 72);
    System.Drawing.Icon icon = System.Drawing.Icon.FromHandle(bitmap.GetHicon());
    FileStream fs = new FileStream(filename, FileMode.OpenOrCreate);
    icon.Save(fs);
    fs.Close();

你可以从这里获得GetBitmap方法:

    static Bitmap GetBitmap(BitmapSource source)
    {
        Bitmap bmp = new Bitmap(source.PixelWidth, source.PixelHeight, 
            System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
        BitmapData data = bmp.LockBits(
            new System.Drawing.Rectangle(System.Drawing.Point.Empty, bmp.Size), ImageLockMode.WriteOnly, 
            System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
        source.CopyPixels(Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride);
        bmp.UnlockBits(data);
        return bmp;
    }

2
我知道这个问题已经有答案了,但是最近我在Code Project上写了一篇文章,分享了一个IconBitmapEncoder的源代码。它可以将BitmapImage编码为图标文件,无需第三方dll或Win Forms的使用。100% Windows Presentation Foundation。

用于WPF的高质量IconBitmapEncoder

我希望这对你有用。


0
我使用这个扩展方法来创建一个 System.Drawing.Icon:
public static System.Drawing.Icon ToGDIIcon(this System.Windows.Media.ImageSource icon)
        {
            var image = (System.Windows.Media.Imaging.BitmapSource)icon;
            var encoder = new System.Windows.Media.Imaging.PngBitmapEncoder();
            encoder.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(image));
            using (var ms = new MemoryStream())
            {
                encoder.Save(ms);
                using (var tempBitmap = new System.Drawing.Bitmap(ms))
                {
                    return System.Drawing.Icon.FromHandle(tempBitmap.GetHicon());
                }
            }
        }

...

var icon = imageSource.ToGDIIcon();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接