Returning Image using Image.FromStream - c#

I know there are similar posts but I haven't got any answer for my problem and hence posting this.
I have a method that retrieves and returns image from a image path. Below is the code snippet I used. This fails in some cases as the image is lost after returning.
public static Image GetImageFromPicPath(string strUrl)
{
WebResponse wrFileResponse;
wrFileResponse = WebRequest.Create(strUrl).GetResponse();
using (Stream objWebStream = wrFileResponse.GetResponseStream())
{
return Image.FromStream(objWebStream);
}
}
If I use Bitmap class and return the image, metadata is lost.
If I use MemoryStream (as shown below) and I don't dispose MemoryStream it works . But there is possible memory leak here. If I use using block, the image is lost.
MemoryStream ms = new MemoryStream();
objWebStream.CopyTo(ms, 8192);
return System.Drawing.Image.FromStream(ms);
Can someone suggest me best approach to solve this issue.
Thanks in advance!!

This is why it's not working for you (from https://msdn.microsoft.com/en-us/library/93z9ee4x(v=vs.110).aspx) :
Here's a post that covers the issue a bit more: Loading an image from a stream without keeping the stream open
Try this:
public static Image GetImageFromPicPath(string strUrl)
{
using (WebResponse wrFileResponse = WebRequest.Create(strUrl).GetResponse())
using (Stream objWebStream = wrFileResponse.GetResponseStream())
{
MemoryStream ms = new MemoryStream();
objWebStream.CopyTo(ms, 8192);
return System.Drawing.Image.FromStream(ms);
}
}
In your consuming code do something like this:
using (var image = GetImageFromPicPath("http://imgur.com/123456.png"))
{
//use image
}
By wrapping "var image" in a using statement, Dispose() will be called on image which will also Dispose() and release the underlying MemoryStream in use by the Image.

Use the MemoryStream and don't explicitly close it. The Bitmap will close it in its Dispose method. There's no memory leak, as long as you remember to Dispose() the Bitmap when you're done with it. (And even if you didn't, the MemoryStream would eventually get garbage collected provided you let go of the Bitmap at some point and the Bitmap's the only thing holding a reference to it.)
https://support.microsoft.com/en-us/kb/814675

Related

Unable to create System.Drawing.Image object from WebResponse Stream

I am trying to create a System.Drawing.Image object from a WebResponse's response stream. Here's what I'm doing:
using (WebResponse response = await request.GetResponseAsync())
{
using (Stream originalInputStream = response.GetResponseStream())
{
// some code that calls a 3rd party image resizer, passing in the original stream
ResizeImage(originalInputStream, out resizedOutputStream);
// manipulation of the resizedOutputStream
// now i want to create an image from the ORIGINAL stream
// ERROR HAPPENS HERE!!
using (Image image = Image.FromStream(originalInputStream))
{
// random code that doesn't get hit because of the error above
}
}
}
When the program tries to create the Image.FromStream() in the using statement, I get an error saying:
'Parameter is not valid.'
I assume this is because of the manipulation of the originalInputStream in the resizer function. I searched around and found that resetting the position of the stream can solve these issues. So I tried that, using both:
originalInputStream.Seek(0, SeekOrigin.Begin);
originalInputStream.Position = 0;
but both of those are erroring out as well, giving me an error message of:
Specified method is not supported.
When I try and create the Image.FromStream(), WITHOUT any of the preceding image resizing/stream manipulation... IT WORKS. But THEN, I cannot do anything else with the stream afterwards, or else it will error out as before. However, I need to do the manipulation, and also create the Image, so I'm stuck.
Is the best course of action to simply create another request? And just create the image from the new request's response stream? that just seems like bad practice, I don't know, I feel like what I'm doing should theoretically work and I'm probably just doing something dumb.
Thanks in advance for the help, let me know if I can provide any extra info.
Resetting the stream position does not work on the Stream base class. If you can read the response into a MemoryStream, then you will be able to manipulate the image as you please. Something like this could work:
using (WebResponse response = await request.GetResponseAsync())
{
using (Stream responseStream = response.GetResponseStream())
{
using (MemoryStream memStream = new MemoryStream())
{
responseStream.CopyTo(memStream);
// some code that calls a 3rd party image resizer, passing in the original stream
ResizeImage(memStream, out resizedOutputStream);
memStream.Seek(0, SeekOrigin.Begin);
// manipulation of the resizedOutputStream
// now i want to create an image from the ORIGINAL stream
using (Image image = Image.FromStream(memStream))
{
}
}
}
}

Conversion from byte[] to image using image.FromStream method

I try converting image data from the database which is already in byte[] back to the image and I'm getting "invalid parameter error" using Image.FileStream.
Please, can anyone help me out with this?
I've tried working around the code using various methods and the last one is below in my code.
byte[] data = validaccount.FingerPrint;
try
{
using (MemoryStream strm = new MemoryStream())
{
strm.Write(data, 0, data.Length);
strm.Position = 0;
System.Drawing.Image img = System.Drawing.Image.FromStream(strm);
BitmapImage bi = new BitmapImage();
bi.BeginInit();
MemoryStream ms = new MemoryStream();
img.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
ms.Seek(0, SeekOrigin.Begin);
bi.StreamSource = ms;
bi.EndInit();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
The code is supposed to convert the byte[] into an image.
According to the docs, Image.FromStream(stream) will throw an argument exception if "The stream does not have a valid image format". Have you verified the data is actually correct? If so, what type of image is it?
You're misusing your streams. You only need 1 memory stream and it has a constructor that takes a byte array (no need to write the bytes yourself). Be sure to wrap it in a using block (like you did for your first stream).
You may not want to use BitmapImage - that's for xaml/wpf apps. You probably want System.Drawing.Bitmap which inherits/extends System.Drawing.Image. Additionally, Bitmap has a constructor which takes a stream - no need to use FromStream.
Finally, Image (and hence Bitmap since Bitmap inherits Image) implements IDisposable, so you should also wrap it in a using block.
P.S. This is a duplicate question.
Though its not memory stream, this method has worked for me and if you browse SO for your question, some times MS does not work.
using System.Drawing;
var converterdImage = (Bitmap)((new ImageConverter()).ConvertFrom(byteArray));
Byte Array to Image Conversion

Destroying stream cause destroying the bitmap

I have something like:
public Bitmap GetBitmap()
{
Byte[] byteArray= bring it from somewhere
using (Stream stream = new MemoryStream(byteArray))
{
return new Bitmap(stream);
}
}
When I use this method outside the Bitmap is crushed. but if I stepped into the "using" scope the bitmap will be exists and works fine. it seems that disposing the stream cause disposing the bitmap..
the question is:
Do I need some deep copy? how should I perform it?
When you dispose the Bitmap will be lost, so indeed you need so perform a deep copy.
Eventually your code should be:
public static Bitmap GetBitmap()
{
byte[] byteArray = bring it from somewhere
using (Stream stream = new MemoryStream(byteArray))
{
var tempBitmap = new Bitmap(stream);
return new Bitmap(tempBitmap); // This will deep-copy the Bitmap
}
}
By the way, usually primitive types, like byte are written in small case.

covert from base64 to image using c# in windows 8.1

Any executable funtion to convert from base64 to an image using c# windows 8.1************* .
I tried :
public Image byteArrayToImage(byte[] byteArrayIn)
{
Image returnImage = null;
using (MemoryStream ms = new MemoryStream(byteArrayIn))
{
returnImage = Image.FromStream(ms);
}
return returnImage;
}
FromStream not suitable for windows 8.1
First of all, the Windows.UI.Xaml.Controls.Image class is a control object, not an actual bitmap-type object. What you actually want is a BitmapImage. Of course, given this misunderstanding, you're likely to run into other problems with your code; you don't show the caller of this method, but if you've confused the type here, you've probably confused it elsewhere. So that will have to be fixed.
Secondly, as is the case with many things in WinRT, doing what you want is somewhat more complicated than if you were using the desktop API. :(
That said, something like this should work:
public Windows.UI.Xaml.Media.Imaging.BitmapImage byteArrayToImage(byte[] byteArrayIn)
{
using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())
{
await stream.WriteAsync(byteArrayIn.AsBuffer(0, byteArrayIn.Length));
stream.Seek(0);
BitmapImage image = new BitmapImage();
await image.SetSourceAsync(stream);
return image;
}
}
Then you can set that object to the Source property of an Image control object.
Some notes:
In your original example, disposing the source stream is at the very least unconventional. My recollection is that in at least some cases, doing so isn't legal, as the Bitmap object returned requires the Stream instance to remain undisposed. For WinRT, AFAIK disposing the stream after the bitmap has been initialized is fine.
The AsBuffer() method is an extension method. You'll need to include a using System.Runtime.InteropServices.WindowsRuntime; in your code if it's not already there for it to work.
See also:
BitmapSource class
InMemoryRandomAccessStream class
WindowsRuntimeBufferExtensions Class

Returning image created by Image.FromStream(Stream stream) Method

I have this function which returns an Image within the function the image is created using the Image.FromStream method
According to MSDN:
You must keep the stream open for the lifetime of the Image
So I'm not closing the stream(if I do close the steam a GDI+ exception is thrown from the returned image object). My question is whether the stream will be closed/disposed when Image.Dispose() is called somewhere else on the returned Image
public static Image GetImage(byte[] buffer, int offset, int count)
{
var memoryStream = new MemoryStream(buffer, offset, count);
return Image.FromStream(memoryStream);
}
As suggested in one of the answers, using is not the way to go, since it throws an exception:
public static Image GetImage(byte[] buffer, int offset, int count)
{
using(var memoryStream = new MemoryStream(buffer, offset, count))
{
return Image.FromStream(memoryStream);
}
}
public static void Main()
{
var image = GetImage(args);
image.Save(path); <-- Throws exception
}
According to some people explicitly disposing/closing a MemoryStream is not necessary as it doesn't use any unmanaged resources others say the opposite thing so its kind of a dilemma.
Image.Dispose method doesn't dispose the stream ftom which the Image was created
The Image class doesn't hold any reference to the Stream passed to Image.FromStream method so the stream will eventually be collected by the GC...? Hence the exception in Image.Save method
Return a wrapper class which contains a reference to the stream and the Image created by it hence enabling us to dispose both of them...? or simply use the Tag property to keep a reference to the parent stream...?
This problem only seems to happen when using the MemoryStream. If the image is created from ConnectStream nothing bad happens even if the parent stream is disposed.
Despite what others advice to do, you should not close or dispose the stream until the image is disposed.
MSDN states:
You must keep the stream open for the lifetime of the Image.
For some streams, like MemoryStream, disposing doesn't have much use since it doesn't allocate unmanaged resources. File streams on the other hand do, so unless you are very sure the stream is safe, you should always dispose the stream when you are done with the image.
Since you are only constructing an Image and then saving it consider this implementation instead:
public static void GetAndSaveImage(byte[] buffer, int offset, int count,string path)
{
using(var memoryStream = new MemoryStream(buffer, offset, count))
using(var img = Image.FromStream(memoryStream))
{
img.Save(path);
}
}
Disposing the image will not affect the memorystream as the following example demonstrates :
static void Main(string[] args) {
byte[] contents = File.ReadAllBytes(DESKTOP_PATH + "asample.tif");
MemoryStream ms = new MemoryStream(contents);
Image img = Image.FromStream(ms);
img.Dispose();
Image img2 = Image.FromStream(ms);
Console.WriteLine(img2.PixelFormat);
Console.ReadKey();
}
This will output "Format32bppPargb". I suggest wrapping it into a using statement like so :
using (MemoryStream ms = new MemoryStream(contents){
// code here
}

Categories

Resources