方案一: 使用 MemoryStream 先将 Bitmap 储存成 MemoryStream ,然后指定给 BitmapImage 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 void UpdateImageByMemoryStream (){ using (MemoryStream memory = new MemoryStream()) { int w = 0 , h = 0 ; MyDll.GetBitmapSize(ref w, ref h); System.Drawing.Bitmap bitmap; bitmap = new System.Drawing.Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppArgb); System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0 , 0 , bitmap.Width, bitmap.Height); while (true ) { System.Drawing.Imaging.BitmapData bmpData = bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap.PixelFormat); IntPtr ptr = bmpData.Scan0; var status = MyDll.GetBitmapData(ptr) >= 0 ? true : false ; bitmap.UnlockBits(bmpData); if (status) { bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Bmp); UpdateUI(() => { memory.Position = 0 ; BitmapImage bitmapimage = new BitmapImage(); bitmapimage.BeginInit(); bitmapimage.StreamSource = memory; bitmapimage.CacheOption = BitmapCacheOption.OnLoad; bitmapimage.EndInit(); imgPreview.Source = bitmapimage; }); } } } }
方案二: 调用 Imaging.CreateBitmapSourceFromHBitmap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 void UpdateImageByBitmap (){ int w = 0 , h = 0 ; MyDll.GetBitmapSize(ref w, ref h); var bitmap = new System.Drawing.Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppArgb); System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0 , 0 , bitmap.Width, bitmap.Height); while (true ) { System.Drawing.Imaging.BitmapData bmpData = bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap.PixelFormat); IntPtr ptr = bmpData.Scan0; var status = MyDll.GetBitmapData(ptr) >= 0 ? true : false ; bitmap.UnlockBits(bmpData); if (status) UpdateUI(() => { imgPreview.Source = BitmapHelper.BitmapToBitmapSource(bitmap); }); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class BitmapHelper { [DllImport("gdi32.dll" ) ] private static extern bool DeleteObject (IntPtr hObject ) ; public static BitmapSource BitmapToBitmapSource (System.Drawing.Bitmap bitmap ) { IntPtr ptr = bitmap.GetHbitmap(); BitmapSource result = Imaging.CreateBitmapSourceFromHBitmap( ptr, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); DeleteObject(ptr); return result; } }
方案三: 使用 WriteableBitmap 注:这个方法会长时间占用 UI 线程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 void UpdateImageByWriteBitmap (){ int w = 0 , h = 0 ; MyDll.GetBitmapSize(ref w, ref h); var rect = new System.Windows.Int32Rect(0 , 0 , w, h); UpdateUI(() => { imgPreview.Source = writeBitmap = new WriteableBitmap(rect.Width, rect.Height, 96 , 96 , PixelFormats.Bgra32, null ); }); while (true ) { UpdateUI(() => { writeBitmap.Lock(); if (MyDll.GetBitmapData(writeBitmap.BackBuffer) >= 0 ) writeBitmap.AddDirtyRect(rect); writeBitmap.Unlock(); }); } }
MainWindow.xaml.cs 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 using System;using System.IO;using System.Runtime.InteropServices;using System.Windows;using System.Windows.Controls;using System.Windows.Interop;using System.Windows.Media;using System.Windows.Media.Imaging;namespace WpfDemo { public partial class MainWindow : Window { Image imgPreview; WriteableBitmap writeBitmap; public MainWindow () { InitializeComponent(); } void UpdateUI (Action x ) { if (imgPreview.Dispatcher.CheckAccess()) { x.Invoke(); } else { imgPreview.Dispatcher.Invoke(x); } } } }
调用 DLL 获取图片数据 1 2 3 4 5 6 7 8 9 10 public class MyDll { [DllImport("xxx.dll" , CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl) ] public static extern void GetBitmapSize (ref int width, ref int height ) ; [DllImport("xxx.dll" , CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl) ] public static extern int GetBitmapData (IntPtr desFrameData ) ; }