我编写的应用程序显示了我从某个网络层获取的图像。 我把图像作为字节数组,我做反序列化并将byte []转换为bitmapimage并在我的wpf应用程序上显示它。
图像每50毫秒更改一次。
我正在考虑如何有效地做到这一点 - 我如何处理最低GC呼叫......
我的意思是......当我需要创建新的bitmapimage时,我如何处理旧的bitmapimage?
是否有旧的bitmapImage重用或类似的东西,通过这种方式减少对GC的调用次数?
答案 0 :(得分:2)
您需要避免每帧创建新的字节数组。您可以使用Array.Copy(或C#指针)将数据从网络服务复制到映像源。
但是,如果您的网络服务占用太多内存,因为它为每个帧创建了新的字节数组,那么您就遇到了问题。
我已将相机直播流添加到我的WPF应用程序,并注意到一个有趣的事实。我使用EgmuCV来抓取帧。它为我捕获了System.Drawing.Bitmap
帧。我使用转换器将帧转换为BitmapImage
。表现相当不错。
有趣的是,当我调用bitmap.Save(filePath)
或bitmap.Copy()
时,它会从流中保存大部分当前帧,而不是创建位图时的帧。当我在同一个位图实例上多次调用save时,我会得到不同的图像。这意味着位图下的数据正在发生变化,而不是一直创建新数据,这是您应该实现的目标。这是代码:
_grabber = new Capture();
....
//on frame requested:
Image<Brg, byte> currentFrame = _grabber.QueryFrame();
Bitmap bitmap = currentFrame.Bitmap; //System.Drawing
public class BitmapToImageSourceConverter: IValueConverter
{
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) return null;
var bitmap = (Bitmap) value;
var hBitmap = bitmap.GetHbitmap();
using (var handle = new SafeHBitmapHandle(hBitmap, true))
{
if (handle.IsInvalid) return null;
return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
handle.DangerousGetHandle(),
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
答案 1 :(得分:-1)
我做了一点拐杖,他可以帮助你:)。
WPF:
protected System.Drawing.Bitmap m_Bmp = new System.Drawing.Bitmap(yourWidth, yourHeight);
protected System.Windows.Forms.PictureBox m_PictureBox = new System.Windows.Forms.PictureBox();
protected Rectangle m_Rect;
public MyWindow()
{
InitializeComponent();
m_PictureBox.Image = m_Bmp;
m_Rect= new Rectangle(0, 0, m_Bmp.Width, m_Bmp.Height);
f_WindowsFormsHost.Child = m_PictureBox;
}
private void timer_Tick()
{
System.Drawing.Imaging.BitmapData bmpData = m_Bmp.LockBits(m_Rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, m_Bmp.PixelFormat);
IntPtr ptr = bmpData.Scan0;
//or use System.Runtime.InteropServices.Marshal.Copy(youData, 0, ptr, countBytes);
Random r = new Random();
unsafe {
byte *data = (byte*)ptr;
for (int i = 0; i < bmpData.Stride * m_Bmp.Height; ++i)
{
*data = (byte)r.Next(256);
++data;
}
}
m_Bmp.UnlockBits(bmpData);
m_PictureBox.Refresh();
}
CS:
0x0000: c40e 6457 a310 01bb e6c0 f6b1 b5ed ec6b �.dW�..������k
0x0010: 23f8 8018 015e dfc7 0000 0101 080a 17c2 #�...^��.......�
0x0020: 6af1 0014 f0c3 1703 0300 6f00 0000 0000 j�..��....o.....
0x0030: 0000 0208 7db4 d0c1 846d ca75 323c e6cb ....}���.m�u2<��
0x0040: 1636 be16 942f 51ea 1caf 1c09 c085 3dbc .6�../Q�.�..�.=�
0x0050: 7642 vB