我需要显示一个原始字节数组中的8k RGB图像,这是我在wpf控制中以高fps速度获得的帧采集器。我能够成功地将字节数组转换为BitmapSource,并将其显示在WPF的图像窗口中。但是,由于抓取器在显示后以大约5FPS的速度生成图像,我正在释放对对象的保留,但GC需要时间收集内存,在此内存中,我的应用程序内存会增加,并冻结应用程序和我的系统。如何正确处理使用以下方法创建的BitmapSource(CachedBitmap)。请帮我处理使用后的物品。
我在图像更改时尝试了GC.Collect(),但它不起作用。
下面是我的字节数组到位图转换代码,
int Width = 7680;
int Height = 4320;
PixelFormat PixelFormat = PixelFormats.Bgr24;
int BytesPerPixel = 3;
public BitmapSource ByteToImage(byte[] imageData)
{
var stride = BytesPerPixel * Width;
BitmapSource bitmapSource = BitmapSource.Create(Width, Height, 96d, 96d, PixelFormat, null, imageData, stride);
bitmapSource.Freeze();
return bitmapSource;
}发布于 2018-12-21 21:09:11
这听起来像是合成目标渲染的可能候选者,尝试将此添加到您的MainWindow构造函数中:
CompositionTarget.Rendering += CompositionTarget_Rendering;然后实现函数本身:
void CompositionTarget_Rendering(object sender, EventArgs e)
{
// dispose previous image, create and assign the new one
}正确地这样做,它还应该处理目标机器无法跟上您期望的帧速率的情况。
更新: BitmapSource只使用常规内存,所以正确的行为是让GC清理它。如果在你的例子中没有发生这种情况,那么这意味着由于某种原因,可能是显示的原因,某些东西正在抓住那个内存。下面是一个使用CompositionTarget.Rendering的例子,我在收集之前和之后都转储了GC内存,这样你就可以很清楚地看到它被正确地收集了:
public MainWindow()
{
InitializeComponent();
CompositionTarget.Rendering += CompositionTarget_Rendering;
}
private void CompositionTarget_Rendering(object sender, EventArgs e)
{
// remove reference to old image
this.theImage.Source = null;
// invoke GC
Debug.WriteLine(GC.GetTotalMemory(false));
GC.Collect();
Debug.WriteLine(GC.GetTotalMemory(false));
// create and assign new image
const int width = 1000;
const int height = 1000;
var pixels = new uint[width * height];
uint color = (uint)((new Random((int)DateTime.Now.Ticks)).Next(0x1000000) | 0xff000000);
for (int i = 0; i < width * height; i++)
pixels[i] = color;
this.theImage.Source = BitmapSource.Create(width, height, 96, 96, PixelFormats.Bgra32, null, pixels, width * 4);
}发布于 2018-12-25 03:03:42
也许你应该试试可写的位图:
WriteableBitmap writeableBitmap = new WriteableBitmap(
(int)width,
(int)height,
96,
96,
PixelFormats.Bgr32,
null);
int stride = width * writeableBitmap.Format.BitsPerPixel / 8现在,当你收到一个帧时,你可以将它写入可写的位图中:
writeableBitmap.Lock();
writeableBitmap.WritePixels(new Int32Rect(0, 0, width, height), imageData, stride, 0);
writeableBitmap.Unlock();通过这种方式,您不需要创建新的映像。只需覆盖位图数据即可。但是要注意,始终要将数据从源抓取到同一个缓冲区数组中。
https://stackoverflow.com/questions/53879583
复制相似问题