4

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!!

Marshal
  • 6,551
  • 13
  • 55
  • 91
subbu
  • 53
  • 1
  • 1
  • 4
  • What does "the image is lost" mean? – CodeCaster Jan 06 '16 at 19:11
  • After retrieving the image I am trying to display it. It gives me GDI+ error (if using first snippet that I mentioned). I am assuming image is lost. Not very sure though. – subbu Jan 06 '16 at 19:19

2 Answers2

8

This is why it's not working for you (from https://msdn.microsoft.com/en-us/library/93z9ee4x(v=vs.110).aspx) :

Image.FromStream Method remarks: You must keep the stream open for the lifetime of the Image.

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.

Community
  • 1
  • 1
Justin Steele
  • 2,230
  • 13
  • 16
  • This is awesome, except it "throws": https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1416 – Mario Mucalo Aug 05 '22 at 12:20
3

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

Justin Steele
  • 2,230
  • 13
  • 16
adv12
  • 8,443
  • 2
  • 24
  • 48