2010-07-09 25 views
7

如何创建包含多种尺寸的图标文件?如何在C#中创建包含多种尺寸/图像的图标文件

我知道我使用Icon.FromHandle()从位图创建了一个图标,但是如何将另一个图像/大小添加到该图标?

编辑:我需要在我的应用程序中这样做,所以我不能执行外部应用程序来执行组合。

+0

因为我不认为它回答你的问题,我会张贴这个评论。我使用名为IcoFX的程序来创建图标,并且通过重新采样各种其他尺寸的原始256x256图标(即64x64,32x32 ...),一次创建多个图标大小非常方便。您可能会也可能不会找到它和相关的信息有用。网址:http://icofx.ro/ – JYelton 2010-07-09 15:20:06

+0

我使用GIF Movie Gear。 – 2010-07-09 15:20:55

+0

我使用axialis iconworkshop – iTEgg 2010-07-09 15:25:21

回答

3

快速CYA:我只是做了谷歌搜索,并没有测试下面的方法。因人而异。

我发现this article,它提到了这样做的类(尽管在VB.Net中,但很容易翻译),并告诉他如何使用它。虽然线程指向的页面不再显示源代码,但我确实找到了它的一个版本here.

+0

你的谷歌foo比我的好多了。 :) – Geoff 2010-07-10 05:43:04

1

您不能使用System.Drawing API创建图标。它们是为构建的,它访问图标文件中的特定图标,但不适用于返回多个图标到.ico文件。

如果您只是想制作图标,可以使用GIMP或其他图像处理程序来创建.ico文件。否则,如果您确实需要以编程方式制作.ico文件,则可以使用png2ico(使用System.Diagnostics.Process.Start调用)或类似的东西。

+0

当然,你可以使任何图像的图标文件... http://www.go4expert.com/forums/showthread.php?t= 19250 – NickAldwin 2010-07-09 19:25:48

+0

@NickAldwin:您可以保存单层图标(如链接所示),但不能保存*多个*分层图标。我已编辑澄清。 – 2010-07-09 20:27:04

+0

只是想澄清一个可能的误解,感谢编辑;) – NickAldwin 2010-07-09 20:44:13

2

这可以使用IconLib完成。您可以从CodeProject文章中获得源代码,或者您可以获得compiled dll from my GitHub mirror

public void Convert(string pngPath, string icoPath) 
{ 
    MultiIcon mIcon = new MultiIcon(); 
    mIcon.Add("Untitled").CreateFrom(pngPath, IconOutputFormat.FromWin95); 
    mIcon.SelectedIndex = 0; 
    mIcon.Save(icoPath, MultiIconFormat.ICO); 
} 

CreateFrom可以采取一个路径,一个256x256 PNG或System.Drawing.Bitmap对象。

+0

太棒了。谢谢。 – Robinson 2016-01-19 18:21:51

6

我正在寻找一种方法来将.png文件组合成一个图标,没有任何花哨。我无法找到简单的东西,并且这个问题成为最热门的搜索结果后,我创建了下面的代码。


如果,对于每个图像,该Image.RawFormatImageFormat.Png,将Image.PixelFormatPixelFormat.Format32bppArgb下面的代码可以创建具有多种尺寸的图标和尺寸是小于或等于256x256

/// <summary> 
/// Provides methods for creating icons. 
/// </summary> 
public class IconFactory 
{ 

    #region constants 

    /// <summary> 
    /// Represents the max allowed width of an icon. 
    /// </summary> 
    public const int MaxIconWidth = 256; 

    /// <summary> 
    /// Represents the max allowed height of an icon. 
    /// </summary> 
    public const int MaxIconHeight = 256; 

    private const ushort HeaderReserved = 0; 
    private const ushort HeaderIconType = 1; 
    private const byte HeaderLength = 6; 

    private const byte EntryReserved = 0; 
    private const byte EntryLength = 16; 

    private const byte PngColorsInPalette = 0; 
    private const ushort PngColorPlanes = 1; 

    #endregion 

    #region methods 

    /// <summary> 
    /// Saves the specified <see cref="Bitmap"/> objects as a single 
    /// icon into the output stream. 
    /// </summary> 
    /// <param name="images">The bitmaps to save as an icon.</param> 
    /// <param name="stream">The output stream.</param> 
    /// <remarks> 
    /// The expected input for the <paramref name="images"/> parameter are 
    /// portable network graphic files that have a <see cref="Image.PixelFormat"/> 
    /// of <see cref="PixelFormat.Format32bppArgb"/> and where the 
    /// width is less than or equal to <see cref="IconFactory.MaxIconWidth"/> and the 
    /// height is less than or equal to <see cref="MaxIconHeight"/>. 
    /// </remarks> 
    /// <exception cref="InvalidOperationException"> 
    /// Occurs if any of the input images do 
    /// not follow the required image format. See remarks for details. 
    /// </exception> 
    /// <exception cref="ArgumentNullException"> 
    /// Occurs if any of the arguments are null. 
    /// </exception> 
    public static void SavePngsAsIcon(IEnumerable<Bitmap> images, Stream stream) 
    { 
     if (images == null) 
      throw new ArgumentNullException("images"); 
     if (stream == null) 
      throw new ArgumentNullException("stream"); 

     // validates the pngs 
     IconFactory.ThrowForInvalidPngs(images); 

     Bitmap[] orderedImages = images.OrderBy(i => i.Width) 
             .ThenBy(i => i.Height) 
             .ToArray(); 

     using (var writer = new BinaryWriter(stream)) 
     { 

      // write the header 
      writer.Write(IconFactory.HeaderReserved); 
      writer.Write(IconFactory.HeaderIconType); 
      writer.Write((ushort)orderedImages.Length); 

      // save the image buffers and offsets 
      Dictionary<uint, byte[]> buffers = new Dictionary<uint, byte[]>(); 

      // tracks the length of the buffers as the iterations occur 
      // and adds that to the offset of the entries 
      uint lengthSum = 0; 
      uint baseOffset = (uint)(IconFactory.HeaderLength + 
            IconFactory.EntryLength * orderedImages.Length); 

      for (int i = 0; i < orderedImages.Length; i++) 
      { 
       Bitmap image = orderedImages[i]; 

       // creates a byte array from an image 
       byte[] buffer = IconFactory.CreateImageBuffer(image); 

       // calculates what the offset of this image will be 
       // in the stream 
       uint offset = (baseOffset + lengthSum); 

       // writes the image entry 
       writer.Write(IconFactory.GetIconWidth(image)); 
       writer.Write(IconFactory.GetIconHeight(image)); 
       writer.Write(IconFactory.PngColorsInPalette); 
       writer.Write(IconFactory.EntryReserved); 
       writer.Write(IconFactory.PngColorPlanes); 
       writer.Write((ushort)Image.GetPixelFormatSize(image.PixelFormat)); 
       writer.Write((uint)buffer.Length); 
       writer.Write(offset); 

       lengthSum += (uint)buffer.Length; 

       // adds the buffer to be written at the offset 
       buffers.Add(offset, buffer); 
      } 

      // writes the buffers for each image 
      foreach (var kvp in buffers) 
      { 

       // seeks to the specified offset required for the image buffer 
       writer.BaseStream.Seek(kvp.Key, SeekOrigin.Begin); 

       // writes the buffer 
       writer.Write(kvp.Value); 
      } 
     } 

    } 

    private static void ThrowForInvalidPngs(IEnumerable<Bitmap> images) 
    { 
     foreach (var image in images) 
     { 
      if (image.PixelFormat != PixelFormat.Format32bppArgb) 
      { 
       throw new InvalidOperationException 
        (string.Format("Required pixel format is PixelFormat.{0}.", 
            PixelFormat.Format32bppArgb.ToString())); 
      } 

      if (image.RawFormat.Guid != ImageFormat.Png.Guid) 
      { 
       throw new InvalidOperationException 
        ("Required image format is a portable network graphic (png)."); 
      } 

      if (image.Width > IconFactory.MaxIconWidth || 
       image.Height > IconFactory.MaxIconHeight) 
      { 
       throw new InvalidOperationException 
        (string.Format("Dimensions must be less than or equal to {0}x{1}", 
            IconFactory.MaxIconWidth, 
            IconFactory.MaxIconHeight)); 
      } 
     } 
    } 

    private static byte GetIconHeight(Bitmap image) 
    { 
     if (image.Height == IconFactory.MaxIconHeight) 
      return 0; 

     return (byte)image.Height; 
    } 

    private static byte GetIconWidth(Bitmap image) 
    { 
     if (image.Width == IconFactory.MaxIconWidth) 
      return 0; 

     return (byte)image.Width; 
    } 

    private static byte[] CreateImageBuffer(Bitmap image) 
    { 
     using (var stream = new MemoryStream()) 
     { 
      image.Save(stream, image.RawFormat); 

      return stream.ToArray(); 
     } 
    } 

    #endregion 

} 

用法:

using (var png16 = (Bitmap)Bitmap.FromFile(@"C:\Test\3dGlasses16.png")) 
using (var png32 = (Bitmap)Bitmap.FromFile(@"C:\Test\3dGlasses32.png")) 
using (var stream = new FileStream(@"C:\Test\Combined.ico", FileMode.Create)) 
{ 
    IconFactory.SavePngsAsIcon(new[] { png16, png32 }, stream); 
} 
+0

谢谢。这已经非常有用了。 – apc 2018-01-09 17:09:34

+0

差不多。 Icos不会在XP中工作(我必须支持)。 – apc 2018-01-11 17:49:54