本文介绍了内存转换后的BitmapImage不释放的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用下面的C#中的问题(测试 - )code:

I got a problem with the following c# (test-)code:

    public static void TestBitmap2ByteArray(BitmapImage bitmap)
    {
        JpegBitmapEncoder encoder = new JpegBitmapEncoder();
        MemoryStream memstream = new MemoryStream();
        encoder.Frames.Add(BitmapFrame.Create(bitmap));
        encoder.Save(memstream);

        memstream.Close();
    }

我每次调用该函数,内存分配,而不是再次释放。在实际项目中,该方法被调用非常频繁,应用程序运行的内存。

Each time I call the function, memory is allocated and not freed again. In the real project, the method is called very often and the application runs out of memory.

这是的code一个精简版,不返回任何东西。

This is a stripped down version of the code, not returning anything.

我在使用Visual Studio2010和.NET 3.5 SP1。

I am using Visual Studio2010 and .net 3.5 SP1.

帮助是AP preciated。谢谢你。

Help is appreciated.Thank You.

推荐答案

正如我在其他的答案中描述一个更好的办法来解决,这是直接访问位图数据。 BitmapImage的继承的BitmapSource。的BitmapSource是伟大的,这一点,也与WPF绑定。

As described in my other answer a better way to solve this is to access the bitmap data directly. BitmapImage inherits from BitmapSource. BitmapSource is great for this and also works with WPF binding.

我使用的BitmapSource自己操纵的直接绑定到WPF(MVVM型)图像。基本上我在内存中创建一个区域指向的BitmapSource它。这让我读/写像素直接对内存和无效的BitmapSource让WPF重绘图像。我有我使用的这个标准的位图的对象。直接数据访问使得它速度超快。 (说真的,一点问题都没有修改所有位在4张图像,30fps的..没有在更高的速度尝试,因为它没有被要求的。)

I am using BitmapSource myself to manipulate images that are bound directly to WPF (MVVM style). Basically I create a region in memory and point BitmapSource to it. This allows me to read/write pixels directly to memory and invalidate the BitmapSource so that WPF redraws the image. I have a standard "Bitmap" object I use for this. The direct data access makes it super-fast. (Seriously, no problem at all modifying all bits in 4 images at 30fps .. haven't tried at higher speeds as it hasn't been required.)

样品的使用可以在的。但基本上你这样做:

Sample usage can be found on my blog. But basically you do this:

unsafe {
   byte* imgBytePtr = (byte*)myBitmap.ImageData;
   Int32* imgInt32Ptr = (Int32*)myBitmap.ImageData;
   int height = (int)myBitmap.BitmapSource.Height;
   int width = (int)myBitmap.BitmapSource.Width;
   int bpp = myBitmap.BytesPerPixel;

   // Note: No need to iterate just for copy. A Marshal.Copy() at this point can copy all the bytes into a byte-array if you want.
   // But the best would be if your application could do its work directly in the imgBytePtr[]-array.

   for (int x = 0; x < height; x++)
   {
      for (int y = 0; y < width; y++)
      {
         // Get bytes into RGBA values
         int bytePos = x * (width * bpp) + (y * bpp);
         byte R = imgBytePtr[bytePos + 0];
         byte B = imgBytePtr[bytePos + 1];
         byte G = imgBytePtr[bytePos + 2];
         byte A = imgBytePtr[bytePos + 3];

         // Alternatively get Int32 value of color
         int intPos = x * width + y;
         int intColor = imgIntPtr[intPos];


         // Examples of manipulating data

         // Remove blue
         imgBytePtr[bytePos + 1] = 0;
         // Alternative remove blue by bitmask
         imgIntPtr[intPos] = imgIntPtr[intPos] & 0xFF00FFFF;

      }
   }
}
// Now execute Invalidate() and WPF will automagically update bound picture object :)

这使得一个的BitmapSource,如果你需要的BitmapImage相反,你可以看到,如果你可以改变它的工作。

This makes a BitmapSource, if you need BitmapImage instead you can see if you can change it to work.

    ///
    /// This object holds a byte array of the picture as well as a BitmapSource for WPF objects to bind to. Simply call .Invalidate() to update GUI.
    ///
    public class Bitmap : IDisposable
    {
        // some ideas/code borowed from CL NUI sample CLNUIImage.cs
        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr CreateFileMapping(IntPtr hFile, IntPtr lpFileMappingAttributes, uint flProtect, uint dwMaximumSizeHigh, uint dwMaximumSizeLow, string lpName);
        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, uint dwNumberOfBytesToMap);
        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool UnmapViewOfFile(IntPtr hMap);
        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool CloseHandle(IntPtr hHandle);

        private IntPtr _section = IntPtr.Zero;
        public IntPtr ImageData { get; private set; }
        public InteropBitmap BitmapSource { get; private set; }
        public int BytesPerPixel = 3;

        ///
        /// Initializes an empty Bitmap
        ///
        /// Image width
        /// Image height
        /// Image format
        public Bitmap(int width, int height, PixelFormat pixelFormat)
        {
            BytesPerPixel = pixelFormat.BitsPerPixel / 8;
            uint imageSize = (uint)width * (uint)height * (uint)BytesPerPixel;
            // create memory section and map
            _section = CreateFileMapping(new IntPtr(-1), IntPtr.Zero, 0x04, 0, imageSize, null);
            ImageData = MapViewOfFile(_section, 0xF001F, 0, 0, imageSize);
            BitmapSource = Imaging.CreateBitmapSourceFromMemorySection(_section, width, height, pixelFormat, width * BytesPerPixel, 0) as InteropBitmap;
        }

        ///
        /// Invalidates the bitmap causing a redraw
        ///
        public void Invalidate()
        {
            BitmapSource.Invalidate();
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected void Dispose(bool disposing)
        {
            if (disposing)
            {
                // free managed resources
            }
            // free native resources if there are any.
            if (ImageData != IntPtr.Zero)
            {
                UnmapViewOfFile(ImageData);
                ImageData = IntPtr.Zero;
            }
            if (_section != IntPtr.Zero)
            {
                CloseHandle(_section);
                _section = IntPtr.Zero;
            }
        }
    }

这篇关于内存转换后的BitmapImage不释放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-21 16:14