I don't know why this fixes this... any ideas? (System.Drawing.Image.FromStream "parameter is not v

B

bookon

I was running into the System.Drawing.Image.FromStream "parameter is
not valid" on some of the images I was retrieving from a blob column in
Sql Server. I thought there were corrupt images as almost all worked
(all are gifs), and only a few broke when this line ran: Image img =
Image.FromStream(ms); here is the original code:

b = (byte[])dt.Rows.ItemArray[1];
//b.ToString()
ms = new MemoryStream();
ms.Write(b, 0, b.Length);


Image.GetThumbnailImageAbort callback = new
System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
IntPtr callbackData = new IntPtr(0);

try
{

Image img = Image.FromStream(ms);
...do something with image...
}


I created a StringBulider object with the intention of examining the
contents of "sb" as a file, but simply the act of doing this fixed
the problem and ALL images now work fine.

StringBuilder sb = new StringBuilder();

b = (byte[])dt.Rows.ItemArray[1];
//b.ToString()
foreach (Byte bt in b)
{
sb.Append(bt);

}
ms = new MemoryStream();

ms.Write(b, 0, b.Length);

StreamWriter sw = new StreamWriter(ms);

sw.Write(sb.ToString());


Image.GetThumbnailImageAbort callback = new
System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
IntPtr callbackData = new IntPtr(0);

try
{

Image img = Image.FromStream(ms, false, false);
...do something with image...
}



As you can see merely the act of passing 'ms' as a parameter to a
StreamWriter fixes it. OR The steps I take to be able to do, such as
the foreach loop or the sw.Write(). "ms" appears the same before and
after being passed.

Any ideas on why this fixes my problem would be great.


Thanks.
 
M

Marc Gravell

It looks like you have left the stream at the end... if you use the
overloaded ctor you don't have to worry about this:

ms = new MemoryStream(b);
// snip
Image img = Image.FromStream(ms);

Marc
 
B

bookon

Marc said:
It looks like you have left the stream at the end... if you use the
overloaded ctor you don't have to worry about this:

ms = new MemoryStream(b);
// snip
Image img = Image.FromStream(ms);

Marc

Thanks...

I only showed one version. I tried all three (ms),
(ms,false/true),(ms,false/true,false/true) with no difference.
 
M

Mythran

Thanks...

I only showed one version. I tried all three (ms),
(ms,false/true),(ms,false/true,false/true) with no difference.

What I believe Marc meant was to use the MemoryStream's overloaded
constructor that takes a byte-array as a parameter. What you are doing is
using the default constructor and then writing the byte-array to the stream.
In other words, instead of writing the byte-array to the stream, directly,
you can just pass the byte-array into the constructor of the MemoryStream
and it will automatically be written by the MemoryStream without any extra
processing on your part:

ms = new MemoryStream(b); // This line here.
....
Image img = Image.FromStream(ms); // This just shows passing the stream
after it's created.


HTH,
Mythran
 
B

bookon

Mythran said:
What I believe Marc meant was to use the MemoryStream's overloaded
constructor that takes a byte-array as a parameter. What you are doing is
using the default constructor and then writing the byte-array to the stream.
In other words, instead of writing the byte-array to the stream, directly,
you can just pass the byte-array into the constructor of the MemoryStream
and it will automatically be written by the MemoryStream without any extra
processing on your part:

ms = new MemoryStream(b); // This line here.
...
Image img = Image.FromStream(ms); // This just shows passing the stream
after it's created.


HTH,
Mythran

I see... wrong ctor :)


I tried this:


b = (byte[])dt.Rows.ItemArray[1];

ms = new MemoryStream(b);



Image.GetThumbnailImageAbort callback = new
System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
IntPtr callbackData = new IntPtr(0);




try
{

Image img = Image.FromStream(ms);
...do stuff here with image...
}

to no avail...

in fact using the ms = new MemoryStream(b) instead of ms.Write(b, 0,
b.Length) using the current StreamWiter fix causes a memory stream not
expandable error.


Any ideas why the streamwriter fixes this currently?


Thanks.
 
M

Mythran

What I believe Marc meant was to use the MemoryStream's overloaded
constructor that takes a byte-array as a parameter. What you are doing
is
using the default constructor and then writing the byte-array to the
stream.
In other words, instead of writing the byte-array to the stream,
directly,
you can just pass the byte-array into the constructor of the MemoryStream
and it will automatically be written by the MemoryStream without any
extra
processing on your part:

ms = new MemoryStream(b); // This line here.
...
Image img = Image.FromStream(ms); // This just shows passing the stream
after it's created.


HTH,
Mythran

I see... wrong ctor :)


I tried this:


b = (byte[])dt.Rows.ItemArray[1];

ms = new MemoryStream(b);



Image.GetThumbnailImageAbort callback = new
System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
IntPtr callbackData = new IntPtr(0);




try
{

Image img = Image.FromStream(ms);
...do stuff here with image...
}

to no avail...

in fact using the ms = new MemoryStream(b) instead of ms.Write(b, 0,
b.Length) using the current StreamWiter fix causes a memory stream not
expandable error.


Any ideas why the streamwriter fixes this currently?


Thanks.


Unfortunately, without me seeing all of the involved code, I am unable to
determine the cause (unless I'm just not seeing it). Hope someone else can
chime in here and give a hand if they see it.

Mythran
 
C

Chris Dunaway

Mythran said:
What I believe Marc meant was to use the MemoryStream's overloaded
constructor that takes a byte-array as a parameter. What you are doing is
using the default constructor and then writing the byte-array to the stream.
In other words, instead of writing the byte-array to the stream, directly,
you can just pass the byte-array into the constructor of the MemoryStream
and it will automatically be written by the MemoryStream without any extra
processing on your part:

ms = new MemoryStream(b); // This line here.
...
Image img = Image.FromStream(ms); // This just shows passing the stream
after it's created.


HTH,
Mythran

I see... wrong ctor :)


I tried this:


b = (byte[])dt.Rows.ItemArray[1];

ms = new MemoryStream(b);



Image.GetThumbnailImageAbort callback = new
System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
IntPtr callbackData = new IntPtr(0);




try
{

Image img = Image.FromStream(ms);
...do stuff here with image...
}

to no avail...

in fact using the ms = new MemoryStream(b) instead of ms.Write(b, 0,
b.Length) using the current StreamWiter fix causes a memory stream not
expandable error.


Any ideas why the streamwriter fixes this currently?


In your initial version, using only the MemoryStream without the
StreamWriter, perhaps you need to seek back to the beginning of the
stream before using it in FromStream:

ms.Seek(0, SeekOrigin.Begin);
Image img = Image.FromStream(ms);

I think that's what Marc may have been referring to. Perhaps using the
StreamWriter does this.

Just a guess
 
B

bookon

Chris said:
Mythran said:
Marc Gravell wrote:
It looks like you have left the stream at the end... if you use the
overloaded ctor you don't have to worry about this:

ms = new MemoryStream(b);
// snip
Image img = Image.FromStream(ms);

Marc

Thanks...

I only showed one version. I tried all three (ms),
(ms,false/true),(ms,false/true,false/true) with no difference.


What I believe Marc meant was to use the MemoryStream's overloaded
constructor that takes a byte-array as a parameter. What you are doing is
using the default constructor and then writing the byte-array to the stream.
In other words, instead of writing the byte-array to the stream, directly,
you can just pass the byte-array into the constructor of the MemoryStream
and it will automatically be written by the MemoryStream without any extra
processing on your part:

ms = new MemoryStream(b); // This line here.
...
Image img = Image.FromStream(ms); // This just shows passing the stream
after it's created.


HTH,
Mythran

I see... wrong ctor :)


I tried this:


b = (byte[])dt.Rows.ItemArray[1];

ms = new MemoryStream(b);



Image.GetThumbnailImageAbort callback = new
System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
IntPtr callbackData = new IntPtr(0);




try
{

Image img = Image.FromStream(ms);
...do stuff here with image...
}

to no avail...

in fact using the ms = new MemoryStream(b) instead of ms.Write(b, 0,
b.Length) using the current StreamWiter fix causes a memory stream not
expandable error.


Any ideas why the streamwriter fixes this currently?


In your initial version, using only the MemoryStream without the
StreamWriter, perhaps you need to seek back to the beginning of the
stream before using it in FromStream:

ms.Seek(0, SeekOrigin.Begin);
Image img = Image.FromStream(ms);

I think that's what Marc may have been referring to. Perhaps using the
StreamWriter does this.

Just a guess


I was thinking something along those lines as well. The problem with
that is that it works just fine almost all the time. Only 11 out 100
images failed.

Thanks...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top