Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is passing System.Drawing.Bitmap across class libraries unreliable?

Tags:

c#

bitmap

wpf

I have a 3rd party dll which generates a Bitmap and send back its reference. If I generate a System.Windows.Media.Imaging.BitmapSource out of it immediately then all goes well. But if I save the reference and later on (after a few seconds and many function calls) I try to generate the Bitmapsource, I get

System.AccessViolationException was unhandled by user code
Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt. Source="System.Drawing"

when doing :

System.Windows.Media.Imaging.BitmapSource bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
    bmp.GetHbitmap(),
    IntPtr.Zero,
    Int32Rect.Empty,
    System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());

Any clues on whats going wrong here ? Any pointers will be useful. Thanks.

like image 810
mishal153 Avatar asked Mar 12 '10 14:03

mishal153


2 Answers

I think this indicates that the handle (reference to a resource managed by the operating system, rather than .Net) returned by bmp.GetHBitmap is no longer valid - possibly a Dispose has been called somewhere or something like that (not necessarily by your code though).

I'd recommend using another way of persisting the bitmap data that does not rely on handles - possibly stream out the binary data of the bitmap itself immediately, and then throw a reference to that around.

like image 62
Andras Zoltan Avatar answered Nov 09 '22 01:11

Andras Zoltan


I had a big problem with Bitmaps and access violations as well. What I believe to be happening is that certain bitmap constructors leave file handles open when they should not. Thus, the program you are running detects that the files are in use, when they shouldn't be.

I eventually figured out a solution in that I make a copy of the original bitmap and then dispose the original. Here is my code, which preserves the resolution of the original Bitmap:

Bitmap Temp = new Bitmap(inFullPathName);
Bitmap Copy = new Bitmap(Temp.Width, Temp.Height);
Copy.SetResolution(Temp.HorizontalResolution, Temp.VerticalResolution);
using (Graphics g = Graphics.FromImage(Copy))
{
     g.DrawImageUnscaled(Temp, 0, 0);
}
Temp.Dispose();
return Copy;

Obviously, for the first line, yours would be Bitmap Temp = MyThirdPartyDLL.GetBitmap(); or something. If you don't care about the resolution it can be simplified to:

Bitmap Temp = MyThirdPartyDLL.GetBitmap();
Bitmap Copy = new Bitmap(Temp, Temp.Width, Temp.Height);
Temp.Dispose();
return Copy;

After making this change, I was able to do all kinds of File I/O, etc, perfectly fine, hope you can do the same.

like image 3
Brandi Avatar answered Nov 09 '22 02:11

Brandi