在 WPF 界面上高效地刷新来自 C++ 处理的超大分辨率相机图像
下面给出两种常用方案,均能让你在 WPF 界面上高效地刷新来自 C++ 处理的超大分辨率相机图像:
方案一:WriteableBitmap + C++/CLI 桥接
1. 在 C++ 侧准备原始图像缓冲区
// NativeProcessor.h (纯 C++)
class NativeProcessor {
public:
NativeProcessor(int w, int h);
~NativeProcessor();
// 调用后,_buffer 中存放 BGRA32 数据
void GrabFrame();
uint8_t* GetBuffer() const { return _buffer; }
int Width() const { return _w; }
int Height() const { return _h; }
int Stride() const { return _w * 4; }
private:
int _w, _h;
uint8_t* _buffer;
};
2. 用 C++/CLI 封装成托管接口
// ManagedBridge.h (C++/CLI)
#pragma once
#include "NativeProcessor.h"
using namespace System;
namespace Bridge {
public ref class FrameProvider {
public:
FrameProvider(int width, int height)
: _native(new NativeProcessor(width, height)) {}
~FrameProvider() { this->!FrameProvider(); }
!FrameProvider() { delete _native; }
// 抓取一帧
void Update() { _native->GrabFrame(); }
// 获取图像指针给 WPF
IntPtr GetBuffer() {
return IntPtr(_native->GetBuffer());
}
property int Width { int get() { return _native->Width(); }}
property int Height { int get() { return _native->Height(); }}
property int Stride { int get() { return _native->Stride(); }}
private:
NativeProcessor* _native;
};
}
把这个项目编译成 Bridge.dll,在你的 WPF (.NET) 项目中直接引用。
3. 在 WPF 中创建并不断更新 WriteableBitmap
<!-- MainWindow.xaml -->
<Window x:Class="WpfApp.MainWindow"
…>
<Image x:Name="imgDisplay"/>
</Window>
// MainWindow.xaml.cs
using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Bridge; // 引用 C++/CLI
namespace WpfApp {
public partial class MainWindow : Window {
private FrameProvider _provider;
private WriteableBitmap _wb;
public MainWindow() {
InitializeComponent();
_provider = new FrameProvider(3840, 2160); // 例如 4K
_wb = new WriteableBitmap(
_provider.Width, _provider.Height,
96, 96, PixelFormats.Bgra32, null);
imgDisplay.Source = _wb;
// 启动定时器或后台线程不断拉帧
var timer = new System.Timers.Timer(30); // ~33 FPS
timer.Elapsed += (s, e) => RefreshFrame();
timer.Start();
}
private void RefreshFrame() {
_provider.Update(); // C++ 抓取并处理一帧
var bufferPtr = _provider.GetBuffer();
Dispatcher.Invoke(() => {
_wb.Lock();
// 直接把 native 缓冲区复制到 WriteableBitmap
_wb.WritePixels(
new Int32Rect(0, 0, _wb.PixelWidth, _wb.PixelHeight),
bufferPtr,
_provider.Stride * _provider.Height,
_provider.Stride);
_wb.Unlock();
});
}
}
}
优点
-
完全托管式调用,代码清晰;
-
WriteableBitmap.WritePixels 在大块内存拷贝时性能较好;
-
易于调试、跨平台 .NET Core/Framework 均支持。
方案二:D3DImage + Direct3D 资源共享
当分辨率更高(8K+)、帧率更大(60+ FPS)时,CPU 拷贝已经成为瓶颈,这时可考虑 GPU 直通渲染:
-
C++ 侧
-
使用 Direct3D11/9Ex 创建一个
ID3D11Texture2D或IDirect3DSurface9,把相机数据上传到 GPU 资源。 -
导出这个 D3D 资源的共享句柄(shared handle 或 DXGI SharedResource)。
-
-
WPF 侧
-
在 C# 中通过 P/Invoke 拿到共享资源句柄,创建一个
D3DImage:D3DImage d3dImg = new D3DImage(); imgDisplay.Source = d3dImg; // 通过 D3D9Ex 接口调用 Lock()、SetBackBuffer()、Unlock() 来绑定你的 Direct3D surface -
每次 C++ 侧更新 GPU 纹理后,只需在 UI 线程:
d3dImg.Lock(); d3dImg.AddDirtyRect(new Int32Rect(0,0,width,height)); d3dImg.Unlock(); -
WPF 会直接使用 GPU 纹理渲染,大幅减轻 CPU 负担。
-
优点
-
零拷贝、最低延迟;
-
GPU 加速,适合实时性极强的场景。
小结
-
简单场景(<4K,<30FPS):建议用 WriteableBitmap + C++/CLI,开发成本最低。
-
极限场景(>4K,>60FPS):推荐使用 D3DImage + 资源共享,最大化利用 GPU。
根据你的相机分辨率和实时性能要求,选择最合适的方案即可。

浙公网安备 33010602011771号