Image.FromStream does not hold a ref to the underlying stream - c#

I have some code that does
MemoryStream ms = new MemoryStream();
...
return Image.FromStream(ms);
It fails in very eclectic ways since the Image object does not hold a ref to the stream, so it can get disposed if the GC kicks in which results in GDI+ errors.
How do I work around this (without saving the stream to disk, or altering my method sigs) ?

This seems highly unlikely to me - it would cause a problem for almost any use of Image.FromStream.
It seems more likely to me that something's disposing of your MemoryStream, which it shouldn't.
Could you provide a short but complete program which demonstrates the problem? Forcing garbage collection should make it relatively easy to reproduce - you could even create your own class deriving from MemoryStream with a finalizer to show whether or not it really is being collected (well, finalized at least).

There isn't a way to do it without changing your code somewhat. The Remarks section for the documentation for the static FromStream method on the Image class states:
You must keep the stream open for the
lifetime of the Image.
That being said, you have to make sure that while the Image is accessing the Stream, the stream is open. It would also appear (looking through Reflector) that the FromImage method doesn't actually cause the Image instance to hold onto a reference to the Stream the image was loaded from.
That being said, you to somehow link the image and the MemoryStream (or Stream) together so that it doesn't get GCed. If don't really retain "ownership" of the image (it is passed around), then I recommend that you create a data structure which will hold the reference to the Image and to the Stream and pass the two around in tandem.

Related

How to get MemoryStream (or another Stream) from Memory<byte> without reallocating?

Is there an existing way get a MemoryStream (or another Stream) from Memory<byte> without reallocating?
When you construct a MemoryStream from a byte[] the array is assigned as the stream's buffer. In this case there is no additional allocation or copy.
Unfortunately there's no constructor that takes Memory<byte>. You'll have to call Memory<byte>.ToArray() to get there, and that does allocate. The documentation comment for Memory<T>.ToArray() states:
Copies the contents from the memory into a new array. This heap allocates, so should generally be avoided, however it is sometimes necessary to bridge the gap with APIs written in terms of arrays.
(Internally this is implemented via Span<T>.ToArray().)
The Microsoft.Toolkit.HighPerformance package adds an AsStream() extension that creates a thin stream wrapper around Memory<byte>, allowing you to read/write to your Memory<byte> without allocations.

Why Read and ReadAync are producing totally different results

I have been using this code to capture the webcam and I have been trying to learn from it and make it better. Rider IDE suggested I should use an async variant of MemoryMappedViewStream.Read but it doesn't work at all. It produces all-black images suggesting the async and sync methods are totally different. I am wondering why that's the case?
// Working:
sourceStream.Read(MemoryMarshal.AsBytes(image.GetPixelMemoryGroup().Single().Span));
// NOT Working:
var bytes = MemoryMarshal.AsBytes(image.GetPixelMemoryGroup().Single().Span).ToArray();
await sourceStream.ReadAsync(bytes, 0, bytes.Length, token);
Repository and line of code
Those two versions are not the same. In "sync" version you obtain a reference to memory location of an image via image.GetPixelMemoryGroup(). Then you read data from sourceStream directly into that location.
In "async" version you again obtain reference to memory location via image.GetPixelMemoryGroup but then you do something different - you call ToArray. This extension method copies bytes from image memory location into new array, the one you hold in bytes variable. You then read data from sourceStream into that bytes array, NOT directly into image memory locaiton. Then you discard bytes array, so you read them to nowhere basically.
Now,MemoryMappedViewStream inherits from UnmanagedMemoryStream and all read\write operations are implemented in UnmanagedMemoryStream. This kind of stream represents data in memory and there is nothing async it can do. The only reason it even has ReadAsync is because base stream class (Stream) has those methods. Even if you manage to make ReadAsync work - in this case it will not be asynchornous anyway. As far as I know - MemoryMappedViewStream does now allow real asynchronous access, even though it could make sense, since it has underlying file.
In short - I'd just continue with sync version, because there is no benefit in this case to use "async" one. Static analyzer of course doesn't know that, it only sees that there is Async-named analog of the method you use.
await sourceStream.ReadAsync(bytes, 0, bytes.Length, token).ConfigureAwait(false);
Check like this

Do I need to clear Byte[]?

In my game user can choose multiple images from gallery and load them into game. I have created a function that get images from filepath. In that function I declare local variable byte[]. so after read file do i need to dispose that byte[] to freed memory. here is my code :
if (File.Exists(filePath))
{
byte[] fileData = File.ReadAllBytes(filePath);
Texture2D tex = new Texture2D(2, 2);
tex.LoadImage(fileData);
}
Do I need to clear byte[] after texture is loaded from byte[] ???? User can choose any image file from gallery so there is no limit of filesize.
Short answer: No
byte[] is a managed resource. It will be fully cleaned up by the GC.
File related classes often involve unmanaged resources - usually the OS filehandles. But File.ReadAllBytes(string) looks like it follows my advise "create, use, dispose. All in the same piece of code, ideally using a using statement." So I expect not issues form it.
Networking and DB classes involve unamanged resources - usually network connections.
A lot of drawing related classes use unmanaged resources - primarily some unmanaged memory for performance.
But this is just a byte[]. As managed as any int[]. Note that you do not have a choice on the mater anyway as neither byte nor array implement IDisposeable. If you try to dispose if it, the compiler will wonder what you are talking about as there is no such function.

BitmapSource access with pointers

Is there a way to access the underlying memory of a BitmapImage object with c# pointers?
I know that there's a CopyPixels method but it makes a copy of the pixels array into a new array (duplicating memory requirements). If you open a large image (2gb) it allocates a lot of un-useful stuff. And if you want to operate some sort of elaboration, like CCLA, it takes a huge amount of memory.
I need only to read the pixel array.
Is it possible to address pixels directly like you can do in System.Drawing.Bitmap?
I wrote a fast bitmap access for System.Drawing.Bitmap, but as I'm using WPF, I need the same functionality for BitmapSource. Otherwise I have to duplicate the image loading (Bitmap for my old method and BitmapSource to show the image in WPF) taking a lot of memory and time.
Thank you
Lorenzo
A bitmap source does not necessarily have backing memory for the entire image. An example of when it does not would be an image file on disk which is lazy loaded.
The only access you have with WIC, and therefore WPF, is the CopyPixels method. Certain subclasses of BitmapSource will allow access to a buffer, but they are internally just allocating memory and calling CopyPixels themselves.
I would assume that whatever operation does not require access to the entire image at a time. If so, you can call CopyPixels to a smaller buffer, and window your access to the image. Most decoders, when a single pixel is requested, will buffer the entire stride, or in the case of JPEG, then entire block.
I am not sure what CCLA is, and cannot find a definition that seems to fit, but if it is some sort of transform on the source image, you can implement it as a BitmapSource. That way, you can compose a full chain which will
read the image from disk (TiffBitmapEncoder et al.)
scale or translate them (TransformedBitmap)
then window it to only the portion you need (CroppedBitmap)
use a format conversion (FormatConvertedBitmap)
pass it to your algorithm (CclaTransformBitmap)
and finally render it to a WritableBitmap, which gives you access to the buffer
With careful attention to the CacheOption used on the source image, as well as the order of transforms, you should be able to access an arbitrarily large image without significant memory impact.
If you already have a performant algorithm for GDI (System.Drawing), there is no sense re-implementing it. You can still display your final bitmap using Imaging.CreateBitmapSourceFromHBitmap or by using a WindowsFormsHost to host the control you previously built.

Memory not being relieved when setting BitmapImage to null

I have a collections of objects, each object contains a BitmapImage. I have this collection bound to a FlipView. When user flips a page in he FlipView, the BitmapInmage of the selected object gets loaded from ApplicationData and I set the BitmapImage of the previous object to null to relieve the memory. The problem is, that the memory never gets relieved and the app crashes after some time of flipping. When I look at the collection, only the actual item has its BitmapImage set, all the others have it as null. So how do I relieve the memory?
The way I load the images:
StorageFile s = await ApplicationData.Current.LocalFolder.GetFileAsync(localFilename);
BitmapImage bitmapImage = new BitmapImage();
using (var stream = await s.OpenAsync(FileAccessMode.Read))
{
bitmapImage.SetSource(stream);
}
return bitmapImage;
Edit: I think the problem may be the way I load the Image, I guess the file stream does not get freed
I ran into a similar issue with Windows Phone 7 applications.
One trick that worked for me was removing the image from the parent element.
grid1.Children.Remove(image1);
image1 = null;
I'm not sure if this will help in your situation though.
More details about this issue from my blog post.
What worked for me was setting the UriSource property to null before setting the object itself to null.
If these images are using large amounts of memory then it might make sense to force Garbage Collection to free the memory. This will only work if you've removed all strong references to the memory. You can run into performance problems if you're too aggressive in forcing garbage collection, so you'll want to experiment with this. For example, you might want to force collection only after "nulling out" a few images.
You can force garbage collection using the GC.Collect method.
http://msdn.microsoft.com/en-us/library/bb384155.aspx
If you are using x:Bindings in UWP, you may find a similar issue, however, if you run Bindings.Update() after clearing out your classes (Say your image is in a class, held in an observable collection), first run .Clear() on that ObservableCollection, then Bindings.Update(), then you will find that your will regain free space.
In .net setting something to null never does anything - GC is unrelated and happens when it chooses. Instead, check whether the image implements IDisposable: if it does, you should be calling Dispose() when you have finished with it. Moat commonly, you would do this automatically via a "using" statement:
using(var img = GetImage()) {
// todo: some stuff involving img
}

Categories

Resources