tags:

views:

79

answers:

3

How does one convert between System.Drawing.Icon type and byte[]? I'm looking for something simple that can (hopefully) work in .NET2.

+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
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
Yes, you could make it a bitmap and extract the array of pixels if you need to.
lasseespeholt
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
I can verify that Icon reads the stream as soon as it's constructed.
BC
@BC: Thanks - duly wrapped in a `using` statement now :)
Jon Skeet
@Jon Skeet: I feel totally overlooked now! lol
Abel
Thanks! I had hit a dead end with the Bitmap conversion route.
emptyset
+1  A: 

See: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/1551fd3b-02b6-4479-852a-dfea4b610c35

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
No, don't call `GetBuffer` - that may well have extraneous 0s at the end. `ToArray` is the right call to use.
Jon Skeet
Thanks, noted. I really just copied stuff from the link. There are multiple solutions in it. 20 secs on Google :)
lasseespeholt
+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
+1 for using `using` :)
Abel
-1 for not understanding what Dispose() does.
Hans Passant
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
@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
PS: if you need an example, see how Jon Skeet corrected his own code after my comment on Dispose.
Abel
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