Exemplo n.º 1
0
        public static Icon Create(byte[] colors, int width, int height,
                                  PixelFormat format)
        {
            if (format != PixelFormat.Format32bppArgb)
            {
                throw new NotImplementedException();
            }

            ICONIMAGE image = new ICONIMAGE(width, height, colors);
            ICONDIR   dir   = new ICONDIR(
                new ICONDIRENTRY[] { new ICONDIRENTRY(image, 0) });

            dir.Entries[0].ImageOffset = dir.Size;

            Icon icon;

            binaryWriter.BaseStream.Position = 0;
            dir.Write(binaryWriter);
            image.Write(binaryWriter);

            binaryWriter.BaseStream.Position = 0;
            icon = new Icon(binaryWriter.BaseStream);

            return(icon);
        }
Exemplo n.º 2
0
        public unsafe MultiIcon Load(Stream stream)
        {
            stream.Position = 0;
            SingleIcon singleIcon = new SingleIcon("Untitled");
            ICONDIR    iconDir    = new ICONDIR(stream);

            if (iconDir.idReserved != 0)
            {
                throw new InvalidMultiIconFileException();
            }

            if (iconDir.idType != 1)
            {
                throw new InvalidMultiIconFileException();
            }

            int entryOffset = sizeof(ICONDIR);

            // Add Icon Images one by one to the new entry created
            for (int i = 0; i < iconDir.idCount; i++)
            {
                stream.Seek(entryOffset, SeekOrigin.Begin);
                ICONDIRENTRY entry = new ICONDIRENTRY(stream);

                // If there is missing information in the header... lets try to calculate it
                entry = CheckAndRepairEntry(entry);

                stream.Seek(entry.dwImageOffset, SeekOrigin.Begin);

                singleIcon.Add(new IconImage(stream, (int)(stream.Length - stream.Position)));
                entryOffset += sizeof(ICONDIRENTRY);
            }

            return(new MultiIcon(singleIcon));
        }
Exemplo n.º 3
0
        public unsafe MultiIcon Load(Stream stream)
        {
            stream.Position = 0;
            SingleIcon singleIcon = new SingleIcon("Untitled");
            ICONDIR iconDir = new ICONDIR(stream);
            if (iconDir.idReserved != 0)
                throw new InvalidMultiIconFileException();

            if (iconDir.idType != 1)
                throw new InvalidMultiIconFileException();

            int entryOffset = sizeof(ICONDIR);

            // Add Icon Images one by one to the new entry created
            for(int i=0; i<iconDir.idCount; i++)
            {
                stream.Seek(entryOffset, SeekOrigin.Begin);
                ICONDIRENTRY entry = new ICONDIRENTRY(stream);

                // If there is missing information in the header... lets try to calculate it
                entry = CheckAndRepairEntry(entry);

                stream.Seek(entry.dwImageOffset, SeekOrigin.Begin);

                singleIcon.Add(new IconImage(stream, (int) (stream.Length - stream.Position)));
                entryOffset += sizeof(ICONDIRENTRY);
            }

            return new MultiIcon(singleIcon);
        }
Exemplo n.º 4
0
        public void Save(System.IO.Stream Stream)
        {
            _frames.SortAscending();
            System.IO.BinaryWriter writer = new System.IO.BinaryWriter(Stream, System.Text.Encoding.UTF32);

            ushort FramesCount       = Convert.ToUInt16(_frames.Count);
            ushort FileHeaderLength  = 6;
            ushort FrameHeaderLength = 16;

            ICONDIR FileHeader = new ICONDIR(FramesCount);

            writer.Write(FileHeader.idReserved);
            writer.Write(FileHeader.idType);
            writer.Write(FileHeader.idCount);

            byte[][] data = new byte[FramesCount][];

            foreach (BitmapFrame Frame in _frames)
            {
                int FrameIndex = _frames.IndexOf(Frame);
                if (Frame.PixelWidth == 256)
                {
                    data[FrameIndex] = GetPNGData(Frame);
                }
                else
                {
                    data[FrameIndex] = GetBMPData(Frame);
                }
            }

            uint FrameDataOffset = FileHeaderLength;

            FrameDataOffset += (uint)(FrameHeaderLength * FramesCount);

            foreach (BitmapFrame Frame in _frames)
            {
                int FrameIndex = _frames.IndexOf(Frame);
                if (FrameIndex > 0)
                {
                    FrameDataOffset += Convert.ToUInt32(data[FrameIndex - 1].Length);
                }
                ICONDIRENTRY FrameHeader = new ICONDIRENTRY((ushort)Frame.PixelWidth, (ushort)Frame.PixelHeight, Convert.ToUInt16(Frame.Format.BitsPerPixel), Convert.ToUInt32(data[FrameIndex].Length), FrameDataOffset);
                writer.Write(FrameHeader.bWidth);
                writer.Write(FrameHeader.bHeight);
                writer.Write(FrameHeader.bColorCount);
                writer.Write(FrameHeader.bReserved);
                writer.Write(FrameHeader.wPlanes);
                writer.Write(FrameHeader.wBitCount);
                writer.Write(FrameHeader.dwBytesInRes);
                writer.Write(FrameHeader.dwImageOffset);
            }

            foreach (byte[] FrameData in data)
            {
                writer.Write(FrameData);
            }
        }
Exemplo n.º 5
0
        public unsafe static Cursor Create(ref CefCursorInfo cursorInfo)
        {
            CefSize size = cursorInfo.Size;

            if (size.Width > 0 && size.Height > 0 && cursorInfo.Buffer != IntPtr.Zero)
            {
                try
                {
                    var bufferSize       = size.Width * size.Height * 4;
                    int ICON_HEADER_SIZE = sizeof(ICONDIR);
                    var stream           = new MemoryStream();
                    {
                        DpiScale dpi    = OffscreenGraphics.DpiScale;
                        var      source = BitmapSource.Create(size.Width, size.Height, dpi.PixelsPerInchX, dpi.PixelsPerInchY, PixelFormats.Bgra32, null, cursorInfo.Buffer, bufferSize, size.Width << 2);
                        if (stream.Seek(ICON_HEADER_SIZE, SeekOrigin.Begin) != ICON_HEADER_SIZE)
                        {
                            stream.Seek(0, SeekOrigin.Begin);
                            stream.Write(new byte[ICON_HEADER_SIZE], 0, ICON_HEADER_SIZE);
                        }

                        var png = new PngBitmapEncoder();
                        png.Frames.Add(BitmapFrame.Create(source));
                        png.Save(stream);
                        stream.Seek(0, SeekOrigin.Begin);
                    }

                    CefPoint hotSpot = cursorInfo.Hotspot;

                    var icon = new ICONDIR();
                    icon.IconType    = 2;
                    icon.ImagesCount = 1;
                    icon.Width       = (byte)size.Width;
                    icon.Height      = (byte)size.Height;
                    icon.HotSpotX    = (short)hotSpot.X;
                    icon.HotSpotY    = (short)hotSpot.Y;
                    icon.BytesInRes  = (int)stream.Length - ICON_HEADER_SIZE;
                    icon.ImageOffset = ICON_HEADER_SIZE;

                    using (var iconHead = new UnmanagedMemoryStream(icon._data, ICON_HEADER_SIZE))
                    {
                        iconHead.CopyTo(stream);
                        stream.Seek(0, SeekOrigin.Begin);
                    }

                    return(new Cursor(stream));
                }
                catch (AccessViolationException) { throw; }
                catch { }
            }
            return(Cursors.Arrow);
        }
Exemplo n.º 6
0
        public bool IsRecognizedFormat(Stream stream)
        {
            stream.Position = 0;
            try
            {
                ICONDIR iconDir = new ICONDIR(stream);
                if (iconDir.idReserved != 0)
                    return false;

                if (iconDir.idType != 1)
                    return false;

                return true;

            }
            catch(Exception){}
            return false;
        }
Exemplo n.º 7
0
        public unsafe void Save(Stream stream)
        {
            ICONDIR iconDir = ICONDIR.Initalizated;

            iconDir.idCount = (ushort)this.IconImages.Count;
            iconDir.Write(stream);

            int entryPos = sizeof(ICONDIR);
            // Placeholder for an array if ICONDIRENTRY here
            int imagesPos = entryPos + iconDir.idCount * sizeof(ICONDIRENTRY);

            foreach (IconImage iconImage in this.IconImages)
            {
                // IconImage
                stream.Seek(imagesPos, SeekOrigin.Begin);
                // Header
                BITMAPINFOHEADER header = Make_BITMAPINFOHEADER(iconImage);
                header.Write(stream);

                // Palette - (none)

                // XOR Image
                stream.Write(iconImage.XOR, 0, iconImage.XOR.Length);

                // AND Image - (not needed)


                long bytesInRes = stream.Position - imagesPos;

                // IconDirHeader
                stream.Seek(entryPos, SeekOrigin.Begin);
                ICONDIRENTRY iconEntry = Make_ICONDIRENTRY(iconImage);
                stream.Seek(entryPos, SeekOrigin.Begin);
                iconEntry.dwImageOffset = (uint)imagesPos;
                iconEntry.dwBytesInRes  = (uint)bytesInRes;
                iconEntry.Write(stream);

                entryPos  += sizeof(ICONDIRENTRY);
                imagesPos += (int)bytesInRes;
            }
        }
Exemplo n.º 8
0
        public unsafe void Save(MultiIcon multiIcon, Stream stream)
        {
            if (multiIcon.SelectedIndex == -1)
            {
                return;
            }

            SingleIcon singleIcon = multiIcon[multiIcon.SelectedIndex];

            // ICONDIR header
            ICONDIR iconDir = ICONDIR.Initalizated;

            iconDir.idCount = (ushort)singleIcon.Count;
            iconDir.Write(stream);

            // ICONENTRIES
            int entryPos  = sizeof(ICONDIR);
            int imagesPos = sizeof(ICONDIR) + iconDir.idCount * sizeof(ICONDIRENTRY);

            foreach (IconImage iconImage in singleIcon)
            {
                // for some formats We don't know the size until we write,
                // so we have to write first the image then later the header

                // IconImage
                stream.Seek(imagesPos, SeekOrigin.Begin);
                iconImage.Write(stream);
                long bytesInRes = stream.Position - imagesPos;

                // IconDirHeader
                stream.Seek(entryPos, SeekOrigin.Begin);
                ICONDIRENTRY iconEntry = iconImage.ICONDIRENTRY;
                stream.Seek(entryPos, SeekOrigin.Begin);
                iconEntry.dwImageOffset = (uint)imagesPos;
                iconEntry.dwBytesInRes  = (uint)bytesInRes;
                iconEntry.Write(stream);

                entryPos  += sizeof(ICONDIRENTRY);
                imagesPos += (int)bytesInRes;
            }
        }
Exemplo n.º 9
0
        public bool IsRecognizedFormat(Stream stream)
        {
            stream.Position = 0;
            try
            {
                ICONDIR iconDir = new ICONDIR(stream);
                if (iconDir.idReserved != 0)
                {
                    return(false);
                }

                if (iconDir.idType != 1)
                {
                    return(false);
                }

                return(true);
            }
            catch (Exception) {}
            return(false);
        }
Exemplo n.º 10
0
        public static Icon Create(byte[] colors, int width, int height, 
            PixelFormat format)
        {
            if (format != PixelFormat.Format32bppArgb)
            throw new NotImplementedException();

              ICONIMAGE image = new ICONIMAGE(width, height, colors);
              ICONDIR dir = new ICONDIR(
            new ICONDIRENTRY[] { new ICONDIRENTRY(image, 0) } );
              dir.Entries[0].ImageOffset = dir.Size;

              Icon icon;
              using (BinaryWriter bw = new BinaryWriter(new MemoryStream())) {
                dir.Write(bw);
            image.Write(bw);

                bw.BaseStream.Position = 0;
            icon = new Icon(bw.BaseStream);
            }

              return icon;
        }
Exemplo n.º 11
0
        private static Icon LoadIconFromResource(UIntPtr lpIconName)
        {
            HandleRef hmodule = new HandleRef(null, GetModuleHandle(null));

            uint totalsize;

            RESOURCE_ICONDIRENTRY[] entries;
            SafeResourceBuffer[]    entrybuffers;
            RESOURCE_ICONDIR        dir;

            using (SafeResourceBuffer buffer = GetResourceBuffer(hmodule, lpIconName, MAKEINTRESOURCE(RT_GROUP_ICON)))
            {
                dir = buffer.Read <RESOURCE_ICONDIR>(0);
                if (dir.idReserved != 0 || dir.idType != IMAGE_ICON || dir.idCount == 0)
                {
                    throw new InvalidDataException("There is no icon directory in resource data.");
                }

                entries      = new RESOURCE_ICONDIRENTRY[dir.idCount];
                entrybuffers = new SafeResourceBuffer[dir.idCount];
                uint  entrysize = (uint)Marshal.SizeOf(typeof(RESOURCE_ICONDIRENTRY));
                ulong offset    = (uint)Marshal.SizeOf(typeof(RESOURCE_ICONDIR)) - entrysize;
                totalsize = (uint)(Marshal.SizeOf(typeof(ICONDIR)) + (Marshal.SizeOf(typeof(ICONDIRENTRY)) * (dir.idCount - 1)));

                entries[0] = dir.idEntries;
                for (int i = 0; i < dir.idCount; i++, offset += entrysize)
                {
                    if (i > 0)
                    {
                        entries[i] = buffer.Read <RESOURCE_ICONDIRENTRY>(offset);
                    }

                    uint iconsize = entries[i].dwBytesInRes;
                    SafeResourceBuffer entrybuffer = GetResourceBuffer(hmodule, MAKEINTRESOURCE(entries[i].nID), MAKEINTRESOURCE(RT_ICON));
                    if (iconsize != entrybuffer.ByteLength)
                    {
                        throw new InvalidDataException("Reported resource size is not equal to the icon size.");
                    }

                    entrybuffers[i] = entrybuffer;
                    totalsize      += iconsize;
                }
            }

            using (SafeLocalAllocHandle iconbuffer = SafeLocalAlloc(LMEM_ZEROINIT | LMEM_FIXED, totalsize))
            {
                using (UnmanagedMemoryStream outstream = iconbuffer.ToStream(FileAccess.ReadWrite))
                {
                    ICONDIR icondir = new ICONDIR(dir);
                    iconbuffer.Write(0, icondir);

                    uint iconoffset = icondir.idEntries.dwImageOffset;
                    outstream.Position = iconoffset;
                    uint         entrysize = (uint)Marshal.SizeOf(typeof(ICONDIRENTRY));
                    ulong        offset    = (uint)Marshal.SizeOf(typeof(ICONDIR));
                    ICONDIRENTRY entry     = icondir.idEntries;
                    for (int i = 0; i < dir.idCount; i++, offset += entrysize)
                    {
                        if (i > 0)
                        {
                            entry = new ICONDIRENTRY(entries[i], iconoffset);
                            iconbuffer.Write(offset, entry);
                        }

                        using (UnmanagedMemoryStream instream = entrybuffers[i].ToStream())
                        {
                            instream.CopyTo(outstream);
                        }

                        if (outstream.Position != (iconoffset + entry.dwBytesInRes))
                        {
                            throw new InvalidOperationException();
                        }

                        iconoffset += entry.dwBytesInRes;
                    }

                    outstream.Position = 0;
                    return(new Icon(outstream));
                }
            }
        }
Exemplo n.º 12
0
        public static void ChangeIcon(string exeFilePath, string icoFilePath)
        {
            int len = Marshal.SizeOf(typeof(GRPICONDIR));

            using (FileStream fs = new FileStream(icoFilePath, FileMode.Open, FileAccess.Read))
            {
                // 读取图标目录
                ICONDIR iconDir = fs.Read <ICONDIR>();
                // 读取图标头列表
                List <ICONDIRENTRY> iconDirEntrys = new List <ICONDIRENTRY>();
                for (int i = 0; i < iconDir.idCount; i++)
                {
                    ICONDIRENTRY iconDirEntry = fs.Read <ICONDIRENTRY>();
                    iconDirEntrys.Add(iconDirEntry);
                }
                // 读取图标数据列表
                List <byte[]> iconDatas = new List <byte[]>();
                for (int i = 0; i < iconDir.idCount; i++)
                {
                    byte[] iconData = new byte[iconDirEntrys[i].dwBytesInRes];
                    fs.Seek(iconDirEntrys[i].dwImageOffset, SeekOrigin.Begin);
                    fs.Read(iconData, 0, iconData.Length);
                    iconDatas.Add(iconData);
                }

                // 生成GRPICONDIR
                GRPICONDIR grpIconDir = new GRPICONDIR();
                grpIconDir.idCount    = iconDir.idCount;
                grpIconDir.idReserved = 0;
                grpIconDir.idType     = 1; // 1代表图标

                // 生成List<GRPICONDIRENTRY>
                List <GRPICONDIRENTRY> grpIconDirEntrys = new List <GRPICONDIRENTRY>();
                for (int i = 0; i < iconDirEntrys.Count; i++)
                {
                    GRPICONDIRENTRY grpIconDirEntry = new GRPICONDIRENTRY();
                    grpIconDirEntry.CopyFrom(iconDirEntrys[i]);
                    grpIconDirEntry.nID = (short)(i + 1);
                    grpIconDirEntrys.Add(grpIconDirEntry);
                }
                List <byte> grpData = new List <byte>();
                grpData.AddRange(grpIconDir.ToByteArray());
                for (int i = 0; i < grpIconDirEntrys.Count; i++)
                {
                    grpData.AddRange(grpIconDirEntrys[i].ToByteArray());
                }
                IntPtr grpDataPtr = grpData.ToArray().ToPtr();

                bool   ret        = false;
                IntPtr pUpdateRes = BeginUpdateResource(exeFilePath, false);
                for (int i = 0; i < grpIconDirEntrys.Count; i++)
                {
                    // 更新图标数据
                    int id = grpIconDirEntrys[i].nID;
                    ret = UpdateResource(pUpdateRes, new IntPtr((int)eResourceTypes.RT_ICON), new IntPtr(id), 0, iconDatas[i].ToPtr(), iconDatas[i].Length);
                }
                // 更新图标目录和图标头
                // 32512为当前exe中Icon Group下id号
                ret = UpdateResource(pUpdateRes, new IntPtr((int)eResourceTypes.RT_GROUP_ICON), new IntPtr(32512), 0, grpDataPtr, grpData.Count);
                ret = EndUpdateResource(pUpdateRes, false);
            }
        }
Exemplo n.º 13
0
    internal static string makeIconEx(string icon, int size, int depth, string icoFormat)
    {
        // Header of the whole file, the file may contain more than one Icon

        byte[] bytes           = System.Convert.FromBase64String(icon);
        int    colorsInPalette = depth > 8 ? 0 : 1 << depth;

        ICONDIR          iconDir      = ICONDIR.Initalizated;
        ICONDIRENTRY     iconEntry    = new ICONDIRENTRY();
        BITMAPINFOHEADER bitMapHeader = new BITMAPINFOHEADER();

        iconEntry.bWidth        = (byte)size;
        iconEntry.bHeight       = (byte)size;
        iconEntry.bColorCount   = (byte)colorsInPalette; // 4 = 16 colors, 8 = 256
        iconEntry.wBitCount     = (ushort)depth;
        iconEntry.bReserved     = 0;
        iconEntry.dwBytesInRes  = (uint)(bytes.Length + Marshal.SizeOf(bitMapHeader) + colorsInPalette * 4); // Each color requires 4 bytes in the palette
        iconEntry.dwImageOffset = (uint)(Marshal.SizeOf(iconDir) + Marshal.SizeOf(iconEntry));
        iconEntry.wPlanes       = 1;

        bitMapHeader.biSize          = (uint)Marshal.SizeOf(bitMapHeader);
        bitMapHeader.biWidth         = (uint)size;
        bitMapHeader.biHeight        = (uint)size * 2;
        bitMapHeader.biBitCount      = (ushort)depth;
        bitMapHeader.biPlanes        = 1;
        bitMapHeader.biCompression   = IconImageFormat.BMP;
        bitMapHeader.biXPelsPerMeter = 0;
        bitMapHeader.biYPelsPerMeter = 0;
        bitMapHeader.biClrUsed       = (uint)colorsInPalette;
        bitMapHeader.biClrImportant  = 0;
        bitMapHeader.biSizeImage     = (uint)bytes.Length;

        //
        // The icon is recieved flipped vertically, we need first to flip it before sending
        // it to the consumer
        //
        byte[] data = null;
        int    len = 0, revIndex = 0, rowWidth = 0, ANDmapSize;

        len        = bytes.Length;
        data       = new byte[bytes.Length];
        rowWidth   = size * depth / 8;
        ANDmapSize = len - size * size * depth / 8;
        int step = 4;

        for (int k = len - rowWidth; k >= ANDmapSize; k -= rowWidth)
        {
            for (int r = 0; r < rowWidth; r++, revIndex++)
            {
                data[revIndex] = bytes[k + r];
            }
        }

        for (int l = 0, m = ANDmapSize - step; l < ANDmapSize; l += step, m -= step)
        {
            for (int n = 0; n < step; n++, revIndex++)
            {
                data[revIndex] = bytes[m + n];
            }
        }

        MemoryStream mStream = new MemoryStream();

        //
        // Write the Icon directory
        //
        iconDir.Write(mStream);

        //
        // Write the icon directory entry
        //
        iconEntry.Write(mStream);

        //
        // Write the bitmap header
        //
        bitMapHeader.Write(mStream);

        //
        // Write the appropriate palette if required
        //
        if (depth == 4)
        {
            mStream.Write(palette_16, 0, palette_16.Length);
        }

        //
        // Write the icon data recieved from the CPS server
        //
        mStream.Write(data, 0, data.Length);

        byte[] outBytes;

        //
        // If the consumer requested an ico format return the stream as is without any conversion
        //
        if (icoFormat.ToLower() == "ico")
        {
            outBytes = mStream.GetBuffer();
            mStream.Dispose();
            return(Convert.ToBase64String(outBytes));
        }

        //
        // Store the stream in an Icon object, this will solve the transparency problem
        //
        mStream.Position = 0;
        Icon iconStream = new Icon(mStream, depth, depth);

        //
        // Retrieve the icon as bitmap for conversion
        //
        Bitmap      bitMap    = iconStream.ToBitmap();
        ImageFormat imgFormat = ImageFormat.Png;

        switch (icoFormat.ToLower())
        {
        case "png":
            imgFormat = ImageFormat.Png;
            break;

        case "gif":
            imgFormat = ImageFormat.Gif;
            break;

        case "tiff":
            imgFormat = ImageFormat.Tiff;
            break;
        }

        //
        // Save the icon in the requested format to an icon to be sent to the consumer
        //
        MemoryStream oMStream = new MemoryStream();

        bitMap.Save(oMStream, imgFormat);
        outBytes = oMStream.GetBuffer();
        mStream.Dispose();
        oMStream.Close();
        oMStream.Dispose();
        bitMap.Dispose();

        //
        // Return the icon as base64 string
        //
        return(Convert.ToBase64String(outBytes));
    }
Exemplo n.º 14
0
        // Layout: ICONDIR, ICONDIRENTRY[], PngData[]
        static void WriteIcoFile(string fileName,
                                 IEnumerable <Bitmap> smallerBmps,
                                 Bitmap big256PxSource)
        {
            var dir = new ICONDIR
            {
                reserved  = 0,
                imageType = 1,
                numImages = (UInt16)(1 + smallerBmps.Count())
            };

            var entries = new ICONDIRENTRY[dir.numImages];

            var pngsToWrite = new Queue <MemoryStream>();

            // Smaller entries go first
            var i      = 0;
            var offset = Marshal.SizeOf(dir) +
                         (Marshal.SizeOf(entries[0]) * entries.Length);

            foreach (var img in smallerBmps)
            {
                entries[i].imageWidth   = (byte)img.Size.Width;
                entries[i].imageHeight  = (byte)img.Size.Height;
                entries[i].numColors    = 0;
                entries[i].reserved     = 0;
                entries[i].colorPlanes  = 0;
                entries[i].bitsPerPixel = 32;

                var stream = new MemoryStream();
                img.Save(stream, ImageFormat.Png);
                pngsToWrite.Enqueue(stream);

                entries[i].imageDataSize   = (UInt32)stream.Length;
                entries[i].imageDataOffset = (UInt32)offset;

                Debug.WriteLine($"Storing {img.Size.Width}x{img.Size.Height} image with size {stream.Length} at offset {offset}");

                offset += (int)stream.Length;
                i++;
            }

            // 256x256 goes last
            entries[i].imageWidth   = (byte)big256PxSource.Size.Width;
            entries[i].imageHeight  = (byte)big256PxSource.Size.Height;
            entries[i].numColors    = 0;
            entries[i].reserved     = 0;
            entries[i].colorPlanes  = 0;
            entries[i].bitsPerPixel = 32;

            var bigImageStream = new MemoryStream();

            big256PxSource.Save(bigImageStream, ImageFormat.Png);
            pngsToWrite.Enqueue(bigImageStream);

            entries[i].imageDataSize   = (UInt32)bigImageStream.Length;
            entries[i].imageDataOffset = (UInt32)offset;

            Debug.WriteLine($"Storing {big256PxSource.Size.Width}x{big256PxSource.Size.Height} image with size {bigImageStream.Length} at offset {offset}");

            offset = 0;
            // Write all of the data out to the ICO file
            using (var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
            {
                var header = GetBytesForStruct(dir);
                fileStream.Write(header, 0, header.Length);

                Debug.WriteLine($"Wrote header ({header.Length} bytes, offset = {offset})");
                offset += header.Length;

                i = 0;
                foreach (var entry in entries)
                {
                    var entryBytes = GetBytesForStruct(entry);
                    fileStream.Write(entryBytes, 0, entryBytes.Length);

                    Debug.WriteLine($"Wrote directory entry {i++} ({entryBytes.Length} bytes, offset = {offset})");
                    offset += entryBytes.Length;
                }
                while (pngsToWrite.Count > 0)
                {
                    var pngStream = pngsToWrite.Dequeue();
                    pngStream.Position = 0;
                    pngStream.CopyTo(fileStream);
                    Debug.WriteLine($"Wrote PNG ({pngStream.Length} bytes, offset = {offset})");
                    offset += (int)pngStream.Length;
                }
            }
        }