Exemple #1
0
        private void SaveToStream(Stream stream)
        {
            using (var writer = new BinaryWriter(stream, Encoding.UTF8, true))
            {
                // Remove any duplicated resolutions. Done first because this may change the image count.
                //  ValidateImages();

                var imageData = new Dictionary <IconEntry, byte[]>();

                // Write header
                new IconHeader
                {
                    Reserved = 0,
                    Type     = 1,
                    Count    = Convert.ToInt16(images.Count)
                }.Save(writer);

                // The offset of the first icon.
                var offset = Marshal.SizeOf(typeof(IconHeader)) + images.Count * Marshal.SizeOf(typeof(IconEntry));


                // Write all the icon entries
                for (var i = 0; i < images.Count; i++)
                {
                    ImageConverter a     = new ImageConverter();
                    Bitmap         image = images[i] as Bitmap;
                    byte[]         data  = (byte[])a.ConvertTo(image, typeof(byte[]));

                    //    var lol = new ImageMagick.MagickReadSettings() {Format=ImageMagick.MagickFormat.Png };
                    //     ImageMagick.MagickImage mi = new ImageMagick.MagickImage(data1, lol);
                    //    byte[] data = mi.ToByteArray();

                    var entry = new IconEntry
                    {
                        Width       = image.Width < 256 ? Convert.ToByte(image.Width) : (byte)0,
                        Height      = image.Height < 256 ? Convert.ToByte(image.Height) : (byte)0,
                        ColorCount  = 0,
                        Reserved    = 0,
                        Planes      = 1,
                        BitCount    = 32,
                        BytesInRes  = data.Length,
                        ImageOffset = offset
                    };

                    imageData[entry] = data;
                    Console.WriteLine(entry);
                    entry.Save(writer);

                    offset += data.Length;
                }

                // Write the Icons.
                foreach (var kvp in imageData)
                {
                    writer.Seek(kvp.Key.ImageOffset, SeekOrigin.Begin);
                    writer.Write(kvp.Value);
                }
            }
        }
Exemple #2
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);
                            }
                        }
                    }
                }
            }
        }
Exemple #3
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);
            }
        }