使用不安全代码将 Bitmap 位图转为 WPF 的 ImageSource 以获得高性能和持续小的内存占用
来源:互联网 发布:深圳奥凯软件 编辑:程序博客网 时间:2024/05/21 11:32
在 WPF 中将一个现成的 Bitmap 位图转换成 ImageSource 用于显示一个麻烦的事儿,因为 WPF 并没有提供多少可以转过来的方法。不过产生 Bitmap 来源却非常多,比如屏幕截图、GDI 图、数组或其它非托管框架生成的图片。
WPF 官方提供了一种方法,使用 System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap()
方法。官方解释称这是托管和非托管位图相互转换所用的方法。然而此方法有一个很严重的弊端——每次都会生成全新的位图,即便每次 DeleteObject
之后,内存依然不会即时释放。
DeleteObject:
[DllImport("gdi32")]static extern int DeleteObject(IntPtr o);
DeleteObject 的指针源于 Bitmap.GetHbitmap()
方法,且得到的指针会作为 System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap()
的参数之一。
在持续输出图像的时候(例如播放 Gif 图、持续显示屏幕截图等)不及时释放内存非常致命!为了防止重复创建图片,WriteableBitmap
似乎成了比较好的选择。
但是 WriteableBitmap
没有提供与位图 Bitmap 的互操作。然而它们都提供了像素操作。
于是,我们考虑内存拷贝来完成转换,代码如下:
public static class WriteableBitmapExtensions{ public static void CopyFrom(this WriteableBitmap wb, Bitmap bitmap) { if (wb == null) throw new ArgumentNullException(nameof(wb)); if (bitmap == null) throw new ArgumentNullException(nameof(bitmap)); var ws = wb.PixelWidth; var hs = wb.PixelHeight; var wt = bitmap.Width; var ht = bitmap.Height; if (ws != wt || hs != ht) throw new ArgumentException("暂时只支持相同尺寸图片的复制。"); var width = ws; var height = hs; var bytes = ws * hs * wb.Format.BitsPerPixel / 8; var rBitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bitmap.PixelFormat); wb.Lock(); unsafe { Buffer.MemoryCopy(rBitmapData.Scan0.ToPointer(), wb.BackBuffer.ToPointer(), bytes, bytes); } wb.AddDirtyRect(new Int32Rect(0, 0, width, height)); wb.Unlock(); bitmap.UnlockBits(rBitmapData); }}
我写了一个持续不断截取屏幕并输出显示的控件,在我的 The New Surface Pro 2736*1826 分辨率下内存一直保持 168M 从不变化。
这个方法的简化空间还非常大,比如,如果数据源是一个一次申请不断修改的数组,那么连 Bitmap
都可以不需要了,直接拷贝数组空间即可。我的朋友林德熙为此将这段代码简化得只剩下几行代码了:WPF 使用不安全代码快速从数组转 WriteableBitmap - 林德熙。
- 使用不安全代码将 Bitmap 位图转为 WPF 的 ImageSource 以获得高性能和持续小的内存占用
- bitmap 转 wpf 的 imageSource
- System.Drawing.Bitmap转换成WPF中可用的ImageSource
- WPF Image控件中的ImageSource与Bitmap的互相转换
- Wpf ImageSource对象与Bitmap对象的互相转换
- Bitmap的内存占用
- ImageSource的使用心得
- ImageSource的使用心得
- ImageSource的使用心得
- 获得PHP代码占用内存的情况
- 获得php代码占用内存的情况
- 获得php代码占用内存的情况
- System.Drawing.Bitmap要如何轉換成WPF中可用的ImageSource
- 计算Bitmap占用的内存
- 手机 内存优化: bitmap 占用 多大内存;使用bitmap=null;bitmap.recycle();的好处
- 内存占用量的获得
- android 获取Bitmap位图所占用的内存大小
- Bitmap的使用习惯——及时释放Bitmap占用的内存
- 一个二维码实现同时支持AppStore下载地址 、安卓端下载地址
- 1.A+B问题,不用+实现加法运算
- java习题-(六)
- JSON.parse和stringify 小案例
- 数据挖掘-Apriori算法(2)
- 使用不安全代码将 Bitmap 位图转为 WPF 的 ImageSource 以获得高性能和持续小的内存占用
- [基础题] 7.第二种(*)按如下要求编写Java程序:
- 费用流-模板
- 自动人机无脑3v3脚本
- 高德地图的多人定位实现方式
- Hibernate的关联关系
- HDU 4287 Intelligent IME(字典树)
- markdown简单语法总结
- Visual->UIElement->FrameworkElement,带来更多功能的同时也带来了更多的限制