# ImageDisplay
Avanti.Toolkit.MachineVision.Controls.ImageDisplay 是基于 Skia 的机器视觉图片显示表面。
包名为 Avanti.Toolkit.MachineVision.ImageDisplay。首版支持 Gray8 原始帧和静态栅格图片;
静态图片按亮度转换为 Gray8,暂不提供彩色或 16 位灰度显示。
# 注册与显示
在现有 UseAvantiToolkit 配置中调用:
using Avanti.Toolkit.Controls;
using Avanti.Toolkit.Desktop.Controls;
using Avanti.Toolkit.MachineVision;
builder.UseDesktopControls();
builder.UseMachineVisionImageDisplay();
builder.UseImageLoading(options =>
{
// 示例 16384×4000 超过框架默认的 6400 万像素限制,应用显式配置。
options.MaxImagePixelCount = 100_000_000;
options.MaxDecodedImageBytes = 512L * 1024 * 1024;
});
UseMachineVisionImageDisplay() 只注册控件主题;应用图片服务由第一阶段的
UseDesktopControls() 或 UseImageLoading() 配置。控件注册可以放入 Deferred,
但图片服务及其预算配置必须保留在第一阶段。
<vision:ImageDisplay xmlns:vision="urn:avanti-toolkit/machine-vision"
Source="D:\Images\sample.png" />
Source 使用现有 ImageSource 契约,静态来源经过应用的 IImageLoader;帧流使用 FrameImageSource。
普通静态图片控件不消费帧流,收到该来源时返回明确的 UnsupportedFormat 错误。
本控件不接收 SVG 或 BorrowedImageSource;静态栅格必须通过编码来源进入受校验的解码管线。
# 连续帧
先在 UI 线程把 FrameImageSource 赋给已挂载显示控件,再由单个生产者提交:
var source = new FrameImageSource("Camera 1");
viewer.Source = source;
// 生产者线程:owner 是相机适配器交出的 IMemoryOwner<byte>。
using var frame = new ImageFrame(frameId, width, height, stride, owner);
FramePresentation drawn = await source.SubmitAsync(frame, cancellationToken);
SubmitAsync 返回时该帧已完成至少一次可见视口绘制,随后才提交下一帧。它不确认显示器物理扫描输出。
帧号须严格递增;宽高为正、步长至少等于宽度,缓冲区至少为 stride * height 字节。
提交前调用方拥有缓冲区;接收成功后所有权转交显示控件,调用方不得写入。返回后也不能自行复用,
必须等待租约的 Dispose 归还。失败发生在接收前时仍由调用方释放;接收后取消不提前释放正在渲染的缓冲区。
无法转移相机缓冲区时使用 SubmitCopyAsync,复制期间源内存必须稳定。
同一来源只允许一个显示控件与一个串行生产者。冻结、隐藏和最小化会向生产者施加背压;换源、卸载及关闭取消等待。 采集适配器必须真正等待提交;不能暂停的相机由宿主提供可靠录制,不能通过额外无限队列模拟无遗漏。
# 查看与扩展接口
| 接口 | 行为 |
|---|---|
Zoom、MinZoom、MaxZoom |
默认范围 1/256~256;Zoom=1 是一原图像素对应一物理屏幕像素 |
FitToView()、ActualSize()、ZoomAt()、Pan() |
适应、1:1、指定锚点缩放和平移 |
IsFrozen |
保留当前帧,暂停消费 |
PixelGridMode、PixelGridThreshold |
自动/隐藏/显示;自动阈值默认 8 物理像素 |
Viewport、ImageToView()、ViewToImage() |
原图像素与控件 DIP 坐标转换 |
TryGetPixel()、PixelChanged |
返回原始帧号、整数坐标和灰度值;图外无值 |
State、Error、StateChanged |
加载、就绪、错误状态;状态事件通知宿主更新 |
FrameRendered、RenderBackend |
首次绘制确认及实际 Skia GPU/软件后端 |
CpuMemoryBytes、GpuMemoryBytes |
当前显示控件持有的数据与瓦片占用;GPU 采用保守估算 |
CpuMemoryLimit、GpuMemoryLimit |
首次挂载前配置;默认 512 MiB / 128 MiB |
ImageOverlays、ScreenOverlays、InvalidateOverlays() |
不暴露 Skia 对象的覆盖层快照扩展 |
ActiveTool |
UI 线程输入工具,拥有激活、取消和指针捕获生命周期 |
滚轮以鼠标为中心缩放,中键或空格+左键拖动。Escape 或失去捕获取消交互。 首次输入适应窗口,后续帧保留视口;图片较小时居中,较大时限制平移使视口不越过图片边缘。
覆盖层几何使用原图坐标,控制柄与命中范围可使用屏幕单位,工具可在冻结帧上交互。 当前不提供这些形状的编辑、撤销、旋转、翻转或多视口联动。