0

I am wondering if it is possible to load an Image-File directly to the preallocated memory WITHOUT a new allocation for the bitmapimage itself. I wrote a sample class to demonstrate what I want to do.

  public class PreAllocatedImageLoader
    {
        private readonly int _width;
        private readonly int _height;
        private readonly int _stride;
        private readonly IntPtr _imageData;

        public PreAllocatedImageLoader(int width, int height, PixelFormat pixelFormat)
        {
            _width = width;
            _height = height;
            _stride = width * ((pixelFormat.BitsPerPixel + 7) / 8);
            _imageData = Marshal.AllocHGlobal(height * _stride);
        }

        public void LoadFromFile(string filePath)
        {
            // Oh nooo, we allocate memory here
            var newAllocatedImage = new BitmapImage(new Uri(filePath));
            // Copy the pixels in the preallocated memory
            newAllocatedImage.CopyPixels(new Int32Rect(0, 0, _width, _height), _imageData, _height * _stride, _stride);
        }
    }

Hopefully someone can help me with this. Thanks in advance!

Andreas
  • 3,843
  • 3
  • 40
  • 53
  • 1
    Why would you like to do that? – Yogee Feb 23 '15 at 14:15
  • Because allocation comes always at a high cost. For the OS and the GC. – Andreas Feb 23 '15 at 14:17
  • First: What's the cost of allocation in your case? I guess it will not be bottleneck. Second: BitmapImage is disposable, you should manually dispose it before GC does. – Yogee Feb 23 '15 at 14:20
  • First: I am loading a lot of images in a small amout of time so the memory climbs over 5 GB before the GC realises the dead objects. Second: Even this would not be a fix, it is not correct. BitmapImage is not disposeable. – Andreas Feb 23 '15 at 14:22
  • 3
    Your memory climbs to 5 GB, because you are not disposing used BitmapImage objects. Once you correct that, your program will consume less memory and speedup beyond your expectation. – Yogee Feb 23 '15 at 14:24
  • Can you please share a bit more of a code, so that I can assist where you can dispose the BitmapImage? – Yogee Feb 23 '15 at 14:26
  • Oh.. I think you are using WPF BitmapImage. If so, my bad. I misunderstood it with Image type that is part of System.Drawing – Yogee Feb 23 '15 at 14:29
  • I do! WPF BitmapImage is not disposeable! Yes, the system.drawing.bitmap is disposeable. But if there is an answer to my question, disposing would not be necessary – Andreas Feb 23 '15 at 14:31
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/71501/discussion-between-andreas-and-yogee). – Andreas Feb 23 '15 at 14:33
  • You may want to read the answer to this [question](http://stackoverflow.com/questions/11202807/garbage-collection-fails-to-reclaim-bitmapimage) – juharr Feb 23 '15 at 14:34
  • Here's another blog post about memory leaks from BitmapImage. He recommends explicitly loading a blank image into the BitmapImage to free the memory immediately. http://blogs.codes-sources.com/kookiz/archive/2013/02/17/wpdev-memory-leak-with-bitmapimage.aspx – Moby Disk Feb 23 '15 at 15:52
  • 2
    This really is an X-Y problem (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). I think your real question should be more like "How do I save memory when creating and destroying many BitmapImage objects" or something like that. – Moby Disk Feb 23 '15 at 15:53
  • @MobyDisk, my question is about NOT creating and destorying bitmapimage objects^^. I just want to reuse allocated space and just change the pixels. – Andreas Feb 23 '15 at 16:05
  • Perhaps WriteableBitmap is closer to what you want? http://stackoverflow.com/questions/20181132/edit-raw-pixel-data-of-writeablebitmap – Moby Disk Feb 23 '15 at 18:26

2 Answers2

1

It is not possible to use self-allocated memory for images with WPF. This answers your question as asked. You have been very insistent in the comment that this is what you want but there is no way to do it.

What you should do instead is make sure that memory is released when no longer needed. Unfortunately, this is not as straight-forward as one might hope.

usr
  • 168,620
  • 35
  • 240
  • 369
  • I am not restricted to WPF! I found this https://msdn.microsoft.com/en-us/library/aa288474(v=vs.71).aspx#vcwlkunsafecode_readfileexample .I will test it the next days – Andreas Feb 24 '15 at 09:29
  • XY-problem. What are you trying to do? If you want to do image processing consider using System.Drawing. It allows for precise memory management. – usr Feb 24 '15 at 09:55
  • It seems to be possible to read a file into a preallocated data buffer with the "unsafe bool ReadFile" method. But perhaps your answer is correct and it is simply not possible – Andreas Feb 24 '15 at 11:18
  • You can already read data with FileStream.Read. Reading is not the problem. The problem is a) that the image library does not support user-provided buffers and b) that you don't need this at all. – usr Feb 24 '15 at 11:21
  • a). Ok, thx for info. b). I would not need all this but unfortunately releasing memory is really not as straight-forward as one might hope :). Now I use Emgucv to load and dispose images. This looks much better in ProcessExplorer. – Andreas Feb 24 '15 at 11:26
0

I do not think this is supported with the BitmapImage class. It can only be initialized once, so you cannot re-use it, and it does not support explicitly specifying memory locations.

I suppose you could try to sidestep the issue by making a stream source (memoryStream) and initializing your BitmapImage from that, since those have more finite control on lifecycle.

I would not use IntPtr's around in your code unless absolutely necessary, as you are in dangerous water there. Anything with any unmanaged resources must implement IDisposable (which you are not) and it becomes much more difficult to properly clean up after yourself.

Tim
  • 2,878
  • 1
  • 14
  • 19