using System; using System.Collections.Generic; using System.Threading.Tasks; using System.Windows; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; namespace Ink_Canvas.Helpers { /// /// 硬件加速的墨迹处理器,利用WPF的GPU渲染能力 /// public class HardwareAcceleratedInkProcessor { private readonly RenderTargetBitmap _renderTarget; private readonly DrawingVisual _drawingVisual; private bool _isInitialized; public HardwareAcceleratedInkProcessor(int width = 1920, int height = 1080) { // 创建硬件加速的渲染目标 _renderTarget = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32); _drawingVisual = new DrawingVisual(); // 启用硬件加速 RenderOptions.SetBitmapScalingMode(_drawingVisual, BitmapScalingMode.HighQuality); RenderOptions.SetEdgeMode(_drawingVisual, EdgeMode.Aliased); _isInitialized = true; } /// /// 使用GPU加速的贝塞尔曲线平滑 /// public async Task SmoothStrokeWithGPU(Stroke originalStroke) { if (!_isInitialized || originalStroke == null || originalStroke.StylusPoints.Count < 2) return originalStroke; return await Task.Run(() => { try { // 使用PathGeometry进行硬件加速的曲线拟合 var pathGeometry = CreateSmoothPathGeometry(originalStroke.StylusPoints); // 将PathGeometry转换回StylusPoint集合 var smoothedPoints = ConvertPathGeometryToStylusPoints(pathGeometry, originalStroke.StylusPoints); return new Stroke(new StylusPointCollection(smoothedPoints)) { DrawingAttributes = originalStroke.DrawingAttributes.Clone() }; } catch { return originalStroke; } }); } /// /// 创建平滑的路径几何体 /// private PathGeometry CreateSmoothPathGeometry(StylusPointCollection points) { var pathGeometry = new PathGeometry(); var pathFigure = new PathFigure(); if (points.Count < 2) return pathGeometry; pathFigure.StartPoint = new Point(points[0].X, points[0].Y); // 使用贝塞尔曲线段创建平滑路径,增加插点密度 for (int i = 0; i < points.Count - 1; i += 2) // 从i+=3改为i+=2,增加插点密度 { var p1 = i + 1 < points.Count ? new Point(points[i + 1].X, points[i + 1].Y) : pathFigure.StartPoint; var p2 = i + 2 < points.Count ? new Point(points[i + 2].X, points[i + 2].Y) : p1; var p3 = i + 3 < points.Count ? new Point(points[i + 3].X, points[i + 3].Y) : p2; var bezierSegment = new BezierSegment(p1, p2, p3, true); pathFigure.Segments.Add(bezierSegment); } pathGeometry.Figures.Add(pathFigure); return pathGeometry; } /// /// 将PathGeometry转换为StylusPoint集合 /// private List ConvertPathGeometryToStylusPoints(PathGeometry pathGeometry, StylusPointCollection originalPoints) { var result = new List(); var flattened = pathGeometry.GetFlattenedPathGeometry(); foreach (var figure in flattened.Figures) { result.Add(new StylusPoint(figure.StartPoint.X, figure.StartPoint.Y, 0.5f)); foreach (var segment in figure.Segments) { if (segment is LineSegment lineSegment) { result.Add(new StylusPoint(lineSegment.Point.X, lineSegment.Point.Y, 0.5f)); } else if (segment is PolyLineSegment polyLineSegment) { foreach (var point in polyLineSegment.Points) { result.Add(new StylusPoint(point.X, point.Y, 0.5f)); } } } } // 保持原始压感信息 InterpolatePressure(result, originalPoints); return result; } /// /// 插值压感信息 /// private void InterpolatePressure(List smoothedPoints, StylusPointCollection originalPoints) { if (originalPoints.Count == 0 || smoothedPoints.Count == 0) return; for (int i = 0; i < smoothedPoints.Count; i++) { double ratio = (double)i / (smoothedPoints.Count - 1); int originalIndex = (int)(ratio * (originalPoints.Count - 1)); originalIndex = Math.Max(0, Math.Min(originalIndex, originalPoints.Count - 1)); var point = smoothedPoints[i]; float pressure = originalPoints[originalIndex].PressureFactor; smoothedPoints[i] = new StylusPoint(point.X, point.Y, Math.Max(pressure, 0.1f)); } } /// /// 使用GPU加速的并行贝塞尔计算 /// public static StylusPoint[] ParallelBezierInterpolation(StylusPoint[] controlPoints, int segments = 32) { if (controlPoints.Length < 4) return controlPoints; var result = new StylusPoint[segments * (controlPoints.Length / 4)]; Parallel.For(0, controlPoints.Length / 4, segmentIndex => { var p0 = controlPoints[segmentIndex * 4]; var p1 = controlPoints[segmentIndex * 4 + 1]; var p2 = controlPoints[segmentIndex * 4 + 2]; var p3 = controlPoints[segmentIndex * 4 + 3]; for (int i = 0; i < segments; i++) { double t = (double)i / (segments - 1); result[segmentIndex * segments + i] = CubicBezierFast(p0, p1, p2, p3, t); } }); return result; } /// /// 优化的三次贝塞尔曲线计算 /// private static StylusPoint CubicBezierFast(StylusPoint p0, StylusPoint p1, StylusPoint p2, StylusPoint p3, double t) { double u = 1 - t; double tt = t * t; double uu = u * u; double uuu = uu * u; double ttt = tt * t; double x = uuu * p0.X + 3 * uu * t * p1.X + 3 * u * tt * p2.X + ttt * p3.X; double y = uuu * p0.Y + 3 * uu * t * p1.Y + 3 * u * tt * p2.Y + ttt * p3.Y; float pressure = (float)(p1.PressureFactor * u + p2.PressureFactor * t); return new StylusPoint(x, y, Math.Max(pressure, 0.1f)); } /// /// 释放GPU相关资源标记 /// public void Dispose() { _isInitialized = false; } } }