25

If I have image data in an NSData, extracted from the image as follows, how do I convert this NSData object into a byte array?

NSData data = NSData.FromUrl(NSUrl.FromString(urlString));
ctacke
  • 66,480
  • 18
  • 94
  • 155
BruceHill
  • 6,954
  • 8
  • 62
  • 114
  • The question is: why are you doing that? If you need to get data from an URL, just use .NET's WebClient classes. – Krumelur Jun 07 '11 at 07:46
  • The reason that I need to do this is because the WebClient in MonoTouch seems to cause my application to crash at startup. If I exclude the reference to the WebClient the application starts up normally. And the WebClient code is not even in a startup event, it is in a TouchDown event handler. So that is why I was looking for an alternative solution to WebClient. – BruceHill Jun 07 '11 at 09:35

3 Answers3

45
NSData data = NSData.FromUrl(NSUrl.FromString(urlString));

byte[] dataBytes = new byte[data.Length];

System.Runtime.InteropServices.Marshal.Copy(data.Bytes, dataBytes, 0, Convert.ToInt32(data.Length));
Kirk Woll
  • 76,112
  • 22
  • 180
  • 195
Timo
  • 1,088
  • 1
  • 10
  • 19
  • Thanks, Timo. I used a different solution (see the answer that I posted), but I tested your solution too and it works well. So I am going to give you the credit for this answer and mark it as the accepted solution. Thanks. – BruceHill Jun 07 '11 at 09:32
  • 2
    For base64 encoding images, this is crucial. We ended up with corrupt images because we were using data.ToArray(). – kwcto Sep 25 '13 at 19:42
28

I got an answer to this question from the reply by Dimitris Tavlikos to this question I asked:

How to read the contents of a local image into a base64 string in MonoTouch

From that answer I learnt that if you include a reference System.Linq then the NSData object will have a ToArray() method that will return an array of bytes. So with this namespace referenced you can do the following:

bytes[] dataBytes = data.ToArray();

Hope this info helps someone else.

Community
  • 1
  • 1
BruceHill
  • 6,954
  • 8
  • 62
  • 114
  • 4
    I found this method to be significantly slower than [Timo's solution](http://stackoverflow.com/a/6241501/458193) for bigger images. – Dan Abramov Jun 29 '12 at 14:30
  • 1
    @The person who downvoted: If you think the answer is so bad that it needs downvoting, at least have the courage to leave a comment saying **why** you downvoted it. – BruceHill Sep 11 '12 at 15:56
  • Hey, I'm sorry for not acknowledging my downvote. I revisited the question a couple of days ago and used your method because it had the most votes, only to find that I've already been here (I forgot!) and already found this method to be significantly slower than Timo's. You're right the answer is not bad, and more importantly, does not meet the criteria of “not being useful”. It was not useful to me, but it is certainly useful to anybody looking for a reasonably performant one-liner. My downvoting was emotional and wrong so I amend that. – Dan Abramov Sep 11 '12 at 20:53
  • Hi Dan. Thanks for acknowledging the downvote, for explaining the situation that prompted it and for reversing the downvote. I appreciate it. Thanks also for the information on the performance difference between the two solutions. My application works with small images so I never had the need to do performance testing of the solutions, but I'm sure that this information will help other people where performance is an issue. I'm curious though why the performance of the `ToArray` method is bad. Maybe this is something that someone at Monotouch could look at and correct. Thanks for your comments. – BruceHill Sep 12 '12 at 07:31
  • 1
    Performance differences aside, we have been experiencing data consistency issues when POSTing UIImages as Base64 encoded PNGs over HTTP. Migrating from .ToArray() to the System.Runtime.InteropServices.Marshal.Copy method eliminated the corrupt PNG files that were ending up on the server. – kwcto Sep 25 '13 at 19:40
  • Thanks for sharing the issues you encountered, bayfrontconsulting. – BruceHill Sep 26 '13 at 12:30
7

Timo's answer as an extension method:

    public static byte[] ToByteArray (this NSData data) {
        var dataBytes = new byte[data.Length];
        System.Runtime.InteropServices.Marshal.Copy(data.Bytes, dataBytes, 0, Convert.ToInt32(data.Length));
        return dataBytes;
    }
Herman Schoenfeld
  • 8,464
  • 4
  • 38
  • 49