How does one convert between System.Drawing.Icon type and byte[]? I'm looking for something simple that can (hopefully) work in .NET2.
views:
79answers:
3
+3
A:
You go via a MemoryStream, basically:
public static byte[] IconToBytes(Icon icon)
{
using (MemoryStream ms = new MemoryStream())
{
icon.Save(ms);
return ms.ToArray();
}
}
public static Icon BytesToIcon(byte[] bytes)
{
using (MemoryStream ms = new MemoryStream(bytes))
{
return new Icon(ms);
}
}
(Historical note: I wasn't sure whether or not it was safe to dispose of the stream passed to the constructor. It isn't safe to do so for Bitmap, for example... that holds on to the stream and may read from it later. Apparently it's okay for Icon though. I wish MSDN made this clearer...)
Jon Skeet
2010-07-15 16:50:03
It's worth pointing out that the bytes "saved" here are the exact same as the bytes written to a file (so it includes file header, any applicable compression, etc) not the bytes of the image itself.
Neil N
2010-07-15 16:53:33
Yes, you could make it a bitmap and extract the array of pixels if you need to.
lasseespeholt
2010-07-15 16:56:15
Just curious, you wrapped `MemoryStream` neatly in a using-block, why didn't you do equally so in the reverse `BytesToIcon` method? No need to dispose the ms anymore?
Abel
2010-07-15 16:56:30
I can verify that Icon reads the stream as soon as it's constructed.
BC
2010-07-15 16:58:40
@BC: Thanks - duly wrapped in a `using` statement now :)
Jon Skeet
2010-07-15 17:42:37
@Jon Skeet: I feel totally overlooked now! lol
Abel
2010-07-15 18:27:29
Thanks! I had hit a dead end with the Bitmap conversion route.
emptyset
2010-07-15 19:41:44
+1
A:
Ex (there are multiple ways)
private byte[] GetBytes( Icon icon )
{
MemoryStream ms = new MemoryStream();
icon.Save( ms );
return ms.ToArray();
}
And:
Bitmap bmpIcon = icon.ToBitmap();
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
bmpIcon.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
return ms.ToArray();
}
lasseespeholt
2010-07-15 16:51:15
No, don't call `GetBuffer` - that may well have extraneous 0s at the end. `ToArray` is the right call to use.
Jon Skeet
2010-07-15 16:52:24
Thanks, noted. I really just copied stuff from the link. There are multiple solutions in it. 20 secs on Google :)
lasseespeholt
2010-07-15 16:55:01
+1
A:
... And back again
public static Icon IconFromBytes(byte[] bytes) {
using(var ms = new MemoryStream(bytes)) {
return new Icon(ms);
}
}
The Icon class reads from the stream as soon as it's constructed. No harm in closing MS.
BC
2010-07-15 16:53:22
Care to elaborate? I agree that MemoryStream doesn't need a disposal because it doesn't have unmanaged resources... but it reinforces the whole idea of calling dispose when IDisposable is implemented.
BC
2010-07-15 17:39:28
@Hans Passant: not sure what you mean, but perhaps you mean to ask what Dispose does? If a class implements `IDisposable`, it is close to mandatory to wrap it in a using-block. Due to the the lack of multiple inheritance in .NET, certain classes implement `IDisposable` while they technically wouldn't need to. MemoryStream is a class that implements unmanaged code (WaitHandle) and requires that you use `using` or try/finally. It is applied correctly here. In cases where it isn't needed (some implementations of IComponent come to mind), it is often still best to use `using` for clarity.
Abel
2010-07-15 18:26:06
PS: if you need an example, see how Jon Skeet corrected his own code after my comment on Dispose.
Abel
2010-07-15 18:26:52
Hmya, we'll have to agree about disagreeing about this. Note that I didn't actually vote it down, it was merely a poke in the eye.
Hans Passant
2010-07-15 18:37:54