Come convertire un’immagine in un’icona senza perdere la trasparenza?

Ho immagini PNG che ho bisogno di convertire in un’icona prima di visualizzarla.

Ecco come l’ho fatto:

public Icon ImageToIcon(Image imgTest) { Bitmap bitmap = new Bitmap(imgTest); Icon icoTest; IntPtr iPtr = bitmap.GetHicon(); icoTest = (Icon) Icon.FromHandle(iPtr).Clone(); return icoTest; } 

Perdo la trasparenza dopo averlo fatto, le immagini alfa trasparenti non sono rese come previsto … può essere risolto?

No, c’è molto di più. Le icone hanno una struttura interna piuttosto elaborata, ottimizzata per funzionare ragionevolmente sull’hardware degli anni ’80. Un’immagine icona ha tre bitmap, una per l’icona, una bitmap monocromatica che indica quali parti dell’immagine sono trasparenti e un’altra bitmap monocromatica che indica quali parti sono invertite. La generazione di tali bitmap monocromatiche è piuttosto dolorosa, .NET non li supporta. Bitmap.GetHicon () non tenta nemmeno di farlo. Avrai bisogno di una biblioteca per fare il lavoro per te.

Vista ha dato un po ‘di sollievo, ha iniziato a supportare icone che contengono un’immagine PNG. Avrai una possibilità di generarlo con il tuo codice. Come questo:

  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); } 

Testato su .NET 4.5 e Windows 8.1. Fai attenzione alla possibilità di “frange” che vedrai sulle immagini PNG con trasparenza sui bordi. Funziona bene solo quando l’immagine viene visualizzata su un noto colore di sfondo. Quale, dal design, un’icona non può mai dipendere. Un editor di icone dedicato sarà sempre l’unico vero modo per ottenere icone di bell’aspetto.