How to convert an image to an icon without losing transparency?

后端 未结 1 2013
我寻月下人不归
我寻月下人不归 2020-11-30 11:57

I have PNG images which I need to convert to an icon before displaying it.

This is how I did it:

public Icon ImageToIcon(Image imgTest)
{
    Bitmap          


        
相关标签:
1条回答
  • 2020-11-30 12:04

    No, there's a lot more to it. Icons have a pretty elaborate internal structure, optimized to work reasonably on 1980s hardware. An icon image has three bitmaps, one for the icon, a monochrome bitmap that indicates what parts of the image are transparent and another monochrome bitmap that indicates what parts are reversed. Generating those monochrome bitmaps is pretty painful, .NET doesn't support them. Nor does Bitmap.GetHicon() make an attempt at it. You'll need a library to do the work for you.

    Vista gave some relief, it started supporting icons that contain a PNG image. You'll have a shot at generating it with your own code. Like this:

        public static Icon IconFromImage(Image img) {
            var ms = new System.IO.MemoryStream();
            var bw = new System.IO.BinaryWriter(ms);
            // Header
            bw.Write((short)0);   // 0 : reserved
            bw.Write((short)1);   // 2 : 1=ico, 2=cur
            bw.Write((short)1);   // 4 : number of images
            // Image directory
            var w = img.Width;
            if (w >= 256) w = 0;
            bw.Write((byte)w);    // 0 : width of image
            var h = img.Height;
            if (h >= 256) h = 0;
            bw.Write((byte)h);    // 1 : height of image
            bw.Write((byte)0);    // 2 : number of colors in palette
            bw.Write((byte)0);    // 3 : reserved
            bw.Write((short)0);   // 4 : number of color planes
            bw.Write((short)0);   // 6 : bits per pixel
            var sizeHere = ms.Position;
            bw.Write((int)0);     // 8 : image size
            var start = (int)ms.Position + 4;
            bw.Write(start);      // 12: offset of image data
            // Image data
            img.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
            var imageSize = (int)ms.Position - start;
            ms.Seek(sizeHere, System.IO.SeekOrigin.Begin);
            bw.Write(imageSize);
            ms.Seek(0, System.IO.SeekOrigin.Begin);
    
            // And load it
            return new Icon(ms);
        }
    

    Tested on .NET 4.5 and Windows 8.1. Beware of the possibility of "fringes" you'll see on PNG images with transparency on the edges. That only works well when the image is displayed on a well-known background color. Which, by design, an icon can never depend on. A dedicated icon editor will always be the only truly good way to get good looking icons.

    0 讨论(0)
提交回复
热议问题