System.Drawing.Image.FromStream (objMemoryStream).....exception - Invalid parameter used

G'day,

I've been working on some code that extracts SQL server Image fields to Byte() arrays then converts them, via this little function, to a System.Drawing.Image. I use a collection of images through out the entire application.
Now this has been passing in Nunit tests until the 12th July 2005. Now it fails. Where do I begin to solve a problem like this?



PublicFunction ConvertTo(ByVal ImageArrayAsByte())As System.Drawing.Image

'<summary>

' Convert a SQL Server database byte Array (byte array) to a Image.

'</summary>

Dim objMSAs System.IO.MemoryStream

Dim objImageAs System.Drawing.Image

objMS =New System.IO.MemoryStream(ImageArray)

' Convert the database byte array to a System Drawing Image.

ConvertTo = System.Drawing.Image.FromStream(objMS)' From the 13th July 2005 this suddenly fails during unit testing.

'<comments>

' Tried the following but it failed unit testing with a similar exception.

' ConvertTo = System.Drawing.Image.FromStream(CType(objMS, System.IO.Stream), False, False)

'</comments>

'<comments>

' Tried advice in http://support.microsoft.com/?id=814675 to resolve the problem.

' Similar errors occured on the Memory stream to Image/Bitmap conversion. The

'</comments>

EndFunction

[3497 byte] By [JamieClayton] at [2007-12-16]
# 1

Unfortunately GDI+ can be a little obtuse when it comes to error messages. My assumption is that the ImageArray that you are passing it contains an invalid image format.

You also should look at disposing your MemoryStream, VB 2005 makes that easy by introducing the new Using keyword.

DavidM.Kean-MSFT at 2007-9-9 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 2

David,

I would come to the same conclusion when I reviewed my unit tests when it first occured, but I've tinkered for days trying to get this code to work (including lots of test images). I must admit that my Unit test database scripts have not been kept well enough around this date for me to replicate the problem via a regression in .net service packs/OS service packs. Of our 255 odd unit tests, image related ones are failing the most.

Based on the number of hits on this subject, its obviously a concern to the community at large. We migrated the solution to vs2005 and still get the same failure. Could you elaborate on the suggestion about "Using" keyword.

I'm frustrated that is seams so hard to get an image stream converted from a database and placed on a VB.net windows form via code.

Our cludgy solution is to write the database image stream to the users profile application path, then load the image from there. It's a massive performance hit to our graphical application not to mention a potential failure point in a corporate environment where users often exceed there profile space. Our client is also disappointed with the performace of the solution and the effort we have put into the work around.

JamieClayton at 2007-9-9 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 3
I'm not sure whether this issue was ever resolved but I'll let you know how I got around my "generic GDI+" errors. I declared a MemoryStream object at the class level. When I retrieved an image from SQL Server created a new MemoryStream object and created an Image object from that. At that point the stream was not Disposed or even Closed. This allows GDI+ to access the stream if required as detailed in that MSDN support topic you mentioned. If the Image object was ever Disposed I would Close and Dispose the stream as well, setting the variable to Nothing. When I wanted to get another image from the database I would test this variable and if it was not Nothing I would Close and Dispose it before creating a new one. In my app I only ever had a single image retrieved from the database at any one time. You would need to modify this a little if you are opening multiple images.
jmcilhinney at 2007-9-9 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 4
In addition to the other comments the northwind database offsets the image by 78. There is an example on the vb-tips website on how to get the image from the database.
KenTucker at 2007-9-9 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 5

Ken,

Thanks for you response. I've made a subtle change the function above to make the code work in VS 2005.


Public Overloads Function ConvertTo(ByVal ImageArray As Byte()) As System.Drawing.Image

'<summary>

' Convert a SQL Server database byte Array (byte array) to a Image.

'</summary>

Dim objMS As New System.IO.MemoryStream

objMS.Write(ImageArray, 0, ImageArray.Length)

Try

ConvertTo = System.Drawing.Image.FromStream(objMS)

Catch ae As System.ArgumentException

ConvertTo = Nothing

End Try

End Function


I must admit that I've invested a lot of time with the System.IO.*Stream* code with mixed results and this seems to be another example of subtlies of programming. I've also invested considerable time (3 working weeks) trying to get image loading and custom generation via memory streams to and from databases and files with very mixed results. This should increase the load time of our forms from 3 seconds per image (unlimited number of images) to 3 seconds for the whole form. Thanks.
JamieClayton at 2007-9-9 > top of Msdn Tech,Visual Basic,Visual Basic Language...