---
URL: "/zh-CN/blog/2025-05/wpf_bitmap.html"
LLMS_URL: "/zh-CN/blog/2025-05/wpf_bitmap.md"
lastUpdated: true
commentabled: true
recommended: true
title: "在 WPF 界面上高效地刷新来自 C++ 处理的超大分辨率相机图像"
description: "在 WPF 界面上高效地刷新来自 C++ 处理的超大分辨率相机图像"
date:

pageClass: "blog-page-class"
cover: "/covers/dotnet.svg"
---

---
lastUpdated: true
commentabled: true
recommended: true
title: 在 WPF 界面上高效地刷新来自 C++ 处理的超大分辨率相机图像
description: 在 WPF 界面上高效地刷新来自 C++ 处理的超大分辨率相机图像
date: 2025-05-27 16:00:00
pageClass: blog-page-class
cover: /covers/dotnet.svg
---

# 在 WPF 界面上高效地刷新来自 C++ 处理的超大分辨率相机图像 #

下面给出两种常用方案，均能让你在 WPF 界面上高效地刷新来自 C++ 处理的超大分辨率相机图像：

## 方案一：WriteableBitmap + C++/CLI 桥接 ##

### 1. 在 C++ 侧准备原始图像缓冲区 ###

```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 封装成托管接口 ###

```c++
// 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 ###

```xml
<!-- MainWindow.xaml -->
<Window x:Class="WpfApp.MainWindow"
        …>
    <Image x:Name="imgDisplay"/>
</Window>
```

```cs
// 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：

```cs
D3DImage d3dImg = new D3DImage();
imgDisplay.Source = d3dImg;
// 通过 D3D9Ex 接口调用 Lock()、SetBackBuffer()、Unlock() 来绑定你的 Direct3D surface
```

- 每次 C++ 侧更新 GPU 纹理后，只需在 UI 线程：

```cs
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。

根据你的相机分辨率和实时性能要求，选择最合适的方案即可。
