WPF 没有用到 PictureBox
, 而是用Image代替
.
下面我试着加载显示一个图片 。
XAML
1 | <Image x:Name="srcImg"Width="400"Height="300"></Image> |
CS Attempt 1:
1 | Image<Bgr,Byte>My_Image=newImage<Bgr,byte>(Openfile.FileName); |
Error Message
1 | Cannot implicitly convert type 'System.Drawing.Bitmap' |
CS Attempt 2:
1 | Image<Bgr,Byte>My_Image=newImage<Bgr,byte>(Openfile.FileName); |
Error Message
1 | Error1The best overloaded method match for'System.Windows.Media.Imaging.BitmapImage.BitmapImage(System.Uri)' has some invalid arguments |
Image<Bgr, Byte> My_Image = new Image<Bgr, byte>(Openfile.FileName);
srcImg.Source = BitmapSourceConvert.ToBitmapSource(myImage);
public static class BitmapSourceConvert
{
[DllImport(“gdi32”)] private static extern int DeleteObject(IntPtr o); public static BitmapSource ToBitmapSource(IImage image)
{ using (System.Drawing.Bitmap source = image.Bitmap)
{
IntPtr ptr = source.GetHbitmap();
BitmapSource bs \= System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
ptr,
IntPtr.Zero,
Int32Rect.Empty,
System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
DeleteObject(ptr); return bs;
}
}
}
Bitmap bm = (Bitmap)Bitmap.FromFile(@”D:\my_testfiles\Main.png”); int count = 10000000; for (int i = 0; i < count; i++)
{ Commons.BitMapToImageSource(bm.Clone() as Bitmap);
}
结果:
当循环 1527次, 耗时 00:00:17.8860231后 报错。
ErrorTrace:
at System.Drawing.Bitmap.GetHbitmap(Color background)
at System.Drawing.Bitmap.GetHbitmap()
at SimpleClient.Commons.BitMapToImageSource(Bitmap bitmap) in D:\my_svn\universal-project\SimpleClient\Program.cs:line 165
ErrorMessage:
system.OutOfMemoryException: Out of memory.
改进:
写一个视频显示控件,内部实现显示Bitmap转换成BitmapSource。为控件Source开辟一块内存控件,然后一直刷新。首先我们使用EmuguCV里面的Capture。
控件继承Image、IDisposable接口并开放一个属性
VideoSource。
_代码如下:
_
public class CapPlayer : Image, IDisposable
{ private Capture videoSource; public Capture VideoSource
{ set { if (value != null)
{ this.videoSource = value; this.LaodCapPlayer();
}
}
} private InteropBitmap bitmapSource; private IntPtr map; private IntPtr section; public CapPlayer()
{
Application.Current.Exit += new ExitEventHandler(Current\_Exit);
} private void LaodCapPlayer()
{
videoSource.ImageGrabbed += new Capture.GrabEventHandler(videoSource\_ImageGrabbed);
videoSource.Start(); uint pcount = (uint)(videoSource.Width \* videoSource.Height \* PixelFormats.Bgr32.BitsPerPixel / 8);
section \= CreateFileMapping(new IntPtr(-1), IntPtr.Zero, 0x04, 0, pcount, null);
map \= MapViewOfFile(section, 0xF001F, 0, 0, pcount);
bitmapSource \= Imaging.CreateBitmapSourceFromMemorySection(section, (int)videoSource.Width, (int)videoSource.Height, PixelFormats.Bgr32,
(int)(videoSource.Width \* PixelFormats.Bgr32.BitsPerPixel / 8), 0) as InteropBitmap; this.Source = bitmapSource;
} void videoSource\_ImageGrabbed(object sender, EventArgs e)
{
Capture camera \= sender as Capture; var frame = camera.RetrieveBgrFrame().Bitmap; if (this.Dispatcher != null)
{ this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, (SendOrPostCallback)delegate { if (map != IntPtr.Zero)
{ try {
System.Drawing.Imaging.BitmapData bmpData \= frame.LockBits(new System.Drawing.Rectangle(0, 0, (int)videoSource.Width, (int)videoSource.Height),
System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppRgb); /\* Get the pointer to the pixels \*/ IntPtr pBmp \= bmpData.Scan0; int srcStride = bmpData.Stride; int pSize = srcStride \* (int)videoSource.Height;
CopyMemory(map, pBmp, pSize);
frame.UnlockBits(bmpData);
} catch (Exception ex)
{
Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Write(ex, "Info", 0);
}
} if (bitmapSource != null)
{
bitmapSource.Invalidate();
}
}, null);
} if (captureLock)
{ try { lock (mutCurrentImg)
{
camera.RetrieveBgrFrame().Save(imageFileName);
}
} catch (System.Exception ex)
{
Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Write(ex, "Info", 0);
}
captureLock \= false;
}
} void Current\_Exit(object sender, ExitEventArgs e)
{ this.Dispose();
} object mutCurrentImg = new object(); bool captureLock = false; string imageFileName = string.Empty; public void ImaggingCapture(string imageFileName)
{ this.imageFileName = imageFileName; this.captureLock = true;
} #region IDisposable Members
public void Dispose()
{ if (videoSource != null)
videoSource.Stop();
Application.Current.Exit \-= new ExitEventHandler(Current\_Exit);
} #endregion \[DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory")\] private static extern void CopyMemory(IntPtr Destination, IntPtr Source, int Length);
\[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);
}
测试结果:无异常,但是发现比较占用CPU 10%左右,内存 122M 左右,线程数32.
感觉不太理想CPU占用太多,我们把EmuguCV的Capture改为AForge.NEt的VideoCaptureDevice,代码如下:
public class CapPlayer : Image, IDisposable
{ private VideoCaptureDevice videoSource; private InteropBitmap bitmapSource; private IntPtr map; private IntPtr section; public CapPlayer()
{
Application.Current.Exit += new ExitEventHandler(Current\_Exit); this.Loaded += new RoutedEventHandler(CapPlayer\_Loaded);
videoSource \= new VideoCaptureDevice(@"device:pnp:\\\\?\\usb#vid\_0ac8&pid\_305b#5&ee85354&0&2#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\\global");
} void CapPlayer\_Loaded(object sender, RoutedEventArgs e)
{
videoSource.NewFrame += new NewFrameEventHandler(videoSource\_NewFrame);
videoSource.Start(); uint pcount = (uint)(this.Width \* this.Height \* PixelFormats.Bgr32.BitsPerPixel / 8);
section \= CreateFileMapping(new IntPtr(-1), IntPtr.Zero, 0x04, 0, pcount, null);
map \= MapViewOfFile(section, 0xF001F, 0, 0, pcount);
bitmapSource \= System.Windows.Interop.Imaging.CreateBitmapSourceFromMemorySection(section, (int)this.Width, (int)this.Height, PixelFormats.Bgr32,
(int)(this.Width \* PixelFormats.Bgr32.BitsPerPixel / 8), 0) as InteropBitmap; this.Source = bitmapSource;
} void Current\_Exit(object sender, ExitEventArgs e)
{ this.Dispose();
} object mutCurrentImg = new object(); bool captureLock = false; string imageFileName = string.Empty; public void ImaggingCapture(string imageFileName)
{ this.imageFileName = imageFileName; this.captureLock = true;
} private void videoSource\_NewFrame(object sender, NewFrameEventArgs eventArgs)
{ //eventArgs.Frame.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp);
if (this.Dispatcher != null)
{ this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, (SendOrPostCallback)delegate { if (map != IntPtr.Zero)
{
System.Drawing.Imaging.BitmapData bmpData \= eventArgs.Frame.LockBits(new System.Drawing.Rectangle(0, 0, (int)this.Width, (int)this.Height),
System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppRgb); /\* Get the pointer to the pixels \*/ IntPtr pBmp \= bmpData.Scan0; int srcStride = bmpData.Stride; int pSize = srcStride \* (int)this.Height;
CopyMemory(map, pBmp, pSize);
eventArgs.Frame.UnlockBits(bmpData);
} if (bitmapSource != null)
{
bitmapSource.Invalidate();
}
}, null);
} if (captureLock)
{ try { lock (mutCurrentImg)
{
eventArgs.Frame.Save(imageFileName);
}
} catch (System.Exception ex)
{
}
captureLock \= false;
}
} #region IDisposable Members
public void Dispose()
{ if (videoSource != null)
videoSource.SignalToStop();
} #endregion \[DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory")\] private static extern void CopyMemory(IntPtr Destination, IntPtr Source, int Length);
\[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);
}
测试结果:无异常,但是发现占用CPU 1%左右,内存 72M 左右,线程数28. 是不是比较理想呢!!
CPU
内存
线程数
EmuguCV
10%左右
122M左右
32
Aforge.Net
1%左右
72M左右
28
我的电脑配置.
摄像头:FrameRate 30,Width 320 Height 240.
电脑型号 戴尔 Precision WorkStation T3400 Tower
操作系统 Windows 7 旗舰版 32位 SP1 ( DirectX 11 )
处理器 英特尔 酷睿2 双核 E8400 @ 3.00GHz
主板 戴尔 0HY553 (英特尔 X38/X48 Express 芯片组 - ICH9R)
内存 4 GB ( 海力士 DDR2 800MHz / 金士顿 DDR2 667MHz )
主硬盘 西数 WDC WD3200AAKS-75L9A0 ( 320 GB / 7200 转/分 )
显卡 Nvidia Quadro NVS 290 ( 256 MB / Nvidia )
显示器 戴尔 DELA04A DELL E170S ( 17.1 英寸 )
光驱 飞利浦-建兴 DVD-ROM DH-16D5S DVD光驱
声卡 Analog Devices AD1984 @ 英特尔 82801I(ICH9) 高保真音频
网卡 博通 BCM5754 NetXtreme Gigabit Ethernet / 戴尔
系统文件gdi32.dll是存放在Windows系统文件夹中的重要文件,通常情况下是在安装操作系统过程中自动创建的,对于系统正常运行来说至关重要。除非用户电脑被木马病毒、或是流氓软件篡改导致出现gdi32.dll丢失、缺失损坏等弹窗现象,否则不建议用户对该类文件(gdi32.dll)进行随意的修改。
gdi32.dll是Windows GDI图形用户界面相关程序,包含的函数用来绘制图像和显示文字。