Example #1
0
        // TODO: check image not ignored (presently this method doesnt seem to be called unless width/height
        // refer to image)
        private void SaveBestSingleIcon(BinaryWriter writer, int width, int height)
        {
            writer.Write(iconDir.idReserved);
            writer.Write(iconDir.idType);
            writer.Write((ushort)1);

            // find best entry and save it
            int best     = 0;
            int bitCount = 0;

            for (int i = 0; i < iconDir.idCount; i++)
            {
                IconDirEntry ide = iconDir.idEntries [i];
                if ((width == ide.width) && (height == ide.height))
                {
                    if (ide.bitCount >= bitCount)
                    {
                        bitCount = ide.bitCount;
                        best     = i;
                    }
                }
            }

            SaveIconDirEntry(writer, iconDir.idEntries [best], 22);
            SaveIconImage(writer, (IconImage)imageData [best]);
        }
        public void Save(Stream stream)
        {
            _frames.SortAscending();
            stream.Position = 0;
            var writer = new BinaryWriter(stream, System.Text.Encoding.UTF32);

            var          framesCount       = Convert.ToUInt16(_frames.Count);
            const ushort fileHeaderLength  = 6;
            const ushort frameHeaderLength = 16;

            var fileHeader = new IconDir(framesCount);

            writer.Write(fileHeader.IdReserved);
            writer.Write(fileHeader.IdType);
            writer.Write(fileHeader.IdCount);

            var data = new byte[framesCount][];

            foreach (var frame in _frames)
            {
                var frameIndex = _frames.IndexOf(frame);
                data[frameIndex] = GetPngData(frame);
                //if (frame.PixelWidth == 256)
                //{
                //    data[frameIndex] = GetPngData(frame);
                //}
                //else
                //{
                //    data[frameIndex] = GetBmpData(frame);
                //}
            }

            uint frameDataOffset = fileHeaderLength;

            frameDataOffset += (uint)(frameHeaderLength * framesCount);

            foreach (var frame in _frames)
            {
                var frameIndex = _frames.IndexOf(frame);
                if (frameIndex > 0)
                {
                    frameDataOffset += Convert.ToUInt32(data[frameIndex - 1].Length);
                }
                var 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 (var frameData in data)
            {
                writer.Write(frameData);
            }
        }
Example #3
0
        public void Save(Stream outputStream)
        {
            if (iconDir.idEntries != null)
            {
                BinaryWriter bw = new BinaryWriter(outputStream);
                //write icondir
                bw.Write(iconDir.idReserved);
                bw.Write(iconDir.idType);
                ushort count = iconDir.idCount;
                bw.Write(count);

                //now write iconDirEntries
                for (int i = 0; i < (int)count; i++)
                {
                    IconDirEntry ide = iconDir.idEntries[i];
                    bw.Write(ide.width);
                    bw.Write(ide.height);
                    bw.Write(ide.colorCount);
                    bw.Write(ide.reserved);
                    bw.Write(ide.planes);
                    bw.Write(ide.bitCount);
                    bw.Write(ide.bytesInRes);
                    bw.Write(ide.imageOffset);
                }

                //now write iconImage data
                for (int i = 0; i < (int)count; i++)
                {
                    BitmapInfoHeader bih = imageData[i].iconHeader;
                    bw.Write(bih.biSize);
                    bw.Write(bih.biWidth);
                    bw.Write(bih.biHeight);
                    bw.Write(bih.biPlanes);
                    bw.Write(bih.biBitCount);
                    bw.Write(bih.biCompression);
                    bw.Write(bih.biSizeImage);
                    bw.Write(bih.biXPelsPerMeter);
                    bw.Write(bih.biYPelsPerMeter);
                    bw.Write(bih.biClrUsed);
                    bw.Write(bih.biClrImportant);

                    //now write color table
                    int colCount = imageData[i].iconColors.Length;
                    for (int j = 0; j < colCount; j++)
                    {
                        bw.Write(imageData[i].iconColors[j]);
                    }

                    //now write XOR Mask
                    bw.Write(imageData[i].iconXOR);

                    //now write AND Mask
                    bw.Write(imageData[i].iconAND);
                }
                bw.Flush();
            }
        }
Example #4
0
 private void SaveIconDirEntry(BinaryWriter writer, IconDirEntry ide, uint offset)
 {
     writer.Write(ide.width);
     writer.Write(ide.height);
     writer.Write(ide.colorCount);
     writer.Write(ide.reserved);
     writer.Write(ide.planes);
     writer.Write(ide.bitCount);
     writer.Write(ide.bytesInRes);
     writer.Write((offset == uint.MaxValue) ? ide.imageOffset : offset);
 }
 private static void SaveIconDirEntry(BinaryWriter writer, IconDirEntry iconDirEntry)
 {
     writer.Write(iconDirEntry.width);
     writer.Write(iconDirEntry.height);
     writer.Write(iconDirEntry.colorCount);
     writer.Write(iconDirEntry.reserved);
     writer.Write(iconDirEntry.planes);
     writer.Write(iconDirEntry.bitCount);
     writer.Write(iconDirEntry.bytesInRes);
     writer.Write(iconDirEntry.imageOffset);
 }
Example #6
0
        public Icon(Icon original, Size size)
        {
            this.iconSize  = size;
            this.winHandle = original.winHandle;
            this.iconDir   = original.iconDir;
            this.imageData = original.imageData;

            int  count        = iconDir.idCount;
            bool sizeObtained = false;

            for (int i = 0; i < count; i++)
            {
                IconDirEntry ide = iconDir.idEntries[i];
                if (!sizeObtained)
                {
                    if (ide.height == size.Height && ide.width == size.Width)
                    {
                        this.id              = (ushort)i;
                        sizeObtained         = true;
                        this.iconSize.Height = ide.height;
                        this.iconSize.Width  = ide.width;
                        break;
                    }
                }
            }

            if (!sizeObtained)
            {
                uint largestSize = 0;
                for (int j = 0; j < count; j++)
                {
                    if (iconDir.idEntries[j].bytesInRes >= largestSize)
                    {
                        largestSize          = iconDir.idEntries[j].bytesInRes;
                        this.id              = (ushort)j;
                        this.iconSize.Height = iconDir.idEntries[j].height;
                        this.iconSize.Width  = iconDir.idEntries[j].width;
                    }
                }
            }
        }
Example #7
0
        public Icon(Icon original, Size size)
        {
            if (original == null)
            {
                throw new ArgumentNullException(nameof(original));
            }

            iconSize = size;
            iconDir  = original.iconDir;

            int count = iconDir.idCount;

            if (count > 0)
            {
                imageData = original.imageData;
                id        = ushort.MaxValue;

                for (ushort i = 0; i < count; i++)
                {
                    IconDirEntry ide = iconDir.idEntries[i];
                    if (((ide.height == size.Height) || (ide.width == size.Width)) && !ide.png)
                    {
                        id = i;
                        break;
                    }
                }

                // if a perfect match isn't found we look for the biggest icon *smaller* than specified
                if (id == ushort.MaxValue)
                {
                    int requested = Math.Min(size.Height, size.Width);
                    // previously best set to 1st image, as this might not be smallest changed loop to check all
                    IconDirEntry?best = null;
                    for (ushort i = 0; i < count; i++)
                    {
                        IconDirEntry ide = iconDir.idEntries[i];
                        if (((ide.height < requested) || (ide.width < requested)) && !ide.png)
                        {
                            if (best == null)
                            {
                                best = ide;
                                id   = i;
                            }
                            else if ((ide.height > best.Value.height) || (ide.width > best.Value.width))
                            {
                                best = ide;
                                id   = i;
                            }
                        }
                    }
                }

                // last one, if nothing better can be found
                if (id == ushort.MaxValue)
                {
                    int i = count;
                    while (id == ushort.MaxValue && i > 0)
                    {
                        i--;
                        if (!iconDir.idEntries[i].png)
                        {
                            id = (ushort)i;
                        }
                    }
                }

                if (id == ushort.MaxValue)
                {
                    throw new ArgumentException(SR.NoValidIconImageFound, nameof(original));
                }

                iconSize.Height = iconDir.idEntries[id].height;
                iconSize.Width  = iconDir.idEntries[id].width;
            }
            else
            {
                iconSize.Height = size.Height;
                iconSize.Width  = size.Width;
            }

            if (original.bitmap != null)
            {
                bitmap = (Bitmap)original.bitmap.Clone();
            }
        }
Example #8
0
        private void SaveBitmapAsIcon(BinaryWriter writer)
        {
            writer.Write((ushort)0);                    // idReserved must be 0
            writer.Write((ushort)1);                    // idType must be 1
            writer.Write((ushort)1);                    // only one icon

            // when transformed into a bitmap only a single image exists
            IconDirEntry ide = new IconDirEntry();

            ide.width       = (byte)bitmap.Width;
            ide.height      = (byte)bitmap.Height;
            ide.colorCount  = 0;                // 32 bbp == 0, for palette size
            ide.reserved    = 0;                // always 0
            ide.planes      = 0;
            ide.bitCount    = 32;
            ide.imageOffset = 22;               // 22 is the first icon position (for single icon files)

            BitmapInfoHeader bih = new BitmapInfoHeader();

            bih.biSize          = (uint)Marshal.SizeOf(typeof(BitmapInfoHeader));
            bih.biWidth         = bitmap.Width;
            bih.biHeight        = 2 * bitmap.Height;      // include both XOR and AND images
            bih.biPlanes        = 1;
            bih.biBitCount      = 32;
            bih.biCompression   = 0;
            bih.biSizeImage     = 0;
            bih.biXPelsPerMeter = 0;
            bih.biYPelsPerMeter = 0;
            bih.biClrUsed       = 0;
            bih.biClrImportant  = 0;

            IconImage ii = new IconImage();

            ii.iconHeader = bih;
            ii.iconColors = new uint [0];               // no palette
            int xor_size = (((bih.biBitCount * bitmap.Width + 31) & ~31) >> 3) * bitmap.Height;

            ii.iconXOR = new byte [xor_size];
            int p = 0;

            for (int y = bitmap.Height - 1; y >= 0; y--)
            {
                for (int x = 0; x < bitmap.Width; x++)
                {
                    Color c = bitmap.GetPixel(x, y);
                    ii.iconXOR [p++] = c.B;
                    ii.iconXOR [p++] = c.G;
                    ii.iconXOR [p++] = c.R;
                    ii.iconXOR [p++] = c.A;
                }
            }
            int and_line_size = (((Width + 31) & ~31) >> 3);                    // must be a multiple of 4 bytes
            int and_size      = and_line_size * bitmap.Height;

            ii.iconAND = new byte [and_size];

            ide.bytesInRes = (uint)(bih.biSize + xor_size + and_size);

            SaveIconDirEntry(writer, ide, UInt32.MaxValue);
            SaveIconImage(writer, ii);
        }
Example #9
0
        private void InitFromStreamWithSize(Stream stream, int width, int height)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            if (stream.Length == 0)
            {
                throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", nameof(stream)));
            }

            bool   sizeObtained = false;
            ushort dirEntryCount;

            // Read the icon header
            using (var reader = new BinaryReader(stream))
            {
                iconDir.idReserved = reader.ReadUInt16();
                if (iconDir.idReserved != 0) //must be 0
                {
                    throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", nameof(stream)));
                }

                iconDir.idType = reader.ReadUInt16();
                if (iconDir.idType != 1) //must be 1
                {
                    throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", nameof(stream)));
                }

                dirEntryCount     = reader.ReadUInt16();
                imageData         = new ImageData[dirEntryCount];
                iconDir.idCount   = dirEntryCount;
                iconDir.idEntries = new IconDirEntry[dirEntryCount];
                // Now read in the IconDirEntry structures
                for (int i = 0; i < dirEntryCount; i++)
                {
                    var ide = new IconDirEntry
                    {
                        width       = reader.ReadByte(),
                        height      = reader.ReadByte(),
                        colorCount  = reader.ReadByte(),
                        reserved    = reader.ReadByte(),
                        planes      = reader.ReadUInt16(),
                        bitCount    = reader.ReadUInt16(),
                        bytesInRes  = reader.ReadUInt32(),
                        imageOffset = reader.ReadUInt32()
                    };

                    // Vista 256x256 icons points directly to a PNG bitmap
                    // 256x256 icons are decoded as 0x0 (width and height are encoded as BYTE)
                    // We mark them as png and later on we just store the raw bytes to be able to save to a file.
                    ide.png = (ide.width == 0) && (ide.height == 0);

                    iconDir.idEntries[i] = ide;

                    if (!sizeObtained)
                    {
                        if (((ide.height == height) || (ide.width == width)) && !ide.png)
                        {
                            this.id              = (ushort)i;
                            sizeObtained         = true;
                            this.iconSize.Height = ide.height;
                            this.iconSize.Width  = ide.width;
                        }
                    }
                }

                // If we havent found the best match, return the one with the largest size.
                if (!sizeObtained)
                {
                    uint largestSize = 0;
                    for (int j = 0; j < dirEntryCount; j++)
                    {
                        if (iconDir.idEntries[j].bytesInRes >= largestSize && !iconDir.idEntries[j].png)
                        {
                            largestSize          = iconDir.idEntries[j].bytesInRes;
                            this.id              = (ushort)j;
                            this.iconSize.Height = iconDir.idEntries[j].height;
                            this.iconSize.Width  = iconDir.idEntries[j].width;
                        }
                    }
                }

                // Now read in the icon data
                bool valid = false;
                for (int j = 0; j < dirEntryCount; j++)
                {
                    stream.Seek(iconDir.idEntries[j].imageOffset, SeekOrigin.Begin);
                    byte[] buffer = new byte[iconDir.idEntries[j].bytesInRes];
                    stream.Read(buffer, 0, buffer.Length);
                    using (var bihReader = new BinaryReader(new MemoryStream(buffer)))
                    {
                        uint headerSize  = bihReader.ReadUInt32();
                        int  headerWidth = bihReader.ReadInt32();

                        // Process PNG images into IconDump
                        if (iconDir.idEntries[j].png || (headerSize == PNGSignature1 && headerWidth == (int)PNGSignature2))
                        {
                            IconDump id = new IconDump();
                            id.data                  = buffer;
                            imageData[j]             = id;
                            iconDir.idEntries[j].png = true;
                            continue;
                        }

                        // We found a valid icon BMP entry.
                        valid = true;

                        var bih = new BitmapInfoHeader
                        {
                            biSize          = headerSize,
                            biWidth         = headerWidth,
                            biHeight        = bihReader.ReadInt32(),
                            biPlanes        = bihReader.ReadUInt16(),
                            biBitCount      = bihReader.ReadUInt16(),
                            biCompression   = bihReader.ReadUInt32(),
                            biSizeImage     = bihReader.ReadUInt32(),
                            biXPelsPerMeter = bihReader.ReadInt32(),
                            biYPelsPerMeter = bihReader.ReadInt32(),
                            biClrUsed       = bihReader.ReadUInt32(),
                            biClrImportant  = bihReader.ReadUInt32()
                        };
                        var iidata = new IconImage
                        {
                            iconHeader = bih
                        };
                        // Read the number of colors used and corresponding memory occupied by
                        // color table. Fill this memory chunk into rgbquad[]
                        int numColors;
                        switch (bih.biBitCount)
                        {
                        case 1:
                            numColors = 2;
                            break;

                        case 4:
                            numColors = 16;
                            break;

                        case 8:
                            numColors = 256;
                            break;

                        default:
                            numColors = 0;
                            break;
                        }

                        iidata.iconColors = new uint[numColors];
                        for (int i = 0; i < numColors; i++)
                        {
                            iidata.iconColors[i] = bihReader.ReadUInt32();
                        }

                        //XOR mask is immediately after ColorTable and its size is
                        //icon height* no. of bytes per line

                        //icon height is half of BITMAPINFOHEADER.biHeight, since it contains
                        //both XOR as well as AND mask bytes
                        int iconHeight = bih.biHeight / 2;

                        //bytes per line should be uint aligned
                        int numBytesPerLine = checked ((((bih.biWidth * bih.biPlanes * bih.biBitCount) + 31) >> 5) << 2);

                        //Determine the XOR array Size
                        int xorSize = checked (numBytesPerLine * iconHeight);
                        iidata.iconXOR = new byte[xorSize];
                        int nread = bihReader.Read(iidata.iconXOR, 0, xorSize);
                        if (nread != xorSize)
                        {
                            throw new ArgumentException(SR.Format(SR.IconInvalidMaskLength, "XOR", xorSize, nread), nameof(stream));
                        }

                        //Determine the AND array size
                        numBytesPerLine = checked ((((bih.biWidth) + 31) & ~31) >> 3);
                        int andSize = checked (numBytesPerLine * iconHeight);
                        iidata.iconAND = new byte[andSize];
                        nread          = bihReader.Read(iidata.iconAND, 0, andSize);
                        if (nread != andSize)
                        {
                            throw new ArgumentException(SR.Format(SR.IconInvalidMaskLength, "AND", andSize, nread), nameof(stream));
                        }

                        imageData[j] = iidata;
                    }
                }

                // Throw error if no valid entries found
                if (!valid)
                {
                    throw new Win32Exception(SafeNativeMethods.ERROR_INVALID_PARAMETER, SR.Format(SR.InvalidPictureType, "picture", nameof(stream)));
                }
            }
        }
Example #10
0
        public Icon(Icon original, Size size)
        {
            if (original == null)
            {
                throw new ArgumentException("original");
            }

            iconSize = size;
            iconDir  = original.iconDir;

            int count = iconDir.idCount;

            if (count > 0)
            {
                imageData = original.imageData;
                id        = UInt16.MaxValue;

                for (ushort i = 0; i < count; i++)
                {
                    IconDirEntry ide = iconDir.idEntries [i];
                    if ((ide.height == size.Height) || (ide.width == size.Width))
                    {
                        id = i;
                        break;
                    }
                }

                // if a perfect match isn't found we look for the biggest icon *smaller* than specified
                if (id == UInt16.MaxValue)
                {
                    int          requested = Math.Min(size.Height, size.Width);
                    IconDirEntry best      = iconDir.idEntries [0];
                    for (ushort i = 1; i < count; i++)
                    {
                        IconDirEntry ide = iconDir.idEntries [i];
                        if ((ide.height < requested) || (ide.width < requested))
                        {
                            if ((ide.height > best.height) || (ide.width > best.width))
                            {
                                id = i;
                            }
                        }
                    }
                }

                // last one, if nothing better can be found
                if (id == UInt16.MaxValue)
                {
                    id = (ushort)(count - 1);
                }

                iconSize.Height = iconDir.idEntries [id].height;
                iconSize.Width  = iconDir.idEntries [id].width;
            }
            else
            {
                iconSize.Height = size.Height;
                iconSize.Width  = size.Width;
            }

            if (original.bitmap != null)
            {
                bitmap = (Bitmap)original.bitmap.Clone();
            }
        }
Example #11
0
File: Icon.cs Project: kumpera/mono
		private void SaveBitmapAsIcon (BinaryWriter writer)
		{
			writer.Write ((ushort)0);	// idReserved must be 0
			writer.Write ((ushort)1);	// idType must be 1
			writer.Write ((ushort)1);	// only one icon

			// when transformed into a bitmap only a single image exists
			IconDirEntry ide = new IconDirEntry ();
			ide.width = (byte) bitmap.Width;
			ide.height = (byte) bitmap.Height;
			ide.colorCount = 0;	// 32 bbp == 0, for palette size
			ide.reserved = 0;	// always 0
			ide.planes = 0;
			ide.bitCount = 32;
			ide.imageOffset = 22;	// 22 is the first icon position (for single icon files)

			BitmapInfoHeader bih = new BitmapInfoHeader ();
			bih.biSize = (uint) Marshal.SizeOf (typeof (BitmapInfoHeader));
			bih.biWidth = bitmap.Width;
			bih.biHeight = 2 * bitmap.Height; // include both XOR and AND images
			bih.biPlanes = 1;
			bih.biBitCount = 32;
			bih.biCompression = 0;
			bih.biSizeImage = 0;
			bih.biXPelsPerMeter = 0;
			bih.biYPelsPerMeter = 0;
			bih.biClrUsed = 0;
			bih.biClrImportant = 0;

			IconImage ii = new IconImage ();
			ii.iconHeader = bih;
			ii.iconColors = new uint [0];	// no palette
			int xor_size = (((bih.biBitCount * bitmap.Width + 31) & ~31) >> 3) * bitmap.Height;
			ii.iconXOR = new byte [xor_size];
			int p = 0;
			for (int y = bitmap.Height - 1; y >=0; y--) {
				for (int x = 0; x < bitmap.Width; x++) {
					Color c = bitmap.GetPixel (x, y);
					ii.iconXOR [p++] = c.B;
					ii.iconXOR [p++] = c.G;
					ii.iconXOR [p++] = c.R;
					ii.iconXOR [p++] = c.A;
				}
			}
			int and_line_size = (((Width + 31) & ~31) >> 3);	// must be a multiple of 4 bytes
			int and_size = and_line_size * bitmap.Height;
			ii.iconAND = new byte [and_size];

			ide.bytesInRes = (uint) (bih.biSize + xor_size + and_size);

			SaveIconDirEntry (writer, ide, UInt32.MaxValue);
			SaveIconImage (writer, ii);
		}
Example #12
0
File: Icon.cs Project: kumpera/mono
		private void SaveIconDirEntry (BinaryWriter writer, IconDirEntry ide, uint offset)
		{
			writer.Write (ide.width);
			writer.Write (ide.height);
			writer.Write (ide.colorCount);
			writer.Write (ide.reserved);
			writer.Write (ide.planes);
			writer.Write (ide.bitCount);
			writer.Write (ide.bytesInRes);
			writer.Write ((offset == UInt32.MaxValue) ? ide.imageOffset : offset);
		}
        /// <summary>
        /// Converts this <see cref="Bitmap"/> to an <see cref="Icon"/>.
        /// </summary>
        /// <param name="bitmap">The bitmap to convert.</param>
        public static Icon ToIcon(this Bitmap bitmap)
        {
            var bih = new BitmapInfoHeader {
                biSize          = (uint)Marshal.SizeOf(typeof(BitmapInfoHeader)),
                biWidth         = bitmap.Width,
                biHeight        = 2 * bitmap.Height, // include both XOR and AND images
                biPlanes        = 1,
                biBitCount      = 32,
                biCompression   = 0,
                biSizeImage     = 0,
                biXPelsPerMeter = 0,
                biYPelsPerMeter = 0,
                biClrUsed       = 0,
                biClrImportant  = 0
            };

            var xorSize     = (((bih.biBitCount * bitmap.Width + 31) & ~31) >> 3) * bitmap.Height;
            var andLineSize = (((bitmap.Width + 31) & ~31) >> 3);    // must be a multiple of 4 bytes
            var andSize     = andLineSize * bitmap.Height;

            var iconDirEntry = new IconDirEntry {
                width       = (byte)bitmap.Width,
                height      = (byte)bitmap.Height,
                colorCount  = 0, // 32 bbp == 0, for palette size
                reserved    = 0,
                planes      = 0,
                bitCount    = 32,
                imageOffset = 22,   // 22 is the first icon position (for single icon files)
                bytesInRes  = (uint)(bih.biSize + xorSize + andSize)
            };

            var iconImage = new IconImage {
                iconHeader = bih,
                iconColors = new uint [0],   // no palette
                iconXOR    = new byte [xorSize],
                iconAND    = new byte [andSize]
            };

            var pixel = 0;

            for (var y = bitmap.Height - 1; y >= 0; y--)
            {
                for (var x = 0; x < bitmap.Width; x++)
                {
                    var color = bitmap.GetPixel(x, y);
                    iconImage.iconXOR [pixel++] = color.B;
                    iconImage.iconXOR [pixel++] = color.G;
                    iconImage.iconXOR [pixel++] = color.R;
                    iconImage.iconXOR [pixel++] = color.A;
                }
            }

            using (var outputStream = new MemoryStream())
                using (var streamWriter = new BinaryWriter(outputStream)) {
                    streamWriter.Write((ushort)0); // idReserved must be 0
                    streamWriter.Write((ushort)1); // idType must be 1
                    streamWriter.Write((ushort)1); // only one icon

                    SaveIconDirEntry(streamWriter, iconDirEntry);
                    SaveIconImage(streamWriter, iconImage);

                    outputStream.Seek(0, SeekOrigin.Begin);
                    return(new Icon(outputStream));
                }
        }
Example #14
0
        }     // Save

        /// <summary>
        /// Saves the supplied images in .ico file format
        /// </summary>
        /// <param name="stream"></param>
        public void Save(Stream stream)
        {
            // although not strictly necessary, it's customary to
            // write the images sorted by size and bpp
            var icons = from entry in _images
                        orderby entry.Key.Size ascending, entry.Key.BitsPerPixel ascending
                select new
            {
                Image = entry.Value,
                entry.Key.SaveAs
            };

            // create icon directory header
            var iconDirHeader = new IconDirHeader(_images.Count);

            // create icon directory entries
            var entries   = new IconDirEntry[_images.Count];
            var imageData = new byte[_images.Count][];

            var index = 0;

            foreach (var icon in icons)
            {
                imageData[index] = GetIconImageData(icon.Image, icon.SaveAs);
                var entry = new IconDirEntry()
                {
                    Width       = (icon.Image.Width < 256) ? (byte)icon.Image.Width : (byte)0,
                    Height      = (icon.Image.Height < 256) ? (byte)icon.Image.Height : (byte)0,
                    ColorCount  = 0, // more than 256 colors
                    Reserved    = 0, // must be zero
                    Planes      = 1,
                    BitCount    = GetBitsPerPixel(icon.Image.PixelFormat),
                    BytesInRes  = (uint)imageData[index].Length,
                    ImageOffset = 0 // to be set later
                };
                entries[index++] = entry;
            } // foreach

            // set offsets
            var sizeOfIconDirEntry = Marshal.SizeOf <IconDirEntry>();
            var offset             = Marshal.SizeOf <IconDirHeader>() + (sizeOfIconDirEntry * _images.Count);

            for (index = 0; index < entries.Length; index++)
            {
                entries[index].ImageOffset = (uint)offset;
                offset += imageData[index].Length;
            } // for index

            // write data
            // 1. IconDirHeader
            WriteStruct(stream, iconDirHeader);

            // 2. IconDirEntries (one per icon image)
            foreach (var entry in entries)
            {
                WriteStruct(stream, entry);
            } // foreach entry

            // 3. Icon image data
            foreach (var data in imageData)
            {
                stream.Write(data, 0, data.Length);
            } // foreach
        }     // Save