Search code examples
c#iconsfile-format

Storing BMP in icon file


I have a program to combine graphics files in an icon. Sizes include 16,24,32,48,256 32bit. These use PNG and works. I have correct header and directory/index record list.

However, for 8 bit I am using BMP with the first 14 bytes of the header of a BMP stripped off. This part of the icon file does not work. Having looked at a MS icon they have BMP stored again with the 14 byte header removed. Looking at their BMP data they have the second header as I do but for 16x16 the second header (BITMAPINFOHEADER) says 16x32. The BMP seams to be twice the width. Why? Is the image twice the width with a bit mask or something?

Here's my code: (Note image is 32x32 bitmap 32bit when passed.)

using (Bitmap imageAsBitmap = new Bitmap(image))
{
    int colorCount = 0;
    using (Bitmap bitmap = imageAsBitmap.ColourReduction256(out colorCount))
    {
        byte[] imageBytes = new byte[] { };
        using (MemoryStream ms = new MemoryStream())
        {
            bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
            imageBytes = ms.ToArray();
        }
        byte[] data = new byte[] { };
        Array.Resize(ref data, imageBytes.Length - 14);
        Array.Copy(imageBytes, 14, data, 0, data.Length);
        enteries.Add(new IconEntry(data, image.Width, image.Height, 8));
    }
}

Solution

  • Yes, you are right:

    Images with less than 32 bits of color depth follow a particular format: the image is encoded as a single image consisting of a color mask (the "XOR mask") together with an opacity mask (the "AND mask")[..]

    What results in:

    [..] the masks must each be of the same dimensions, and the height specified in the BMP header must be exactly twice the height specified in the ICONDIRENTRY structure

    Take a look here: https://en.wikipedia.org/wiki/ICO_(file_format)