Reputation: 11035
I am using the following code (based on something I found in another answer) to convert an image (usually it's a PNG added to project resources) to an Icon for use in form titles and such.
public static Icon IconFromImage(Image img)
{
using (var bmp = new Bitmap(img))
{
Byte[] ba;
using (var ms = new MemoryStream())
{
bmp.Save(ms, ImageFormat.Png);
ms.Seek(0, SeekOrigin.Begin);
ba = ms.ToArray();
}
using (var imgData = new MemoryStream())
using (var writer = new BinaryWriter(imgData))
{
if (writer != null)
{
//Header (6 bytes)
writer.Write((Byte)0); // 0 reserved: set to 0
writer.Write((Byte)0); // 1 reserved: set to 0
writer.Write((Int16)1); // 2-3 image type: 1 = icon, 2 = cursor
writer.Write((Int16)1); // 4-5 number of images
//Image entry #1 (16 bytes)
writer.Write((Byte)bmp.Width); // 0 image width
writer.Write((Byte)bmp.Height); // 1 image height
writer.Write((Byte)0); // 2 number of colors
writer.Write((Byte)0); // 3 reserved
writer.Write((Int16)0); // 4-5 color planes
writer.Write((Int16)32); // 6-7 bits per pixel
writer.Write(ba.Length); // 8-11 size of image data
writer.Write(6 + 16); // 12-15 offset to image data
//Write image data
writer.Write(ba); // PNG data must contain the whole PNG data file!
writer.Flush();
writer.Seek(0, SeekOrigin.Begin);
return new Icon(imgData,16,16);
}
}
}
return null;
}
From image to Icon works fine. But there is one instance where I need to grab that form's title Icon and get an Image back from that. This used to work when I was using actual file-based ICO files for the title images, but now that I'm using the conversion code to get the Icon for the form, the resulting PNGs look horrible.
Form's title Icon:
Image rendered using Bitmap.FromHicon(new Icon(theForm.Icon, new Size(16, 16)).Handle)
:
(Note: used to use theForm.Icon.ToBitmap()
, but that now errors)
I read a comment on another post where a user stated that if PNG is used to derive the Icon, then coming back to image would be bad "because PNGs have more than one bit of transparency". If that is the problem I am experiencing, then what can I do about it?
Upvotes: 3
Views: 2332
Reputation: 125312
You can use IconBitmapDecoder
to get icon stream preserving pixel format and the using PngBitmapEncoder
save that stream in a png image:
using System.Drawing;
using System.Windows.Media.Imaging;
class IconHelper
{
public static Bitmap PngFromIcon(Icon icon)
{
Bitmap png = null;
using (var iconStream = new System.IO.MemoryStream())
{
icon.Save(iconStream);
var decoder = new IconBitmapDecoder(iconStream,
BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.None);
using (var pngSteam = new System.IO.MemoryStream())
{
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(decoder.Frames[0]);
encoder.Save(pngSteam);
png = (Bitmap)Bitmap.FromStream(pngSteam);
}
}
return png;
}
}
To use those classes you need to add a reference to PresentationCore
, WindowsBase
and System.Xaml
. Then the usage would be:
this.pictureBox1.Image = IconHelper.PngFromIcon(this.Icon);
And the result is the same as the original png which you used to create the icon.
Upvotes: 3
Reputation: 3724
Try Bitmap.FromHicon(this.Icon.Handle), you may get better results. At the least ToBitmap() seems to barf if the png has compression: Displaying an icon in a picturebox, http://community.sharpdevelop.net/forums/t/21851.aspx
Upvotes: 0