1、问题:
(20190821)做 视频的图像分析的时候,遇到 release版的exe中 BitmapSourceConvert.ToBitmapSource(IImage image)函数报错,而且是 直接内存错误 catch抓不到 全局的异常处理函数Application_DispatcherUnhandledException(...)也抓不到... exe直接崩溃...
具体的 出错函数位置是:“IntPtr ptr = source.GetHbitmap();” ZC:这里 获取 bitmap的句柄 为啥会报错,想不明白... 难道是 bitmap里面是空的?无效的?才会 导致 取句柄的时候出错?
2、我做的尝试:
2.1、个人感觉 是内存过早被GC释放??然后 踩到了 不该踩的内存?? 于是 尝试 System.Drawing.Bitmap.LockBits(...)锁定内存,我的想法 内存锁住了 总该可以使用了吧?但是 LockBits()之后 exe依旧会崩溃...
2.2、找了 另一种 Bitmap 转 BitmapSource的方式,这是 直接取的内存(不是通过句柄,∴不需要获取句柄了),这就说明 Bitmap里面的内存是 OK的,仅仅是 取句柄时 出错了(∴ LockBits不管用)...
(1)想知道到底为啥 Bitmap.GetHbitmap()会出错:现在不知道怎么弄,暂时不知道 怎么看 Bitmap.GetHbitmap()里面的源码/汇编,网上搜也没有这个问题... 暂时搁置...
3、代码:
class BitmapSourceConvert { /// <summary> /// Delete a GDI object /// </summary> /// <param name="o">The poniter to the GDI object to be deleted</param> /// <returns></returns> [DllImport("gdi32")] private static extern int DeleteObject(IntPtr o); /// <summary> /// Convert an IImage to a WPF BitmapSource. The result can be used in the Set Property of Image.Source /// </summary> /// <param name="image">The Emgu CV Image</param> /// <returns>The equivalent BitmapSource</returns> public static BitmapSource ToBitmapSource(IImage image) { try { Stopwatch sw = new Stopwatch(); sw.Start(); //System.Drawing.Bitmap source = image.Bitmap; using (System.Drawing.Bitmap source = image.Bitmap) { Console.WriteLine("ToBitmapSource(...) - 1"); BitmapData bd = source.LockBits( new Rectangle(0, 0, source.Width, source.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, source.PixelFormat); unsafe { int* pii = (int*)bd.Scan0; Console.WriteLine("ToBitmapSource(...) - 1.1 : {0}", pii[0]); } //IntPtr pp = image.Ptr; //unsafe //{ // BitmapData bitmapData = source.LockBits( // new Rectangle(0, 0, source.Width, source.Height), // System.Drawing.Imaging.ImageLockMode.ReadWrite, source.PixelFormat); // int* pii = (int*)bitmapData.Scan0; // Console.WriteLine("ToBitmapSource(...) - 1 : {0} : {1}, {2}, {3}", // bitmapData.PixelFormat, pii[0], pii[10], pii[20]); // //PixelFormat.Format24bppRgb // int* pi = (int*)pp; // Console.WriteLine("ToBitmapSource(...) - 2 : {0}; {1}, {2}:{3}, {4}, {5}", // source, source.Size, image.Ptr, pi[0], pi[10], pi[20]); //} Console.WriteLine("ToBitmapSource(...) - 2"); IntPtr ptr = source.GetHbitmap(); //obtain the Hbitmap Console.WriteLine("ToBitmapSource(...) - 3"); BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap( ptr, IntPtr.Zero, Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions()); sw.Stop(); Console.WriteLine("ToBitmapSource(...) ElapsedMilliseconds : {0}", sw.ElapsedMilliseconds); //source.UnlockBits(bd); DeleteObject(ptr); //release the HBitmap return bs; } } catch (Exception _ex) { string str = "ToBitmapSource(...) err : " + _ex.Message+", ["+DateTime.Now+"]"; Console.WriteLine(str); Trace.TraceError(str); return null; } } //public static BitmapSource ToBitmapSource(Mat _mat) //{ // //try // //{ // _mat.to.Bitmap // Bitmap source = Image.FromStream(new MemoryStream(_mat.Data)); // Bitmap source = new Bitmap(_mat.Width, _mat.Height); // source // Bitmap ^ test = gcnew Bitmap(matToConvert.rows, matToConvert.cols, 4 * matToConvert.rows, System::Drawing::Imaging::PixelFormat::Format4bppIndexed, IntPtr(matToConvert.data)); // Console.WriteLine("_mat.NumberOfChannels : {0}", _mat.NumberOfChannels); // BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromMemorySection( // _mat.Ptr, _mat.Width, _mat.Height, PixelFormats.Bgr24, (int)(_mat.Width * PixelFormats.Bgr24.BitsPerPixel / 8), 0); // return bs; // //} // //catch (Exception _ex) // //{ // // string str = "ToBitmapSource(Mat) err : " + _ex.Message + ", [" + DateTime.Now + "]"; // // Console.WriteLine(str); // // Trace.TraceError(str); // // return null; // //} //}
// ZC: 这里的转换函数 是来自:“Bitmap转换到BitmapSource - koloumi的博客 - CSDN博客.html(https://blog.csdn.net/koloumi/article/details/80577249)”
// ZC: 该方法 美中不足:多了一次MemoryStream操作,需要复制内存。 public static BitmapSource ToBitmapSource(Mat _mat) { System.Windows.Media.Imaging.BitmapFrame bf = null; //Stopwatch sw = new Stopwatch(); //sw.Start(); using (System.Drawing.Bitmap bmp = _mat.Bitmap) { using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) { //Console.WriteLine("zzzzz(...) - 1"); bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp); //Console.WriteLine("zzzzz(...) - 2"); bf = System.Windows.Media.Imaging.BitmapFrame.Create(ms, System.Windows.Media.Imaging.BitmapCreateOptions.None, System.Windows.Media.Imaging.BitmapCacheOption.OnLoad); //sw.Stop(); //Console.WriteLine("zzzzz(...) ElapsedMilliseconds : {0}", sw.ElapsedMilliseconds); //Console.WriteLine("zzzzz(...) - 3"); } } return bf; } }
4、
5、