using OpenCvSharp; using PaintDotNet.Base.Enum; using PaintDotNet.Base.SettingModel; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.Serialization.Formatters.Binary; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Xml.Serialization; namespace PaintDotNet.Base.CommTool { /// /// 绘制标尺 /// public class DrawRulerHelper { /// /// 绘制标尺 /// /// 标尺配置类 /// 画布 /// 中心点 /// 标尺长度 /// 标尺显示文字 public static void drawRuler(RulerModel rulerModel, Graphics graphics, PointF center, int lineLength, String text, out RectangleF borderPenRectangle) { Pen linePen = new Pen(Color.FromArgb(rulerModel.lineColor)); Pen borderPen = new Pen(Color.FromArgb(rulerModel.borderColor)); // 标尺线段 PointF lineL = new PointF(center.X - lineLength / 2, center.Y); PointF lineR = new PointF(center.X + lineLength / 2, center.Y); linePen.Width = (int)rulerModel.lineWidth; int lineWidthOffset = (int)rulerModel.lineWidth / 2 - 1; // 垂线 decimal verticalLength = lineLength * rulerModel.verticalLineLength / 100; PointF verticalLT = new PointF(lineL.X, lineL.Y - (int)(verticalLength / 2)); PointF verticalLB = new PointF(lineL.X, lineL.Y + (int)(verticalLength / 2)); PointF verticalRT = new PointF(lineR.X, lineR.Y - (int)(verticalLength / 2)); PointF verticalRB = new PointF(lineR.X, lineR.Y + (int)(verticalLength / 2)); // 文字 Font textFont; decimal textHeight = lineLength * rulerModel.textHeight / 100; if (rulerModel.textBold == 0) textFont = new Font(rulerModel.textFont, (float)rulerModel.textFontSize,FontStyle.Regular); else textFont = new Font(rulerModel.textFont, (float)rulerModel.textFontSize, FontStyle.Bold); float textSizes = textFont.SizeInPoints * text.Length; float textX = lineL.X; if (rulerModel.textPosition == 1) { textX = (lineR.X - lineL.X) / 2 - (int)(textSizes / 2) + lineL.X; } else if (rulerModel.textPosition == 2) { textX = lineR.X - (int)(textSizes); } PointF textLT = new PointF(textX, lineL.Y - lineWidthOffset - (int)(textHeight + new Decimal(textFont.Height))); // 背景参照Y坐标,垂线高,使用垂线Y值,文字高使用文字Y值。 float backRectangleReferY = textLT.Y < verticalLT.Y - 2 ? textLT.Y : verticalLT.Y -2; // 背景大小 decimal backLength = lineLength * rulerModel.backgroundSize / 100; float backRectangleX = verticalLT.X - (int)backLength - (int)linePen.Width; float backRectangleY = backRectangleReferY - (int)(backLength); float backRectangleW = (verticalRT.X - verticalLT.X) + (int)(backLength * 2) + (int)(linePen.Width * 2); float backRectangleH = (verticalLB.Y - backRectangleReferY) + (int)(backLength * 2) + lineWidthOffset + 2; RectangleF backRectangle = new RectangleF(backRectangleX, backRectangleY, backRectangleW, backRectangleH); // 边框 borderPen.Width = (int)rulerModel.borderWidth; int offset = borderPen.Width>0?(int)(borderPen.Width / 2) - 2:0; borderPenRectangle = new RectangleF(backRectangle.X - offset, backRectangle.Y - offset, backRectangle.Width + offset * 2, backRectangle.Height + offset * 2); // 计算中心Y轴偏移量 // 绘制 graphics.FillRectangle(new SolidBrush(Color.FromArgb(rulerModel.backColor)), backRectangle); graphics.DrawRectangle(borderPen, borderPenRectangle.X, borderPenRectangle.Y, borderPenRectangle.Width, borderPenRectangle.Height); graphics.DrawLine(linePen, lineL, lineR); graphics.DrawLine(linePen, verticalLT, verticalLB); graphics.DrawLine(linePen, verticalRT, verticalRB); graphics.DrawString(text, textFont, new SolidBrush(Color.FromArgb(rulerModel.textColor)), textLT.X, textLT.Y); } /// /// 绘制网格 /// /// /// public static void drawGrid(GridModel gridModel, Graphics graphics, int width, int height) { int length = gridModel.grid.SideLength; //网格宽度 int sideHeight = gridModel.grid.SideHeight; //网格高度 int hnum = gridModel.grid.HorizontalNum; //水平网格数 int vnum = gridModel.grid.VerticalNum; //垂直网格数 int dashStyle = gridModel.grid.DashStyle; //线形 int thickness = gridModel.grid.Thickness; //粗细 int color = gridModel.grid.Color; //颜色 int hlines = vnum + 1; //水平线条数 int vlines = hnum + 1; //垂直线条数 Pen pen = new Pen(new SolidBrush(Color.FromArgb(color)), thickness); pen.DashStyle = (DashStyle)dashStyle; int y = (height - vnum * sideHeight) / 2; int x = (width - hnum * length) / 2; for (int i=0; i< hlines; i++) { graphics.DrawLine(pen, x, y + i * sideHeight, x + length * hnum, y + i * sideHeight); } for (int i = 0; i < vlines; i++) { graphics.DrawLine(pen, x + i * length, y, x + i * length, y + sideHeight * vnum); } } /// /// 绘制网格 /// /// /// public static void drawGridFull(GridModel gridModel, Graphics graphics, int width, int height) { int hnum = gridModel.grid.HorizontalNum; //水平网格数 int vnum = gridModel.grid.VerticalNum; //垂直网格数 int dashStyle = gridModel.grid.DashStyle; //线形 int thickness = gridModel.grid.Thickness; //粗细 int color = gridModel.grid.Color; //颜色 int hlines = vnum + 1; //水平线条数 int vlines = hnum + 1; //垂直线条数 Pen pen = new Pen(new SolidBrush(Color.FromArgb(color)), thickness); pen.DashStyle = (DashStyle)dashStyle; float y = ((height * 1.0f ) / vnum); float x = ((width * 1.0f) / hnum); for (int i = 0; i < hlines; i++) { graphics.DrawLine(pen, 0, y * i , width, y * i); } for (int i = 0; i < vlines; i++) { graphics.DrawLine(pen, x * i, 0, x * i, height); } } /// /// 绘制方形网格,未按标尺进行处理 /// /// /// /// /// public static void drawGridRectangle(GridModel gridModel, Graphics graphics, int width, int height, double micronRatio) { int length = gridModel.rectangle.sideLength; //边长 int dashStyle = gridModel.rectangle.DashStyle; //线形 int thickness = gridModel.rectangle.Thickness; //粗细 int color = gridModel.rectangle.Color; //颜色 Pen pen = new Pen(new SolidBrush(Color.FromArgb(color)), thickness); pen.DashStyle = (DashStyle)dashStyle; //float side = (float)(length / micronRatio); float x = (width - length) / 2; float y = (height - length) / 2; graphics.DrawRectangle(pen, x, y, length, length); } /// /// 绘制圆形网格,未按标尺进行处理 /// /// /// /// /// public static void drawGridRound(GridModel gridModel, Graphics graphics, int width, int height, double micronRatio) { int diameter = gridModel.round.diameter;//直径 int dashStyle = gridModel.round.DashStyle; //线形 int thickness = gridModel.round.Thickness; //粗细 int color = gridModel.round.Color; //颜色 Pen pen = new Pen(new SolidBrush(Color.FromArgb(color)), thickness); pen.DashStyle = (DashStyle)dashStyle; //float diameter = (float)(70 / micronRatio);//直径固定70微米 float x = (width - diameter) / 2; float y = (height - diameter) / 2; graphics.DrawEllipse(pen, new RectangleF(x, y , diameter, diameter)); } /// /// 绘制十字线,未按标尺进行处理 /// /// /// /// /// public static void drawGridCrossCurve(GridModel gridModel, Graphics graphics, int width, int height) { if (gridModel == null) { //样式暂时写死,没有对应样式设置 int dashStyle = 0; //线形 int thickness = 5; //粗细 int color = -59111; //颜色 Pen pen = new Pen(new SolidBrush(Color.FromArgb(color)), thickness); pen.DashStyle = (DashStyle)dashStyle; float lineLength = width < height ? width * 0.3f : height * 0.3f;//线长 float x = (width - lineLength) / 2; float y = (height - lineLength) / 2; graphics.DrawLine(pen, x, height / 2, x + lineLength, height / 2); graphics.DrawLine(pen, width / 2, y, width / 2, y + lineLength); } } /// /// bitmap转base64 /// /// /// public static string ImgToBase64String(Bitmap source) { OpenCvSharp.Mat mat = OpenCvSharp.Extensions.BitmapConverter.ToMat(source); Bitmap bitmap = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat); string base64 = ""; using (MemoryStream ms = new MemoryStream()) { bitmap.Save(ms, ImageFormat.Jpeg); base64 = Convert.ToBase64String(ms.ToArray()); ms.Close(); bitmap.Dispose(); } return base64; } /// /// base64转bitmap /// /// /// public static Bitmap Base64StringToImage(string strbase64) { try { byte[] arr = Convert.FromBase64String(strbase64); MemoryStream ms = new MemoryStream(arr); Bitmap bmp = new Bitmap(ms); ms.Close(); return bmp; } catch (Exception) { return null; } } /// /// 缩放图像 /// /// /// /// /// /// public static Image ResizeImage(Image originalImage, int width, int height, ThumbnailMode mode) { int towidth = width; int toheight = height; int x = 0; int y = 0; int initWidth = originalImage.Width; int initHeight = originalImage.Height; switch (mode) { case ThumbnailMode.UsrHeightWidth: //指定高宽缩放(可能变形) break; case ThumbnailMode.UsrHeightWidthBound: //指定高宽缩放(可能变形)(过小则不变) if (originalImage.Width <= width && originalImage.Height <= height) { return originalImage; } if (originalImage.Width < width) { towidth = originalImage.Width; } if (originalImage.Height < height) { toheight = originalImage.Height; } break; case ThumbnailMode.UsrWidth: //指定宽,高按比例 toheight = originalImage.Height * width / originalImage.Width; break; case ThumbnailMode.UsrWidthBound: //指定宽(过小则不变),高按比例 if (originalImage.Width <= width) { return originalImage; } else { toheight = originalImage.Height * width / originalImage.Width; } break; case ThumbnailMode.UsrHeight: //指定高,宽按比例 towidth = originalImage.Width * height / originalImage.Height; break; case ThumbnailMode.UsrHeightBound: //指定高(过小则不变),宽按比例 if (originalImage.Height <= height) { return originalImage; } else { towidth = originalImage.Width * height / originalImage.Height; } break; case ThumbnailMode.Cut: //指定高宽裁减(不变形) //计算宽高比 double srcScale = (double)originalImage.Width / (double)originalImage.Height; double destScale = (double)towidth / (double)toheight; //宽高比相同 if (srcScale - destScale >= 0 && srcScale - destScale <= 0.001) { x = 0; y = 0; initWidth = originalImage.Width; initHeight = originalImage.Height; } //源宽高比大于目标宽高比 //(源的宽比目标的宽大) else if (srcScale > destScale) { initWidth = originalImage.Height * towidth / toheight; initHeight = originalImage.Height; x = (originalImage.Width - initWidth) / 2; y = 0; } //源宽高比小于目标宽高小,源的高度大于目标的高度 else { initWidth = originalImage.Width; initHeight = originalImage.Width * height / towidth; x = 0; y = (originalImage.Height - initHeight) / 2; } break; default: break; } Image bitmap = new Bitmap(towidth, toheight); //新建一个画板 using (Graphics g = Graphics.FromImage(bitmap)) { //设置高质量插值法 g.CompositingQuality = CompositingQuality.HighQuality; //设置高质量,低速段呈现的平滑程度 g.SmoothingMode = SmoothingMode.HighQuality; //在指定的位置上,并按指定大小绘制原图片的指定部分 g.DrawImage(originalImage, new Rectangle(0, 0, towidth, toheight), new Rectangle(x, y, initWidth, initHeight), GraphicsUnit.Pixel); } return bitmap; } /// /// 深拷贝,反射 /// /// /// public static T DeepCopyByReflect(T obj) { //如果是字符串或值类型则直接返回 if (obj==null || obj is string || obj.GetType().IsValueType) return obj; object retval = Activator.CreateInstance(obj.GetType()); FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); foreach (FieldInfo field in fields) { try { field.SetValue(retval, DeepCopyByReflect(field.GetValue(obj))); } catch { } } return (T)retval; } public static List DeepCopyListByReflect(List objs) { List list = new List(); if (objs!=null && objs.Count>0) { foreach(T t in objs) { list.Add(DeepCopyByReflect(t)); } } return list; } /// /// 深拷贝,xml序列化与反序列化 /// /// /// /// public static T DeserializeXML(string xmlData) where T : new() { if (string.IsNullOrEmpty(xmlData)) return default(T); TextReader tr = new StringReader(xmlData); T DocItms = new T(); XmlSerializer xms = new XmlSerializer(DocItms.GetType()); DocItms = (T)xms.Deserialize(tr); return DocItms == null ? default(T) : DocItms; } /// /// 图片裁剪 /// 原图 /// /// 裁剪起始点横坐标 /// 裁剪起始点纵坐标 /// 裁剪宽度 /// 裁剪高度 /// public static Bitmap KiCut(Bitmap b, int StartX, int StartY, int iWidth, int iHeight) { if (b == null) { return null; } //不对超过原图尺寸的区域做处理,以黑色背景显示 //int w = b.Width; //int h = b.Height; //if (StartX >= w || StartY >= h) //{ // return null; //} //if (StartX + iWidth > w) //{ // iWidth = w - StartX; //} //if (StartY + iHeight > h) //{ // iHeight = h - StartY; //} try { Bitmap bmpOut = new Bitmap(iWidth, iHeight); Graphics g = Graphics.FromImage(bmpOut); g.Clear(Color.Black); g.DrawImage(b, new Rectangle(0, 0, iWidth, iHeight), new Rectangle(StartX, StartY, iWidth, iHeight), GraphicsUnit.Pixel); g.Dispose(); return bmpOut; } catch { return null; } } } }