QuarkCanvas.WPF
1.0.7.5
dotnet add package QuarkCanvas.WPF --version 1.0.7.5
NuGet\Install-Package QuarkCanvas.WPF -Version 1.0.7.5
<PackageReference Include="QuarkCanvas.WPF" Version="1.0.7.5" />
<PackageVersion Include="QuarkCanvas.WPF" Version="1.0.7.5" />
<PackageReference Include="QuarkCanvas.WPF" />
paket add QuarkCanvas.WPF --version 1.0.7.5
#r "nuget: QuarkCanvas.WPF, 1.0.7.5"
#:package QuarkCanvas.WPF@1.0.7.5
#addin nuget:?package=QuarkCanvas.WPF&version=1.0.7.5
#tool nuget:?package=QuarkCanvas.WPF&version=1.0.7.5
QuarkCanvas
一个基于 SkiaSharp 的高性能 WPF 画布控件,提供强大的图像显示和交互式 ROI(感兴趣区域)编辑功能。
功能特性
- 高性能渲染:基于 SkiaSharp 实现硬件加速的 2D 图形渲染
- 图像显示:支持多种图像格式(BMP、JPG、PNG、GIF),具有自动适应视图功能
- 交互式 ROI 编辑:
- Rectangle1D(轴对齐矩形)
- Rectangle2D(旋转矩形)
- Circle(圆形)
- Ellipse(椭圆)
- Line(直线)
- Polygon(多边形,支持顶点编辑)
- 缩放与平移:鼠标滚轮缩放、拖拽平移
- 导出功能:支持将画布内容导出为图像文件
- 多窗口支持:弹出窗口用于图像查看
- 可自定义外观:
- 棋盘格背景
- 自定义描边/填充颜色和透明度
- 十字线显示(固定十字线和鼠标跟随十字线)
使用场景
工业视觉检测
- 显示工业相机采集的图像
- 绘制和编辑检测区域(ROI)
- 标注图像测量结果
- 导出检测结果
医学影像
- 显示医学影像(X 光、CT、MRI)
- 标记感兴趣区域
- 测量距离和面积
文档处理
- 图像预览和标注
- 表单区域选择
- 批量图像处理预览
通用图像查看
- 快速图像查看,支持缩放/平移
- 图像对比
- 截图标注
API 参考
图像显示
DisplayImage(BitmapSource bitmap)
在画布上显示 WPF BitmapSource。
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.UriSource = new Uri("image.bmp");
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.EndInit();
canvas.DisplayImage(bitmap);
canvas.FitToView();
DisplayImage(string imageFilePath)
根据文件路径显示图像。
canvas.DisplayImage(@"D:\image.bmp");
DisplayImage(byte[] bytes)
从字节数组显示图像。
var bytes = File.ReadAllBytes(path);
canvas.DisplayImage(bytes);
DisplayImage(Stream stream)
从流中显示图像。
canvas.DisplayImage(fileStream);
ROI 显示
Display(IShapeStructure shape)
显示单个形状(非交互式)。形状被渲染为路径,不具备编辑功能。
// 显示圆形
canvas.Display(new SharpBoxesCore.DataStruct.Structure.Circle(250, 250, 250));
// 显示 Rectangle1D(轴对齐矩形)
canvas.Display(new SharpBoxesCore.DataStruct.Structure.Rectangle1D(
new SharpBoxesCore.DataStruct.Structure.Point(600, 300),
100,
100
));
// 显示 Rectangle2D(旋转矩形)
canvas.Display(new SharpBoxesCore.DataStruct.Structure.Rectangle2D(
new SharpBoxesCore.DataStruct.Structure.Point(300, 300),
100,
100,
30 // 角度(度)
));
// 显示椭圆
canvas.Display(new SharpBoxesCore.DataStruct.Structure.Ellipse(100, 200, 400, 100, 60));
// 显示直线
canvas.Display(new SharpBoxesCore.DataStruct.Structure.Line(
new SharpBoxesCore.DataStruct.Structure.Point(100, 100),
new SharpBoxesCore.DataStruct.Structure.Point(900, 900)
));
// 显示多边形
var polygon = new SharpBoxesCore.DataStruct.Structure.Polygon(
new List<SharpBoxesCore.DataStruct.Structure.Point>
{
new(100, 100),
new(300, 100),
new(200, 200),
},
true // 是否闭合
);
canvas.Display(polygon);
// 显示点
canvas.Display(new SharpBoxesCore.DataStruct.Structure.Point(500, 500));
// 显示文本
Text text = new("Hello World", new SharpBoxesCore.DataStruct.Structure.Point(1000, 1000))
{
Color = Colors.Black,
};
canvas.Display(text);
Displays<T>(List<T> shapes)
一次性显示多个形状(批量渲染,效率更高)。
// 显示多个矩形
var rects = new List<SharpBoxesCore.DataStruct.Structure.Rectangle1D>();
rects.Add(new SharpBoxesCore.DataStruct.Structure.Rectangle1D(100, 100, 1000, 900));
rects.Add(new SharpBoxesCore.DataStruct.Structure.Rectangle1D(200, 200, 500, 500));
canvas.Displays(rects);
// 显示多条直线
List<SharpBoxesCore.DataStruct.Structure.Line> lines = [];
for (int i = 0; i < 1000; i++)
{
lines.Add(new SharpBoxesCore.DataStruct.Structure.Line(
new SharpBoxesCore.DataStruct.Structure.Point(100 + 2 * i, 100),
new SharpBoxesCore.DataStruct.Structure.Point(100 + 2 * i, 900)
));
}
canvas.Displays(lines);
// 显示多个多边形
List<SharpBoxesCore.DataStruct.Structure.Polygon> polygons = new();
polygons.Add(new SharpBoxesCore.DataStruct.Structure.Polygon(
GenerateHeartPoints(20000, 600, 600, 20),
false
));
canvas.Displays(polygons);
交互式 ROI(可附加)
AttachRect1(string name, Rectangle1D rect1D)
附加一个可编辑的 Rectangle1D(轴对齐矩形)。
canvas.AttactRect1(
"Rectangle",
new SharpBoxesCore.DataStruct.Structure.Rectangle1D(
new SharpBoxesCore.DataStruct.Structure.Point(600, 300),
100,
100
)
);
AttachRect2(string name, Rectangle2D rect2D)
附加一个可编辑的 Rectangle2D(旋转矩形)。
canvas.AttachRect2(
"Rectangle2D",
new SharpBoxesCore.DataStruct.Structure.Rectangle2D(
new SharpBoxesCore.DataStruct.Structure.Point(300, 300),
100,
100,
30
)
);
AttachCircle(string name, Circle circle)
附加一个可编辑的圆形。
var circle = new SharpBoxesCore.DataStruct.Structure.Circle(250, 250, 250);
canvas.AttachCircle("Circle", circle);
AttachEllipse(string name, Ellipse ellipse)
附加一个可编辑的椭圆。
canvas.AttachEllipse(
"Ellipse",
new SharpBoxesCore.DataStruct.Structure.Ellipse(100, 100, 500, 500, 30)
);
AttachLine(string name, Line line)
附加一条可编辑的直线。
var line = new SharpBoxesCore.DataStruct.Structure.Line(300, 400, 600, 700);
canvas.AttachLine("Line", line);
AttachPolygon(string name, Polygon polygon)
附加一个可编辑的多边形(支持双击顶点编辑)。
canvas.AttachPolygon(
"Polygon",
new SharpBoxesCore.DataStruct.Structure.Polygon(
new List<SharpBoxesCore.DataStruct.Structure.Point>
{
new(100, 100),
new(300, 100),
new(200, 200),
},
true
)
);
AttachObject(IDisplayable obj)
附加一个自定义的可显示对象。
var displayImage = new DisplayImage
{
Bitmap = SKBitmap.Decode("image.bmp"),
Origin = SKPoint.Empty,
};
canvas.AttachObject(displayImage);
ROI 移除
DetachObject(string name)
根据名称移除已附加的对象。
canvas.DetachObject("Rectangle");
canvas.DetachObject("Circle");
canvas.DetachObject("Polygon");
canvas.DetachObject("Line");
canvas.DetachObject("Ellipse");
画布操作
ClearWindow()
清除画布上的所有对象。
canvas.ClearWindow();
ClearShapes()
清除所有形状(ROI),但保留显示的图像。
canvas.ClearShapes();
FitToView()
自动缩放并居中图像以适应画布。
canvas.FitToView();
SetPart(Rectangle1D roiRect)
设置视图以显示图像的特定区域(ROI)。
canvas.SetPart(new SharpBoxesCore.DataStruct.Structure.Rectangle1D(100, 100, 1000, 900));
样式配置
SetFillColor(Color color)
设置形状的填充颜色。
canvas.SetFillColor(Colors.Red);
SetStrokeColor(Color color, int lineWidth)
设置描边颜色和线宽。
canvas.SetStrokeColor(Colors.Blue, 6);
SetFillOpacity(int opacity)
设置填充透明度(0-255)。
canvas.SetFillOpacity(128); // 50% 透明度
SetStrokeOpacity(int opacity)
设置描边透明度(0-255)。
canvas.SetStrokeOpacity(128); // 50% 透明度
SetAnchorSize(int anchorSize)
设置交互式 ROI 锚点的大小。
canvas.SetAnchorSize(8);
背景配置
SetCheckerboardBackground(float cellSize, SKColor color1, SKColor color2)
设置棋盘格背景图案。
canvas.SetCheckerboardBackground(20f, new SKColor(60, 60, 60), new SKColor(40, 40, 40));
ClearCheckerboardBackground()
移除棋盘格背景。
canvas.ClearCheckerboardBackground();
文本标注
DisplayMarkRectText(string name, float left, float top, float right, float bottom, string text, float fontSize, Color textColor, Color backgroundColor, Color strokeColor, float strokeWidth, bool isBold)
显示带背景和边框的矩形文本标签。
var bgColor = Colors.Blue;
bgColor.A = 128;
canvas.DisplayMarkRectText(
"Name",
500,
600,
900,
800,
"Hello World",
16,
Colors.Yellow,
bgColor,
Colors.Green,
2,
false
);
导出功能
ExportCanvasFitToSize(int outputWidth, int outputHeight)
将画布内容导出为指定尺寸的 BitmapSource(图像适应尺寸)。
var img = canvas.ExportCanvasFitToSize();
var dialog = new SaveFileDialog();
dialog.Filter = "Png File|*.png|Jpg File|*.jpg|Bmp File|*.bmp";
if (dialog.ShowDialog() == true)
{
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(img));
using var fs = new FileStream(dialog.FileName, FileMode.Create);
encoder.Save(fs);
}
DumpWindow()
异步导出当前窗口视图(包括当前缩放/平移状态)。
var img = await canvas.DumpWindow();
数据获取
GetAllRois()
获取画布上当前所有的 ROI 对象。
var rois = canvas.GetAllRois();
GetAllRoiDatas()
获取所有 ROI 的底层形状数据。
var roiDatas = canvas.GetAllRoiDatas();
视图属性
ShowFixedCrosshair
获取/设置是否在图像中心显示固定十字线。
canvas.ShowFixedCrosshair = true;
ShowMouseCrosshair
获取/设置是否显示鼠标跟随十字线。
canvas.ShowMouseCrosshair = true;
MenuBarVisible
获取/设置是否显示菜单栏。
canvas.MenuBarVisible = false;
StatusBarVisible
获取/设置是否显示状态栏。
canvas.StatusBarVisible = false;
CurrentImagePoint(依赖属性)
获取图像坐标中的当前鼠标位置(可绑定)。
// 在 XAML 中
<local:Canvas x:Name="canvas" CurrentImagePoint="{Binding ImagePoint, Mode=OneWayToSource}"/>
CurrentCanvasPoint(依赖属性)
获取画布坐标中的当前鼠标位置(可绑定)。
WindowHelper
OpenWindow(int width, int height, int x, int y, out Canvas canvas, out Window window)
打开一个带有画布控件的新窗口。
WindowHelper.OpenWindow(500, 500, 200, 600, out var canvas, out var window);
canvas.DisplayImage(bitmap);
OpenWindowFitImage(BitmapSource bitmapSource, int x, int y, out Canvas canvas, out Window window)
打开一个自动适应图像大小的新窗口。
WindowHelper.OpenWindowFitImage(bitmap, 800, 600, out var canvas, out var window);
依赖项
- .NET Framework 4.8+ 或 .NET 6.0+
- SkiaSharp
- SkiaSharp.Views.WPF
- SharpBoxesCore
许可证
MIT 许可证
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0-windows10.0.19041 is compatible. net7.0-windows was computed. net8.0-windows was computed. net8.0-windows10.0.19041 is compatible. net9.0-windows was computed. net10.0-windows was computed. |
| .NET Framework | net48 is compatible. net481 was computed. |
-
.NETFramework 4.8
- SharpBoxesCore (>= 1.1.4.8)
- SkiaSharp (>= 3.119.2)
- SkiaSharp.Views.WPF (>= 3.119.2)
-
net6.0-windows10.0.19041
- SharpBoxesCore (>= 1.1.4.8)
- SkiaSharp (>= 3.119.2)
- SkiaSharp.Views.WPF (>= 3.119.2)
-
net8.0-windows10.0.19041
- SharpBoxesCore (>= 1.1.4.8)
- SkiaSharp (>= 3.119.2)
- SkiaSharp.Views.WPF (>= 3.119.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.