1.InteropBitmap指定内存,绑定WPF的Imag控件的Source属性
创建InteropBitmap的时候,像素的格式必须为PixelFormats.Bgr32,
如果不是的话在绑定到Image控件的Source属性,刷新新界面(BitmapSource.Invalidate())的时候会造成内存泄露。
2. 内存映射:
//内存共享类 internal class Win32Mess { [DllImport("VCamBridge.dll", EntryPoint = "InitializeCam", CallingConvention = CallingConvention.Cdecl)] public static extern byte InitializeCam(string header, string body); [DllImport("VCamBridge.dll", EntryPoint = "SetFrameInfo", CallingConvention = CallingConvention.Cdecl)] public static extern void SetFrameInfo(int width, int height); [DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory")] public static extern void CopyMemory(IntPtr Destination, IntPtr Source, int Length); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, IntPtr lParam); [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern IntPtr CreateFileMapping(int hFile, IntPtr lpAttributes, uint flProtect, uint dwMaxSizeHi, uint dwMaxSizeLow, string lpName); [DllImport("Kernel32.dll", CharSet = CharSet.Auto)] public static extern IntPtr OpenFileMapping(int dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, string lpName); [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern IntPtr MapViewOfFile(IntPtr hFileMapping, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, uint dwNumberOfBytesToMap); [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern bool UnmapViewOfFile(IntPtr pvBaseAddress); [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern bool CloseHandle(IntPtr handle); [DllImport("kernel32", EntryPoint = "GetLastError")] public static extern int GetLastError(); const int ERROR_ALREADY_EXISTS = 183; const int FILE_MAP_COPY = 0x0001; public const int FILE_MAP_WRITE = 0x0002; const int FILE_MAP_READ = 0x0004; public const int FILE_MAP_ALL_ACCESS = 0x0002 | 0x0004; //0xF001F; const int PAGE_READONLY = 0x02; const int PAGE_READWRITE = 0x04; const int PAGE_WRITECOPY = 0x08; const int PAGE_EXECUTE = 0x10; const int PAGE_EXECUTE_READ = 0x20; const int PAGE_EXECUTE_READWRITE = 0x40; const int SEC_COMMIT = 0x8000000; const int SEC_IMAGE = 0x1000000; const int SEC_NOCACHE = 0x10000000; const int SEC_RESERVE = 0x4000000; const int INVALID_HANDLE_VALUE = -1; IntPtr m_hSharedMemoryFile = IntPtr.Zero; IntPtr m_pwData = IntPtr.Zero; bool m_bAlreadyExist = false; bool m_bInit = false; public bool IsOpen { get { return this.m_bInit; } } long m_MemSize = 0; public Win32Mess() { } ~Win32Mess() { Close(); } /// /// 初始化共享内存 /// /// 共享内存名称 /// 共享内存大小 /// public int Init(string strName, long lngSize) { if (lngSize <= 0 || lngSize > 0x00800000) lngSize = 0x00800000; m_MemSize = lngSize; if (strName.Length > 0) { //创建内存共享体(INVALID_HANDLE_VALUE) m_hSharedMemoryFile = CreateFileMapping(INVALID_HANDLE_VALUE, IntPtr.Zero, (uint)PAGE_READWRITE, 0, (uint)lngSize, strName); if (m_hSharedMemoryFile == IntPtr.Zero) { m_bAlreadyExist = false; m_bInit = false; return 2; //创建共享体失败 } else { if (GetLastError() == ERROR_ALREADY_EXISTS) //已经创建 { m_bAlreadyExist = true; } else //新创建 { m_bAlreadyExist = false; } } //--------------------------------------- //创建内存映射 m_pwData = MapViewOfFile(m_hSharedMemoryFile, FILE_MAP_ALL_ACCESS, 0, 0, (uint)lngSize); if (m_pwData == IntPtr.Zero) { m_bInit = false; CloseHandle(m_hSharedMemoryFile); return 3; //创建内存映射失败 } else { m_bInit = true; if (m_bAlreadyExist == false) { //初始化 } } //---------------------------------------- } else { return 1; //参数错误 } return 0; //创建成功 } public InteropBitmap GetImage(System.Drawing.Size sizeMemory) { if (m_bInit) return System.Windows.Interop.Imaging.CreateBitmapSourceFromMemorySection(m_hSharedMemoryFile, (int)sizeMemory.Width, (int)sizeMemory.Height, PixelFormats.Bgr32, (int)(sizeMemory.Width * PixelFormats.Bgr32.BitsPerPixel / 8), 0) as InteropBitmap; else return null; } /// /// 关闭共享内存 /// public void Close() { if (m_bInit) { UnmapViewOfFile(m_pwData); CloseHandle(m_hSharedMemoryFile); m_hSharedMemoryFile = IntPtr.Zero; m_bInit = false; } } /// /// 读数据 /// /// 数据 /// 起始地址 /// 个数 /// public int Read(ref byte[] bytData, int lngAddr, int lngSize) { if (lngAddr + lngSize > m_MemSize) return 2; //超出数据区 if (m_bInit) { Marshal.Copy(m_pwData, bytData, lngAddr, lngSize); } else { return 1; //共享内存未初始化 } return 0; //读成功 } /// /// 写数据 /// /// 数据 /// 起始地址 /// 个数 /// public int Write(byte[] bytData, int lngAddr, int lngSize) { if (lngAddr + lngSize > m_MemSize) return 2; //超出数据区 if (m_bInit) { Marshal.Copy(bytData, lngAddr, m_pwData, lngSize); } else { return 1; //共享内存未初始化 } return 0; //写成功 } public int Write(IntPtr lngAddr, int lngSize) { if (lngSize > m_MemSize) return 2; //超出数据区 if (m_bInit) { CopyMemory(m_pwData, lngAddr, lngSize); } else { return 1; //共享内存未初始化 } return 0; //写成功 } }