212 lines
8.3 KiB
C#
Raw Normal View History

2024-08-21 16:50:14 +08:00
using Abp.Dependency;
using SkiaSharp;
using System.Text;
using Yunda.ISAS.DataMonitoringServer.DataAnalysis.Model;
namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis.LinkageAnalysis
{
/// <summary>
/// 谷歌skia图像处理图调用API
/// </summary>
public class SkiaSharpHandlePicture : ISingletonDependency
{
private float _radius = 8; //画圈半径
private int _fontSize = 24; //文字大小
private int _maxPixQuality = 1920 * 1080; //最大像素质量
private SKEncodedImageFormat _sKEncodedImageFormat = SKEncodedImageFormat.Jpeg; //存储文件格式
private string _tmpPath = "./CaptureJPEGPicture/resultPicture.jpg"; //临时文件目录
public SkiaSharpHandlePicture()
{
}
/// <summary>
/// 谷歌skia图像处理图调用API
/// </summary>
/// <param name="radius">画圈半径</param>
/// <param name="fontSize">文字大小</param>
/// <param name="tmpPath">临时文件目录</param>
/// <param name="sKEncodedImageFormat">存储文件格式</param>
/// <param name="maxPixQuality">最大像素质量</param>
public SkiaSharpHandlePicture(float radius, int fontSize, string tmpPath, SKEncodedImageFormat sKEncodedImageFormat, int maxPixQuality)
{
_radius = radius;
_tmpPath = tmpPath;
_fontSize = fontSize;
_sKEncodedImageFormat = sKEncodedImageFormat;
_maxPixQuality = maxPixQuality;
}
/// <summary>
/// 根据给的关键点获取文字显示的位置
/// </summary>
/// <param name="measureTempCoordinate"></param>
/// <param name="textWidth"></param>
/// <param name="textHeight"></param>
/// <param name="bmpWidth"></param>
/// <param name="bmpHeight"></param>
/// <returns></returns>
private (float, float) GetTextCoordinate(MeasureTempCoordinate measureTempCoordinate, float textWidth, float textHeight, int bmpWidth, int bmpHeight)
{
//var measureTempCoordinate = points[0];
var isCloseUpSide = measureTempCoordinate.Y - textHeight <= 0;//当选择点靠近上边时
var isCloseDownSide = measureTempCoordinate.Y + textHeight >= bmpHeight;//当选择点靠近下边时
var isCloseLeftSide = measureTempCoordinate.X - textWidth / 2 <= 0;// 当选择点靠近左边时
var isCloseRightSide = measureTempCoordinate.X + textWidth / 2 >= bmpWidth;// 当选择点靠近右边时
var textX = measureTempCoordinate.X - textWidth / 2;//文字起点的X坐标
var textY = measureTempCoordinate.Y + textHeight;//文字起点的Y坐标
if (isCloseUpSide)
{
//不处理
}
if (isCloseDownSide)
{
textY = measureTempCoordinate.Y - textHeight;
}
if (isCloseLeftSide)
{
textX = 0;
}
if (isCloseRightSide)
{
textX = bmpWidth - textWidth;
}
return (textX, textY);
}
/// <summary>
/// 绘图API
/// </summary>
/// <param name="points">绘图点集合(百分比)</param>
/// <param name="filePath">背景图路径</param>
/// <param name="content">文字内容</param>
/// <returns>生成文件路径</returns>
public void Bitmap(List<MeasureTempCoordinate> points, ref string filePath, string content)
{
if (points == null || points.Count == 0)
{
return;
}
if (!File.Exists(filePath))
{
return;
}
//载入底图
var bmp = SKBitmap.Decode(filePath);
//图像宽度
var bmpWidth = bmp.Width;
//图像高度
var bmpHeight = bmp.Height;
foreach (var item in points)//处理points坐标换算
{
item.X = item.X * bmpWidth;
item.Y = item.Y * bmpHeight;
}
//初始化画布
var canvas = new SKCanvas(bmp);
//保存当前画布状态,即正常全图绘制状态
canvas.Save();
var paint = new SKPaint
{
//抗锯齿
IsAntialias = true,
IsStroke = true,
StrokeWidth = 0.8f,
//StrokeCap = SKStrokeCap.Butt,
//颜色
Color = new SKColor(255, 255, 255, 255)
};
if (points.Count == 1) //当传入的参数是一个点
{
var point = new SKPoint(points[0].X, points[0].Y);
canvas.DrawCircle(point, _radius, paint);
canvas.Save();
//写文字
float beta = 4 / 3;//文字和像素之间的换算系数
//文字长度
var textWidth = content.Length * _fontSize * beta;
//文字高度
var textHeight = _fontSize * beta;
byte[] gb = Encoding.UTF8.GetBytes(content);
var fontPath = Path.GetFullPath("Fonts/PingFang Regular.otf"); // 为了解决不能写汉字,需要字体文件
var font = new SKFont { Typeface = SKTypeface.FromFile(fontPath), Size = _fontSize };
SKTextBlob sKTextBlob = SKTextBlob.Create(gb, SKTextEncoding.Utf8, font);
var coordinate = GetTextCoordinate(points[0], textWidth, textHeight, bmpWidth, bmpHeight);
canvas.DrawText(sKTextBlob, coordinate.Item1, coordinate.Item2, paint);
canvas.Save();
}
else
{
var skpath = new SKPath();
float maxPos = 0;
MeasureTempCoordinate measureTempCoordinate = new MeasureTempCoordinate();
for (int i = 0; i < points.Count; i++)
{
var X = points[i].X;
var Y = points[i].Y;
if (i == 0)
{
skpath.MoveTo(X, Y); //开始点
}
else
{
skpath.LineTo(X, Y);
}
if (X * Y > maxPos) //找到坐标乘积最大的点
{
maxPos = X * Y;
measureTempCoordinate.X = X;
measureTempCoordinate.Y = Y;
}
}
skpath.Close();
canvas.DrawPath(skpath, paint);
canvas.Save();
//写文字
byte[] gb = Encoding.UTF8.GetBytes(content);
float beta = 4 / 3;//文字和像素之间的换算系数
var fontPath = Path.GetFullPath("Fonts/PingFang Regular.otf"); // 为了解决不能写汉字,需要字体文件
var font = new SKFont { Typeface = SKTypeface.FromFile(fontPath), Size = _fontSize };
SKTextBlob sKTextBlob = SKTextBlob.Create(gb, SKTextEncoding.Utf8, font);
//文字长度
var textWidth = content.Length * _fontSize * beta;
//文字高度
var textHeight = _fontSize * beta;
var coordinate = GetTextCoordinate(measureTempCoordinate, textWidth, textHeight, bmpWidth, bmpHeight);
canvas.DrawText(sKTextBlob, coordinate.Item1, coordinate.Item2, paint);
canvas.Save();
}
//保存为图片
var path = Path.GetFullPath(_tmpPath);
if (!Directory.Exists("./CaptureJPEGPicture"))
{
Directory.CreateDirectory("./CaptureJPEGPicture");
}
var file = File.OpenWrite(path);
bmp.Encode(file, _sKEncodedImageFormat, _maxPixQuality);
paint.Dispose(); //释放画笔
file.Dispose(); //释放文件
bmp.Dispose(); //释放图像
canvas.Dispose(); //释放画板
File.Delete(filePath);
FileInfo fi = new FileInfo(path);
fi.MoveTo(filePath);
}
}
}