2010-07-09 23 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