views:

3034

answers:

6

Hello,

I am capturing images from a smart camera imager and receiving the byte array from the camera through socket programming (.NET application is the client, camera is the server).

The problem is that i get System.InvalidArgument exception at runtime.

private Image byteArrayToImage(byte[] byteArray) {
   if(byteArray != null) {
      MemoryStream ms = new MemoryStream(byteArray);
      return Image.FromStream(ms, false, false); 
      /*last argument is supposed to turn Image data validation off*/
   }
   return null;
}

I have searched this problem in many forums and tried the suggestions given by many experts but nothing helped.

I dont think there is any problem with the byte array as such because When i feed the same byte array into my VC++ MFC client application, i get the image. But this doesn't somehow work in C#.NET.

Can anyone help me ?

P.S :

Other methods i've tried to accomplish the same task are:

1.

  private Image byteArrayToImage(byte[] byteArray) {
     if(byteArray != null) {
        MemoryStream ms = new MemoryStream();
        ms.Write(byteArray, 0, byteArray.Length);
        ms.Position = 0; 
        return Image.FromStream(ms, false, false);
     }
     return null;
  }

2.

  private Image byteArrayToImage(byte[] byteArray) {
     if(byteArray != null) {
        TypeConverter tc = TypeDescriptor.GetConverter(typeof(Bitmap));
        Bitmap b = (Bitmap)tc.ConvertFrom(byteArray);
        return b;
     }
     return null;
  }

None of the above methods worked. Kindly help.

+1  A: 

System.InvalidArgument means The stream does not have a valid image format, i.e. an image type that is not supported.

Mitch Wheat
Hello,Thanks for the reply.But how come the same byte array works in my VC++ MFC application ?Also is there any way i could check the validity of my byte array image data ?Arvind K
A: 

I've had the same problem in the past and it was caused by a leak within the windows GDI libraries, which is what 'Bitmap' uses. If this happening all the time for you then its probably unrelated, however.

Chris
Hello Chris,Thanks for the reply.It happens to me everytime i run the code.
+2  A: 

I'm guessing that something is going wrong when receiving the file from the server. Perhaps you're only getting part of the file before trying to convert it to an Image? Are you sure it's the exact same byte array you're feeding the C++ application?

Try saving the stream to a file and see what you get. You might be able to uncover some clues there.

You can also add a breakpoint and manually compare some of the bytes in the byte array to what they're supposed to be (if you know that).


Edit: It looks like there's nothing wrong with receiving the data. The problem is that it's in raw format (not a format that Image.FromStream understands). The Bitmap(Int32, Int32, Int32, PixelFormat, IntPtr) constructor may be of use here. Or, you can create the blank bitmap and blt it manually from the raw data.

lc
Hello,I tried saving the image to a jpg, bmp file but i don't get the picture in the file.What is puzzling is that it is with the same byte array that i am able to display image in my VC++ MFC application.
That's why I'm not so sure it's the same byte array. Are the file sizes the same?
lc
The VC++ application displays live images from the camera and therefore what i did was writing the byte array to a txt file. Similarly, from my .NET appln i wrote the byte array to a file nad then compared these two files. I find that all the values are filled and they are more or less the same.
Infact, i tried feeding the array i got from VC++ application (in txt file) to my C#.NET application. This failed too :-(
The byte array will not be same everytime due to intensity fluctuations of light falling on camera's lens. So, what i observed was some minor variations in byte array values between VC++ log and C# log
Interesting. What format is the image supposed to be in?
lc
Maybe your C++ code just paint the camera's captured image directly on the screen, so it is not a formatted image (e.g. Jpg, png, bmp, etc), hence Image.FromStream could not work
Michael Buen
The camera send raw data which is of no format(no compression).
Hello Michael,Yes, you are right. The image array is not formatted. How do i proceed in that case ? Please help
Btw, is it a text file, as in ascii-readable text? Or just .txt file extension? Also try to check the file marker, if it is indeed a valid image format
Michael Buen
Try copy paste, i tried that approach with the raw image i get from camera in vb6 using winapi component, luckily the vb6 image control has paste method. Maybe .net image control has paste method too
Michael Buen
Hi Michael Buen,It is just a .txt file extension with byte array values in human readable format.What is this copy paste approach using winapi component ? Could you kindly elaborate in little more detail since i am not aware of it ?
try this: http://channel9.msdn.com/forums/TechOff/93476-Programatically-Using-A-Webcam-In-C/ using api from windows built-in avicap32.dll http://weblogs.asp.net/nleghari/articles/webcam.aspx
Michael Buen
Many thanks Michael, i will give it a try !!
A: 

Crap, that's exactly my problem as well, surfing for 3 days in the internet trying to find a solution on this, the byte[] you get is correct (working with a camera as well - but using COM) if I create an image manually (with setPixel) I get the Image as it's displayed. But this is a very very slow function - has anyone a faster workaround to manually create a picture from byte[]???

A: 

I've had this problem when doing this:

MemoryStream stream = new MemoryStream();
screenshot.Save(stream, ImageFormat.Png);
byte[] bytes = new byte[stream.Length];
stream.Save(bytes, 0, steam.Length);

With the last 2 lines being the problem. I fixed it by doing this:

MemoryStream stream = new MemoryStream();
screenshot.Save(stream, ImageFormat.Png);
byte[] bytes = stream.ToArray();

And then this worked:

MemoryStream stream = new MemoryStream(bytes);
var newImage = System.Drawing.Image.FromStream(stream);
stream.Dispose();
NotDan
A: 

Maybe the image is embedded in an OLE field and you have to consider the 88 bytes OLE header plus payload:

byteBlobData = (Byte[]) reader.GetValue(0);
stream = new MemoryStream(byteBlobData, 88, byteBlobData.Length - 88);
img = Image.FromStream(stream);
Jose Martin