2010-07-09 12 views
7

¿Cómo creo un archivo de icono que contiene varios tamaños?Cómo crear un archivo de icono que contiene múltiples tamaños/imágenes en C#

Sé que creo un ícono a partir de un mapa de bits usando Icon.FromHandle(), pero ¿cómo agrego otra imagen/tamaño a ese ícono?

Edición: Necesito hacer esto en mi aplicación, así que no puedo ejecutar una aplicación externa para hacer la combinación.

+0

como yo no creo que responde a su pregunta, voy a publicar esto como un comentario. Utilizo un programa llamado IcoFX para crear íconos, y es muy útil para crear múltiples tamaños de íconos a la vez, al volver a muestrear el ícono original de 256x256 en los otros varios tamaños (es decir, 64x64, 32x32 ...) Puede o no encontrarlo y la información relacionada útil. Sitio web: http://icofx.ro/ – JYelton

+0

Uso GIF Movie Gear. –

+0

yo uso axialis iconworkshop – iTEgg

Respuesta

3

CYA rápida: acabo de hacer una búsqueda en Google, y no han probado el método siguiente. YMMV.

Encontré this article, que menciona una clase que hace esto (aunque en VB.Net, pero lo suficientemente fácil de traducir), y explica cómo lo usó. Mientras que la página a la que apunta el hilo ya no parece tener el código fuente mencionado, encontré una versión del mismo here.

+0

Tu google foo es mucho mejor que el mío. :) – Geoff

1

No puede crear un icono con las API System.Drawing. Fueron construidos para accediendo a iconos específicos desde dentro de un archivo de icono, pero no para escribiendo detrás de múltiples iconos en un archivo .ico.

Si solo desea hacer iconos, puede usar GIMP u otro programa de procesamiento de imágenes para crear sus archivos .ico. De lo contrario, si realmente necesita hacer los archivos .ico programáticamente, puede usar png2ico (invocando usando System.Diagnostics.Process.Start) o algo similar.

+0

Claro que puedes hacer archivos de iconos ... desde cualquier imagen: http://www.go4expert.com/forums/showthread.php?t= 19250 – NickAldwin

+0

@NickAldwin: Puede guardar iconos de una sola capa (como muestra su enlace), pero no puede guardar * múltiples iconos en capas *. He editado para aclarar. –

+0

Solo quería aclarar un posible malentendido, gracias por la edición;) – NickAldwin

0

Uso IcoFX: http://icofx.ro/

Se puede crear iconos de Windows y almacenar múltiples tamaños y colores en 1 archivo ico

2

Esto se puede hacer con IconLib. Puede obtener la fuente del artículo de CodeProject o puede obtener un 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 puede tomar la ruta de acceso a un png 256x256 o un objeto System.Drawing.Bitmap.

+0

Maravilloso. Gracias. – Robinson

6

Estaba buscando una manera de combinar archivos .png, nada sofisticado, en un icono. Creé el código a continuación después de no poder encontrar algo simple y con esta pregunta como el resultado de búsqueda superior.


el siguiente código puede crear un icono con múltiples tamaños si, para cada una de las imágenes, el Image.RawFormat es ImageFormat.Png, la Image.PixelFormat es PixelFormat.Format32bppArgb y las dimensiones son menores o iguales a 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 

} 

Uso:

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

Gracias. Esto ha sido realmente útil. – apc

+0

Casi. Icos no trabajará en XP (que tengo que apoyar). – apc

Cuestiones relacionadas