Parameter is not valid when getting image from stream - c#

I have this code:
MemoryStream ms = new MemoryStream(newbytes, 0,
newbytes.Length);
ms.Position = 0;
ms.Write(newbytes, 0, newbytes.Length);
Image img = Image.FromStream(ms);
img.Save(#"C:\Users\gsira\Pictures\Blue hills5.jpg");
I get this error at the Image.FromStream(ms) call:
System.ArgumentException: Parameter is not valid.
at System.Drawing.Image.FromStream(Stream stream, Boolean useEmbeddedColorManagement, Boolean validateIma
How can I resolve this? A couple of links which solve this problem (one on an MSDN thread) are broken so I am lost.

If you initialise a MemoryStream with a byte array (which is what I am assuming newbytes to be), you should not need to write to it.
The call to Write(newbytes, 0, newbytes.Length) in your sample is completely redundant.
var s = new MemoryStream(newbytes, 0, newbytes.Length);
var i = Image.FromStream(s);
i.Save(#"C:\Users\gsira\Pictures\Blue hills5.jpg");
The above works for me where newbytes is a byte array of the contents of an image file on my hard drive.

Try to rewind memory stream to the very beginning after you wrote bytes into it.
ms.Seek(0, SeekOrigin.Begin);
Than it's possible to create Image.FromStream

Related

C# byte[] to bitmap System.InvalidOperationException

I'm doing a C# web service soap receiving an image.
I send a string contain the byte characters.
I transform the string in byte[] and next I world like to create the Bitmap.
The line Bitmap img = new Bitmap(ms); generate an exception : invalid argument.
I have a in the ms object this error : System.InvalidOperationException
value contain the correct string, imgBytes contain the good number of sell.
public string GetImage(string value)
{
byte[] imgBytes = Encoding.ASCII.GetBytes(value);
MemoryStream ms = new MemoryStream(imgBytes, true);
Bitmap img = new Bitmap(ms);
Code with debug mode
Exception
Thank you for your help.
It looks like your string holds base64 encoded data. Try to decode it to a byte array via Convert.FromBase64String
I had a similar problem. Basically you write into your memory stream (in the constructor) and the position pointer is at the end. So before reuse the memory stream you can try setting its position pointer to the beginning. Like this:
MemoryStream ms = new MemoryStream(imgBytes, true);
ms.Position = 0;
Bitmap img = new Bitmap(ms);
or the more general approach:
MemoryStream ms = new MemoryStream(imgBytes, true);
ms.Seek(0, SeekOrigin.Begin);
Bitmap img = new Bitmap(ms);
Hope this will solve your Problem.
Update
I think #heinbeinz answer is also important: First decode your string from the right encoding (normally base64), then set the position.

FileStream to Bitmap - Parameter is not valid

I have read the posts on this subject but none of them explains it to me clearly enough to be able to fix the problem.
I am trying to upload a file from a local directory to the server.
Here is my code:
string fullPath = Path.Combine(
AppDomain.CurrentDomain.BaseDirectory + #"Images\Readings", PhotoFileName);
Stream s = System.IO.File.OpenRead(fileUpload);
byte[] buffer = new byte[s.Length];
s.Read(buffer, 0, Convert.ToInt32(s.Length));
using (FileStream fs = new FileStream(fullPath, FileMode.Create))
{
fs.Write(buffer, 0, Convert.ToInt32(fs.Length));
Bitmap bmp = new Bitmap((Stream)fs);
bmp.Save(fs, ImageFormat.Jpeg);
}
I keep on getting an Argument Exception: "Parameter is not valid" on line:
Bitmap bmp = new Bitmap((Stream)fs);
Can anyone explain this to me please
There are at least two problems, probably three. First, your copying code is broken:
byte[] buffer = new byte[s.Length];
s.Read(buffer, 0, Convert.ToInt32(s.Length));
You've assumed that this will read all of the data in a single Read call, and ignored the return value for Read. Generally, you'd need to loop round, reading data and writing it (the amount you've just read) to the output stream, until you read the end. However, as of .NET 4, Stream.CopyTo makes this much simpler.
Next is how you're creating the bitmap:
using (FileStream fs = new FileStream(fullPath, FileMode.Create))
{
fs.Write(buffer, 0, Convert.ToInt32(fs.Length));
Bitmap bmp = new Bitmap((Stream)fs);
bmp.Save(fs, ImageFormat.Jpeg);
}
You're trying to read from the stream when you've just written to it - but without "rewinding"... so there's no more data left to read.
Finally, I would strongly advise against using Bitmap.Save to write to the same stream that you're loading the bitmap from. Bitmap will keep a stream open, and read from it when it needs to - if you're trying to write to it at the same time, that could be very confusing.
It's not clear why you're using Bitmap at all, to be honest - if you're just trying to save the file that was uploaded, without any changes, just use:
using (Stream input = File.OpenRead(fileUpload),
output = File.Create(fullPath))
{
input.CopyTo(output);
}
This is assuming that fileUpload really is an appropriate filename - it's not clear why you haven't just written the file to the place you want to write it to straight away, to be honest. Or use File.Copy to copy the file. The above code should work with any stream, so you can change it to save the stream straight from the request...

Conversion of memory stream to bitmapdata

I make a webrequest to receive a large jpeg as a byte array. This in turn can be converted to a memory stream. I need to get this data into a bitmapdata so that I can marshall copy it to a byte array again. Am i right in assuming that a byte array returned from a memory stream is not the same as a byte array returned from a marshall copy of bitmapdata to a byte array?
I do not want to write the memory stream out to an image as it will return a out of memory error due to its size AND the fact I am using compact cf C# 2.
this is my call to the server..
HttpWebRequest _request = (HttpWebRequest)WebRequest.Create("A url/00249.jpg");
_request.Method = "GET";
_request.Timeout = 5000;
_request.ReadWriteTimeout = 20000;
byte[] _buffer;
int _blockLength = 1024;
int _bytesRead = 0;
MemoryStream _ms = new MemoryStream();
using (Stream _response = ((HttpWebResponse)_request.GetResponse()).GetResponseStream())
{
do
{
_buffer = new byte[_blockLength];
_bytesRead = _response.Read(_buffer, 0, _blockLength);
_ms.Write(_buffer, 0, _bytesRead);
} while (_bytesRead > 0);
}
This is my code to read a byte array from a bitmapdata.
Bitmap Sprite = new Bitmap(_file);
Bitmapdata RawOriginal = Sprite.LockBits(new Rectangle(0, 0, Sprite.Width, Sprite.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);
int origByteCount = RawOriginal.Stride * RawOriginal.Height;
SpriteBytes = new Byte[origByteCount];
System.Runtime.InteropServices.Marshal.Copy(RawOriginal.Scan0, SpriteBytes, 0, origByteCount);
Sprite.UnlockBits(RawOriginal);
Note:
I do not want to use this:
Bitmap Sprite = new Bitmap(_file);
I want to go from:
MemoryStream _ms = new MemoryStream();
to
System.Runtime.InteropServices.Marshal.Copy(RawOriginal.Scan0, SpriteBytes, 0, origByteCount);
using what ever conversions are required without writing to a bitmap.
What you're asking is going to be difficult. The data you're receiving from the response object is a full jpeg image, which has a header and then a bunch of compressed data bytes. The byte array addressed by Scan0 is uncompressed and quite possibly includes some padding bytes at the end of each scan line.
Most importantly, you definitely cannot use Marshal.Copy to copy the received bytes to Scan0.
To do what you're asking will require that you parse the header of the jpeg that you receive and uncompress the image bits directly to Scan0, padding each scan line as appropriate. There is nothing in the .NET Framework that will do that for you.
The accepted answer to this question has a link to a library that might help you out.
Even if that works, I'm not certain it will help you out. If calling the BitMap constructor to create the image causes you to run out of memory, it's almost certain that this roundabout method will, as well.
Is the problem that you have so many sprites that you can't keep them all in memory, uncompressed? If so, you'll probably have to find some other way to solve your problem.
By the way, you can save yourself a lot of trouble by changing your code that reads the image to:
MemoryStream _ms = new MemoryStream();
using (Stream _response = ((HttpWebResponse)_request.GetResponse()).GetResponseStream())
{
_response.CopyTo(_ms);
}

Copy MemoryStream and recreate System.Drawing.Image fails with "Parameter is not valid"

I am receiving an ArgumentException (Parameter is not valid) when trying to recreate an image from a memory stream. I have distilled it down to this example where I load up an image, copy to a stream, replicate the stream and attempt to recreate the System.Drawing.Image object.
im1 can be saved back out fine, after the MemoryStream copy the stream is the same length as the original stream.
I am assuming that the ArgumentException means that System.Drawing.Image doesnt think my stream is an image.
Why is the copy altering my bytes?
// open image
var im1 = System.Drawing.Image.FromFile(#"original.JPG");
// save into a stream
MemoryStream stream = new MemoryStream();
im1.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
// try saving - succeeds
im1.Save(#"im1.JPG");
// check length
Console.WriteLine(stream.Length);
// copy stream to new stream - this code seems to screw up my image bytes
byte[] allbytes = new byte[stream.Length];
using (var reader = new System.IO.BinaryReader(stream))
{
reader.Read(allbytes, 0, allbytes.Length);
}
MemoryStream copystream = new MemoryStream(allbytes);
// check length - matches im1.Length
Console.WriteLine(copystream.Length);
// reset position in case this is an issue (doesnt seem to make a difference)
copystream.Position = 0;
// recreate image - why does this fail with "Parameter is not valid"?
var im2 = System.Drawing.Image.FromStream(copystream);
// save out im2 - doesnt get to here
im2.Save(#"im2.JPG");
Before reading from the stream you need to rewind its position to zero. You are doing that for the copy right now, but also need to do that for the original.
Also, you don't need to copy to a new stream at all.
I usually resolve such problems by stepping through the program and looking at runtime state to see whether it matches my expectation or not.

“Unspecified error” when converting a byte array into a BitmapImage

My goal is to upload and download images using a web service. I understand that in order to do that the images need to be converted to a byte array. However, I’m getting “Unspecified error” when converting a byte array into a BitmapImage.
I’ve create a test rig that converts an image (from a PhotoChooserTask) into a byte array and back again that recreates my problem. The code that does the conversion is listed below with the problem line highlighted.
Any help would be appreciated!
private void PhotoChooserTaskCompleted(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
//Display the photo
BitmapImage PhotoBitmap = new BitmapImage();
PhotoBitmap.SetSource(e.ChosenPhoto);
Photo.Source = PhotoBitmap;
//Convert the photo to bytes
Byte[] PhotoBytes = new byte[e.ChosenPhoto.Length];
e.ChosenPhoto.Read(PhotoBytes, 0, PhotoBytes.Length);
//Convert the bytes back to a bitmap
BitmapImage RestoredBitmap = new BitmapImage();
MemoryStream stream = new MemoryStream(PhotoBytes);
BitmapImage image = new BitmapImage();
RestoredBitmap.SetSource(stream); //<------ I get "Unspecified error" on this line
//Display the restored photo
RestoredPhoto.Source = RestoredBitmap;
}
}
The first time you use e.ChosePhoto as source, the stream is read and the Position property is advanced to the end. You can inspect the PhotoBytes array in the debugger to see that after your read operation it actually does not have any content (or check the return value of the Read method to confirm zero bytes are read).
What you need to do is reset that Position to zero before you read from it again:
//Convert the photo to bytes
Byte[] PhotoBytes = new byte[e.ChosenPhoto.Length];
// rewind first
e.ChosenPhoto.Position = 0;
// now succeeds
e.ChosenPhoto.Read(PhotoBytes, 0, PhotoBytes.Length);
I would bet that this is what's happening (comments inline):
//Display the photo
BitmapImage PhotoBitmap = new BitmapImage();
PhotoBitmap.SetSource(e.ChosenPhoto); // This is reading from the stream
Photo.Source = PhotoBitmap;
//Convert the photo to bytes
Byte[] PhotoBytes = new byte[e.ChosenPhoto.Length];
e.ChosenPhoto.Read(PhotoBytes, 0, PhotoBytes.Length); // Fails to read the full stream
// because you already read from it
//Convert the bytes back to a bitmap
BitmapImage RestoredBitmap = new BitmapImage();
MemoryStream stream = new MemoryStream(PhotoBytes); // You're creating a stream that
// doesn't contain the image
BitmapImage image = new BitmapImage();
RestoredBitmap.SetSource(stream); // Fails because your stream is incomplete
Seek to 0 in the stream before you attempt to read from it. And check the return value from the Read call to make sure it matches PhotoBytes.Length.
This:
//Display the photo
BitmapImage PhotoBitmap = new BitmapImage();
PhotoBitmap.SetSource(e.ChosenPhoto);
Photo.Source = PhotoBitmap;
uses the Stream of the e.ChosenPhoto and might not rewind the Position of the Stream.
So when you do this:
Byte[] PhotoBytes = new byte[e.ChosenPhoto.Length];
e.ChosenPhoto.Read(PhotoBytes, 0, PhotoBytes.Length);
you are starting at the end of the stream reading nothing.
Use Seek to reset the Position of the stream.
Did you check out my other post where I already did this?
I had receive a pretty good rating from it.
BitmapImage to byte[] and byte[] to BitmapImage

Categories