Пример #1
0
        private static IconData BuildIconData(Stream source, IconHeader header, IconEntry entry)
        {
            using (var stream = new MemoryStream())
            {
                using (var writer = new BinaryWriter(stream, System.Text.Encoding.UTF8, true))
                {
                    /* I’m not recreating an icon file here, just one icon at a time in the icon file format.
                     * Therefore write the count as 1, and the offset as sizeof(header) + sizeof(entry). */
                    const short number = 1;
                    var         offset = Marshal.SizeOf(typeof(IconHeader)) + Marshal.SizeOf(typeof(IconEntry));

                    writer.Write(header.Reserved);
                    writer.Write(header.Type);
                    writer.Write(number);
                    writer.Write((byte)entry.Width);
                    writer.Write((byte)entry.Height);
                    writer.Write(entry.ColorCount);
                    writer.Write(entry.Reserved);
                    writer.Write(entry.Planes);
                    writer.Write(entry.BitCount);
                    writer.Write(entry.BytesInRes);
                    writer.Write(offset);

                    var buffer = new byte[entry.BytesInRes];
                    source.Position = entry.ImageOffset;
                    source.Read(buffer, 0, entry.BytesInRes);
                    writer.Write(buffer);

                    /* While this shouldn’t always be necessary, the managed Icon type will throw an exception when, for example,
                     * trying to create an icon from any .png image that was just loaded from the file, whether it is 256×256
                     * (0x0 in the entry), or smaller, whereas this way always seems to work. */
                    using (var image = Image.FromStream(stream) as Bitmap)
                    {
                        Icon temp = null;
                        try
                        {
                            temp = Icon.FromHandle(image.GetHicon());

                            /* Use the dimensions we got from the GDI icon, so we
                             * don’t have to worry about double-height bitmaps etc.*/
                            return(new IconData {
                                Icon = new Icon(temp, temp.Width, temp.Height), BitDepth = entry.BitCount
                            });
                        }
                        finally
                        {
                            if (temp != null)
                            {
                                NativeMethods.DestroyIcon(temp.Handle);
                            }
                        }
                    }
                }
            }
        }
Пример #2
0
        private static IEnumerable <IIconData> ReadStream(Stream stream)
        {
            using (var reader = new BinaryReader(stream, System.Text.Encoding.UTF8, true))
            {
                var header = new IconHeader(reader);

                var entries = new IconEntry[header.Count];

                for (var i = 0; i < header.Count; i++)
                {
                    entries[i] = new IconEntry(reader);
                }

                var imageData = new IconData[header.Count];

                for (var i = 0; i < header.Count; i++)
                {
                    try
                    {
                        imageData[i] = BuildIconData(stream, header, entries[i]);
                    }
                    catch { }
                }

                /* Sort the results; by bit-depth, then size; descending, so that the
                 * first icon found will be the largest resolution and highest bit depth. */
                var bitDepths = imageData.Select(b => b.BitDepth).Distinct().ToList();
                bitDepths.Sort();

                var result = new List <IIconData>();

                foreach (var i in bitDepths)
                {
                    result.AddRange(imageData.Where(b => b.BitDepth == i).OrderBy(b => b.Icon.Width));
                }

                result.Reverse();

                return(result);
            }
        }