代码之家  ›  专栏  ›  技术社区  ›  Geoff

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

  •  7
  • Geoff  · 技术社区  · 14 年前

    如何创建包含多种大小的图标文件?

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

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

    5 回复  |  直到 14 年前
        1
  •  3
  •   Wonko the Sane    14 年前

    快速CYA:我只是做了一个Google搜索,还没有测试下面的方法。基督教青年会。

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

        2
  •  9
  •   test    9 年前

    我正在寻找一种方法来组合.png文件,没有什么花哨的,成一个图标。我创建了下面的代码后,无法找到一些简单的,与这个问题是最高的搜索结果。


    Image.RawFormat ImageFormat.Png ,的 Image.PixelFormat PixelFormat.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);
    }
    
        3
  •  2
  •   James EJ    10 年前

    这可以通过 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 System.Drawing.Bitmap 对象。

        4
  •  1
  •   Zach Johnson    14 年前

    无法使用创建图标 System.Drawing 图标文件中的特定图标,但不适用于 写作 将多个图标返回到.ico文件。

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

        5
  •  -1
  •   Icemanind    14 年前

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

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