11

I am trying to convert a byte[] to Bitmap in c#. Following is the code:

MemoryStream ms = new MemoryStream(b);
Bitmap bmp = new Bitmap(ms);

It shows the error Parameter is not valid when creating the Bitmap.

byte[] b is coming from a network stream.

But when I write this byte[] to a file, and open this file in any image viewer just works perfectly. Following is code for writing the byte[] to file:

 var fs = new BinaryWriter(new FileStream("tmp.bmp", FileMode.Create, FileAccess.Write));
 fs.Write(b);
 fs.Close();

What am I missing here?

EDIT

Here is my full code that was causing problem

 Socket s = listener.AcceptSocket();
 byte[] b = new byte[imgLen];
 s.Receive(b);
 MemoryStream ms = new MemoryStream(b);
 // now here I am using ms.Seek(0, SeekOrigin.Begin); that fixed my problem.
 Bitmap bmp = new Bitmap(ms);
 pictureBox1.Image = bmp;
 s.Close();

I am using this code on Form_Load event and there is nothing extra. I am just trying to display an Image that is streamed on network. The server is written in Java that is streaming this image.

Hope it clarifies the doubts.

Thanks

4
  • Have you tried using Image.FromStream instead? I can't think of why that might work, but it's worth a try... Commented Mar 12, 2011 at 20:19
  • 1
    Tried Image.FromStream but that also didn't worked. Commented Mar 12, 2011 at 20:23
  • @Jon It's too late Jon, Darin's got you this week! Commented Mar 12, 2011 at 20:24
  • Can you show a (minimalized) full working part of the code that throws this error? Perhaps the error comes from a bug somewhere else. Also: that you can open the image in a viewer does not mean necessarily that the image data is valid for GDI+ to understand. What happens if you open tmp.bmp from disk using MemoryStream? Commented Mar 12, 2011 at 20:31

4 Answers 4

16

Okay, just to clarify things a bit... the problem is that new Bitmap(ms) is going to read the data from the stream's current position - if the stream is currently positioned at the end of the data, it's not going to be able to read anything, hence the problem.

The question claims that the code is this:

MemoryStream ms = new MemoryStream(b);
Bitmap bmp = new Bitmap(ms);

In that case there is no requirement to reset the position of the stream, as it will be 0 already. However, I suspect the code is actually more like this:

MemoryStream ms = new MemoryStream();
// Copy data into ms here, e.g. reading from NetworkStream
Bitmap bmp = new Bitmap(ms);

or possibly:

MemoryStream ms = new MemoryStream(b);
// Other code which *reads* from ms, which will change its position,
// before we finally call the constructor:
Bitmap bmp = new Bitmap(ms);

In this case you do need to reset the position, because otherwise the "cursor" of the stream is at the end of the data instead of the start. Personally, however, I prefer using the Position property instead of the Seek method, just for simplicity, so I'd use:

MemoryStream ms = new MemoryStream();
// Copy data into ms here, e.g. reading from NetworkStream

// Rewind the stream ready for reading
ms.Position = 0;
Bitmap bmp = new Bitmap(ms);

It just goes to show how important it is that the sample code in a question is representative of the actual code...

Sign up to request clarification or add additional context in comments.

7 Comments

I am using MemoryStream ms = new MemoryStream(b); to create memory stream!
@Vinod: Then you must be doing something else with it before calling the Bitmap constructor... because the initial position of a stream constructed that way is 0. If you could post the full code involved, we could help further... but I don't believe you're creating the MemoryStream for a byte array and then immediately calling new Bitmap(ms). If you were, rewinding simply would not help.
you write // Other code which *reads* from ms, which will change its position. It wouldn't be the first time that I see people debugging step by step, hovering over with the mouse, invoking getters, invoking side effects. Or use the Immediate window. This is a perfect example where the side effects might cause behavior that only works (throws) in a debugging environment.
@Abel: Indeed. I wouldn't expect that to be the problem here though, as I'd only expect the OP to be debugging into this code if it's already shown a problem. It would have to be a watch or the immediate window, as I don't believe any of the property getters in Stream mutate it.
I am not doing anything with the memory stream. My task is only to read the byte[] and create a bitmap from it. I have edited my question that shows the full actual code I am using apart from that I am not using anything. Please have a look at that. The byte[] stream is coming from server written in java.
|
7

Try resetting current location in the stream

MemoryStream ms = new MemoryStream(b);
ms.Seek(0, SeekOrigin.Begin);
Bitmap bmp = new Bitmap(ms);

7 Comments

That was my first thought, but there's no need for that when you construct a MemoryStream directly from a byte array.
Thanks! I was stretching my heads from past 2 hrs and searched with google also but didn't found any solution. You are great man! Thanks again :)
So, apparently, there was a need after all, or there was code involved that we didn't see ;).
@Jon, I've never figured out a good rule when you need to reset the stream and when you don't.
I've added an answer now to explain what's going on, and why you don't need to do this in the case actually shown in the question, but do need to do this when you've written into the memory stream.
|
1

Try like this:

byte[] b = ...
using (var ms = new MemoryStream(b))
using (var bmp = Image.FromStream(ms))
{
    // do something with the bitmap
}

6 Comments

Firstly I'd use Image.FromStream instead of Bitmap.FromStream (as it's defined in Image, not Bitmap) and secondly I can't see how that will affect the constructor working or not.
@Vinod Maurya, I have just tested this code by having b = File.ReadAllBytes("test.png"); and it successfully loaded into the bitmap. @Jon, you are correct about Image.
@Darin, I just tested the same in my code and I got the same error. I am not reading the bytes from file in fact my bytes are coming from network stream so this may be causing the problem. I just used ms.Seek(0, SeekOrigin.Begin); suggested by Albin and now my code is working perfectly! anyways Thanks for the quick reply!
I'd be interested to know why Darin's code works without SeekOrigin.Begin... Mm, possibly MemoryStream is not the actual underlying stream?
@Abel: When it's actually creating the MemoryStream from a byte array, it's positioned at the start by default. However, I believe the code posted in the question wasn't a fair representation of the real code.
|
0

Error is shown if you are disposing the image. Try removing that from code

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.