WPF中是否有任何IconBitmapEncoder?

时间:2012-03-15 06:04:57

标签: wpf encoding icons

我使用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 个答案:

答案 0 :(得分:1)

没有。

我曾尝试将图像保存为* .ico,而其他.NET类并没有真正帮助(如果我没记错的话,它们只能解码,不能编码;但也许我只是做错了)。 * .ico可以是PNG图像的容器(虽然可能存在向后兼容性问题),因此您可以在其中添加完整的PNG,并使用正确的标题on wikipedia

示例实施:

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;
    }
}

答案 1 :(得分:1)

我知道问题已经得到解答,但最近我写了一篇关于Code Project的文章,我分享了IconBitmapEncoder的源代码。它在图标文件中编码BitmapImage,无需第三方dll或使用Win Forms。 100%Windows Presentation Foundation。

A High-Quality IconBitmapEncoder for WPF

我希望它对你有用。

答案 2 :(得分:0)

MSDN表示没有“IcoBitmapEncoder”。我建议您从Bitmap获取BitmapFrame,然后将其转换为图标,如下所示:

    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();

您可以从here获取的方法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;
    }

答案 3 :(得分: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();