如何在C#中创建包含多个大小/图像的图标文件

如何创建包含多个尺寸的图标文件?

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

编辑:我需要在我的应用程序中执行此操作,因此我无法执行外部应用程序来进行组合。

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

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

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


如果对于每个图像, Image.RawFormat是ImageFormat.Png ,则Image.PixelFormat是PixelFormat.Format32bppArgb且尺寸小于或等于256x256 ,以下代码可以创建具有多个尺寸的图标:

 ///  /// Provides methods for creating icons. ///  public class IconFactory { #region constants ///  /// Represents the max allowed width of an icon. ///  public const int MaxIconWidth = 256; ///  /// Represents the max allowed height of an icon. ///  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 ///  /// Saves the specified  objects as a single /// icon into the output stream. ///  /// The bitmaps to save as an icon. /// The output stream. ///  /// The expected input for the  parameter are /// portable network graphic files that have a  /// of  and where the /// width is less than or equal to  and the /// height is less than or equal to . ///  ///  /// Occurs if any of the input images do /// not follow the required image format. See remarks for details. ///  ///  /// Occurs if any of the arguments are null. ///  public static void SavePngsAsIcon(IEnumerable 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 buffers = new Dictionary(); // 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 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); } 

这可以使用IconLib完成。 您可以从CodeProject文章中获取源代码,也可以从我的GitHub镜像中获取已编译的dll 。

 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可以采用256×256 png的路径或System.Drawing.Bitmap对象。

您无法使用System.Drawing API创建图标。 它们是为了从图标文件中访问特定图标而构建的,但不是用于多个图标回.ico文件。

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

使用IcoFX: http : //icofx.ro/

它可以创建Windows图标并在1个ico文件中存储多种大小和颜色