DrawRulerHelper.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. using OpenCvSharp;
  2. using PaintDotNet.Base.Enum;
  3. using PaintDotNet.Base.SettingModel;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Drawing;
  7. using System.Drawing.Drawing2D;
  8. using System.Drawing.Imaging;
  9. using System.IO;
  10. using System.Linq;
  11. using System.Reflection;
  12. using System.Runtime.Serialization.Formatters.Binary;
  13. using System.Text;
  14. using System.Threading.Tasks;
  15. using System.Windows.Forms;
  16. using System.Xml.Serialization;
  17. namespace PaintDotNet.Base.CommTool
  18. {
  19. /// <summary>
  20. /// 绘制标尺
  21. /// </summary>
  22. public class DrawRulerHelper
  23. {
  24. /// <summary>
  25. /// 绘制标尺
  26. /// </summary>
  27. /// <param name="rulerModel">标尺配置类</param>
  28. /// <param name="graphics">画布</param>
  29. /// <param name="center">中心点</param>
  30. /// <param name="lineLength">标尺长度</param>
  31. /// <param name="text">标尺显示文字</param>
  32. public static void drawRuler(RulerModel rulerModel, Graphics graphics, PointF center, int lineLength, String text, out RectangleF borderPenRectangle)
  33. {
  34. Pen linePen = new Pen(Color.FromArgb(rulerModel.lineColor));
  35. Pen borderPen = new Pen(Color.FromArgb(rulerModel.borderColor));
  36. // 标尺线段
  37. PointF lineL = new PointF(center.X - lineLength / 2, center.Y);
  38. PointF lineR = new PointF(center.X + lineLength / 2, center.Y);
  39. linePen.Width = (int)rulerModel.lineWidth;
  40. int lineWidthOffset = (int)rulerModel.lineWidth / 2 - 1;
  41. // 垂线
  42. decimal verticalLength = lineLength * rulerModel.verticalLineLength / 100;
  43. PointF verticalLT = new PointF(lineL.X, lineL.Y - (int)(verticalLength / 2));
  44. PointF verticalLB = new PointF(lineL.X, lineL.Y + (int)(verticalLength / 2));
  45. PointF verticalRT = new PointF(lineR.X, lineR.Y - (int)(verticalLength / 2));
  46. PointF verticalRB = new PointF(lineR.X, lineR.Y + (int)(verticalLength / 2));
  47. // 文字
  48. Font textFont;
  49. decimal textHeight = lineLength * rulerModel.textHeight / 100;
  50. if (rulerModel.textBold == 0)
  51. textFont = new Font(rulerModel.textFont, (float)rulerModel.textFontSize,FontStyle.Regular);
  52. else
  53. textFont = new Font(rulerModel.textFont, (float)rulerModel.textFontSize, FontStyle.Bold);
  54. float textSizes = textFont.SizeInPoints * text.Length;
  55. float textX = lineL.X;
  56. if (rulerModel.textPosition == 1)
  57. {
  58. textX = (lineR.X - lineL.X) / 2 - (int)(textSizes / 2) + lineL.X;
  59. }
  60. else if (rulerModel.textPosition == 2)
  61. {
  62. textX = lineR.X - (int)(textSizes);
  63. }
  64. PointF textLT = new PointF(textX, lineL.Y - lineWidthOffset - (int)(textHeight + new Decimal(textFont.Height)));
  65. // 背景参照Y坐标,垂线高,使用垂线Y值,文字高使用文字Y值。
  66. float backRectangleReferY = textLT.Y < verticalLT.Y - 2 ? textLT.Y : verticalLT.Y -2;
  67. // 背景大小
  68. decimal backLength = lineLength * rulerModel.backgroundSize / 100;
  69. float backRectangleX = verticalLT.X - (int)backLength - (int)linePen.Width;
  70. float backRectangleY = backRectangleReferY - (int)(backLength);
  71. float backRectangleW = (verticalRT.X - verticalLT.X) + (int)(backLength * 2) + (int)(linePen.Width * 2);
  72. float backRectangleH = (verticalLB.Y - backRectangleReferY) + (int)(backLength * 2) + lineWidthOffset + 2;
  73. RectangleF backRectangle = new RectangleF(backRectangleX, backRectangleY, backRectangleW, backRectangleH);
  74. // 边框
  75. borderPen.Width = (int)rulerModel.borderWidth;
  76. int offset = borderPen.Width>0?(int)(borderPen.Width / 2) - 2:0;
  77. borderPenRectangle = new RectangleF(backRectangle.X - offset, backRectangle.Y - offset, backRectangle.Width + offset * 2, backRectangle.Height + offset * 2);
  78. // 计算中心Y轴偏移量
  79. // 绘制
  80. graphics.FillRectangle(new SolidBrush(Color.FromArgb(rulerModel.backColor)), backRectangle);
  81. graphics.DrawRectangle(borderPen, borderPenRectangle.X, borderPenRectangle.Y, borderPenRectangle.Width, borderPenRectangle.Height);
  82. graphics.DrawLine(linePen, lineL, lineR);
  83. graphics.DrawLine(linePen, verticalLT, verticalLB);
  84. graphics.DrawLine(linePen, verticalRT, verticalRB);
  85. graphics.DrawString(text, textFont, new SolidBrush(Color.FromArgb(rulerModel.textColor)), textLT.X, textLT.Y);
  86. }
  87. /// <summary>
  88. /// 绘制网格
  89. /// </summary>
  90. /// <param name="rulerModel"></param>
  91. /// <param name="graphics"></param>
  92. public static void drawGrid(GridModel gridModel, Graphics graphics, int width, int height)
  93. {
  94. int length = gridModel.grid.SideLength; //网格宽度
  95. int sideHeight = gridModel.grid.SideHeight; //网格高度
  96. int hnum = gridModel.grid.HorizontalNum; //水平网格数
  97. int vnum = gridModel.grid.VerticalNum; //垂直网格数
  98. int dashStyle = gridModel.grid.DashStyle; //线形
  99. int thickness = gridModel.grid.Thickness; //粗细
  100. int color = gridModel.grid.Color; //颜色
  101. int hlines = vnum + 1; //水平线条数
  102. int vlines = hnum + 1; //垂直线条数
  103. Pen pen = new Pen(new SolidBrush(Color.FromArgb(color)), thickness);
  104. pen.DashStyle = (DashStyle)dashStyle;
  105. int y = (height - vnum * sideHeight) / 2;
  106. int x = (width - hnum * length) / 2;
  107. for (int i=0; i< hlines; i++)
  108. {
  109. graphics.DrawLine(pen, x, y + i * sideHeight, x + length * hnum, y + i * sideHeight);
  110. }
  111. for (int i = 0; i < vlines; i++)
  112. {
  113. graphics.DrawLine(pen, x + i * length, y, x + i * length, y + sideHeight * vnum);
  114. }
  115. }
  116. /// <summary>
  117. /// 绘制网格
  118. /// </summary>
  119. /// <param name="rulerModel"></param>
  120. /// <param name="graphics"></param>
  121. public static void drawGridFull(GridModel gridModel, Graphics graphics, int width, int height)
  122. {
  123. int hnum = gridModel.grid.HorizontalNum; //水平网格数
  124. int vnum = gridModel.grid.VerticalNum; //垂直网格数
  125. int dashStyle = gridModel.grid.DashStyle; //线形
  126. int thickness = gridModel.grid.Thickness; //粗细
  127. int color = gridModel.grid.Color; //颜色
  128. int hlines = vnum + 1; //水平线条数
  129. int vlines = hnum + 1; //垂直线条数
  130. Pen pen = new Pen(new SolidBrush(Color.FromArgb(color)), thickness);
  131. pen.DashStyle = (DashStyle)dashStyle;
  132. float y = ((height * 1.0f ) / vnum);
  133. float x = ((width * 1.0f) / hnum);
  134. for (int i = 0; i < hlines; i++)
  135. {
  136. graphics.DrawLine(pen, 0, y * i , width, y * i);
  137. }
  138. for (int i = 0; i < vlines; i++)
  139. {
  140. graphics.DrawLine(pen, x * i, 0, x * i, height);
  141. }
  142. }
  143. /// <summary>
  144. /// 绘制方形网格,未按标尺进行处理
  145. /// </summary>
  146. /// <param name="gridModel"></param>
  147. /// <param name="graphics"></param>
  148. /// <param name="width"></param>
  149. /// <param name="height"></param>
  150. public static void drawGridRectangle(GridModel gridModel, Graphics graphics, int width, int height, double micronRatio)
  151. {
  152. int length = gridModel.rectangle.sideLength; //边长
  153. int dashStyle = gridModel.rectangle.DashStyle; //线形
  154. int thickness = gridModel.rectangle.Thickness; //粗细
  155. int color = gridModel.rectangle.Color; //颜色
  156. Pen pen = new Pen(new SolidBrush(Color.FromArgb(color)), thickness);
  157. pen.DashStyle = (DashStyle)dashStyle;
  158. //float side = (float)(length / micronRatio);
  159. float x = (width - length) / 2;
  160. float y = (height - length) / 2;
  161. graphics.DrawRectangle(pen, x, y, length, length);
  162. }
  163. /// <summary>
  164. /// 绘制圆形网格,未按标尺进行处理
  165. /// </summary>
  166. /// <param name="gridModel"></param>
  167. /// <param name="graphics"></param>
  168. /// <param name="width"></param>
  169. /// <param name="height"></param>
  170. public static void drawGridRound(GridModel gridModel, Graphics graphics, int width, int height, double micronRatio)
  171. {
  172. int diameter = gridModel.round.diameter;//直径
  173. int dashStyle = gridModel.round.DashStyle; //线形
  174. int thickness = gridModel.round.Thickness; //粗细
  175. int color = gridModel.round.Color; //颜色
  176. Pen pen = new Pen(new SolidBrush(Color.FromArgb(color)), thickness);
  177. pen.DashStyle = (DashStyle)dashStyle;
  178. //float diameter = (float)(70 / micronRatio);//直径固定70微米
  179. float x = (width - diameter) / 2;
  180. float y = (height - diameter) / 2;
  181. graphics.DrawEllipse(pen, new RectangleF(x, y , diameter, diameter));
  182. }
  183. /// <summary>
  184. /// 绘制十字线,未按标尺进行处理
  185. /// </summary>
  186. /// <param name="gridModel"></param>
  187. /// <param name="graphics"></param>
  188. /// <param name="width"></param>
  189. /// <param name="height"></param>
  190. public static void drawGridCrossCurve(GridModel gridModel, Graphics graphics, int width, int height)
  191. {
  192. if (gridModel == null)
  193. {
  194. //样式暂时写死,没有对应样式设置
  195. int dashStyle = 0; //线形
  196. int thickness = 5; //粗细
  197. int color = -59111; //颜色
  198. Pen pen = new Pen(new SolidBrush(Color.FromArgb(color)), thickness);
  199. pen.DashStyle = (DashStyle)dashStyle;
  200. float lineLength = width < height ? width * 0.3f : height * 0.3f;//线长
  201. float x = (width - lineLength) / 2;
  202. float y = (height - lineLength) / 2;
  203. graphics.DrawLine(pen, x, height / 2, x + lineLength, height / 2);
  204. graphics.DrawLine(pen, width / 2, y, width / 2, y + lineLength);
  205. }
  206. }
  207. /// <summary>
  208. /// bitmap转base64
  209. /// </summary>
  210. /// <param name="bmp"></param>
  211. /// <returns></returns>
  212. public static string ImgToBase64String(Bitmap source)
  213. {
  214. OpenCvSharp.Mat mat = OpenCvSharp.Extensions.BitmapConverter.ToMat(source);
  215. Bitmap bitmap = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat);
  216. string base64 = "";
  217. using (MemoryStream ms = new MemoryStream())
  218. {
  219. bitmap.Save(ms, ImageFormat.Jpeg);
  220. base64 = Convert.ToBase64String(ms.ToArray());
  221. ms.Close();
  222. bitmap.Dispose();
  223. }
  224. return base64;
  225. }
  226. /// <summary>
  227. /// base64转bitmap
  228. /// </summary>
  229. /// <param name="strbase64"></param>
  230. /// <returns></returns>
  231. public static Bitmap Base64StringToImage(string strbase64)
  232. {
  233. try
  234. {
  235. byte[] arr = Convert.FromBase64String(strbase64);
  236. MemoryStream ms = new MemoryStream(arr);
  237. Bitmap bmp = new Bitmap(ms);
  238. ms.Close();
  239. return bmp;
  240. }
  241. catch (Exception)
  242. {
  243. return null;
  244. }
  245. }
  246. /// <summary>
  247. /// 缩放图像
  248. /// </summary>
  249. /// <param name="originalImage"></param>
  250. /// <param name="width"></param>
  251. /// <param name="height"></param>
  252. /// <param name="mode"></param>
  253. /// <returns></returns>
  254. public static Image ResizeImage(Image originalImage, int width, int height, ThumbnailMode mode)
  255. {
  256. int towidth = width;
  257. int toheight = height;
  258. int x = 0;
  259. int y = 0;
  260. int initWidth = originalImage.Width;
  261. int initHeight = originalImage.Height;
  262. switch (mode)
  263. {
  264. case ThumbnailMode.UsrHeightWidth: //指定高宽缩放(可能变形)
  265. break;
  266. case ThumbnailMode.UsrHeightWidthBound: //指定高宽缩放(可能变形)(过小则不变)
  267. if (originalImage.Width <= width && originalImage.Height <= height)
  268. {
  269. return originalImage;
  270. }
  271. if (originalImage.Width < width)
  272. {
  273. towidth = originalImage.Width;
  274. }
  275. if (originalImage.Height < height)
  276. {
  277. toheight = originalImage.Height;
  278. }
  279. break;
  280. case ThumbnailMode.UsrWidth: //指定宽,高按比例
  281. toheight = originalImage.Height * width / originalImage.Width;
  282. break;
  283. case ThumbnailMode.UsrWidthBound: //指定宽(过小则不变),高按比例
  284. if (originalImage.Width <= width)
  285. {
  286. return originalImage;
  287. }
  288. else
  289. {
  290. toheight = originalImage.Height * width / originalImage.Width;
  291. }
  292. break;
  293. case ThumbnailMode.UsrHeight: //指定高,宽按比例
  294. towidth = originalImage.Width * height / originalImage.Height;
  295. break;
  296. case ThumbnailMode.UsrHeightBound: //指定高(过小则不变),宽按比例
  297. if (originalImage.Height <= height)
  298. {
  299. return originalImage;
  300. }
  301. else
  302. {
  303. towidth = originalImage.Width * height / originalImage.Height;
  304. }
  305. break;
  306. case ThumbnailMode.Cut: //指定高宽裁减(不变形)
  307. //计算宽高比
  308. double srcScale = (double)originalImage.Width / (double)originalImage.Height;
  309. double destScale = (double)towidth / (double)toheight;
  310. //宽高比相同
  311. if (srcScale - destScale >= 0 && srcScale - destScale <= 0.001)
  312. {
  313. x = 0;
  314. y = 0;
  315. initWidth = originalImage.Width;
  316. initHeight = originalImage.Height;
  317. }
  318. //源宽高比大于目标宽高比
  319. //(源的宽比目标的宽大)
  320. else if (srcScale > destScale)
  321. {
  322. initWidth = originalImage.Height * towidth / toheight;
  323. initHeight = originalImage.Height;
  324. x = (originalImage.Width - initWidth) / 2;
  325. y = 0;
  326. }
  327. //源宽高比小于目标宽高小,源的高度大于目标的高度
  328. else
  329. {
  330. initWidth = originalImage.Width;
  331. initHeight = originalImage.Width * height / towidth;
  332. x = 0;
  333. y = (originalImage.Height - initHeight) / 2;
  334. }
  335. break;
  336. default:
  337. break;
  338. }
  339. Image bitmap = new Bitmap(towidth, toheight);
  340. //新建一个画板
  341. using (Graphics g = Graphics.FromImage(bitmap))
  342. {
  343. //设置高质量插值法
  344. g.CompositingQuality = CompositingQuality.HighQuality;
  345. //设置高质量,低速段呈现的平滑程度
  346. g.SmoothingMode = SmoothingMode.HighQuality;
  347. //在指定的位置上,并按指定大小绘制原图片的指定部分
  348. g.DrawImage(originalImage, new Rectangle(0, 0, towidth, toheight), new Rectangle(x, y, initWidth, initHeight), GraphicsUnit.Pixel);
  349. }
  350. return bitmap;
  351. }
  352. /// <summary>
  353. /// 深拷贝,反射
  354. /// </summary>
  355. /// <param name="obj"></param>
  356. /// <returns></returns>
  357. public static T DeepCopyByReflect<T>(T obj)
  358. {
  359. //如果是字符串或值类型则直接返回
  360. if (obj==null || obj is string || obj.GetType().IsValueType) return obj;
  361. object retval = Activator.CreateInstance(obj.GetType());
  362. FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
  363. foreach (FieldInfo field in fields)
  364. {
  365. try { field.SetValue(retval, DeepCopyByReflect(field.GetValue(obj))); }
  366. catch { }
  367. }
  368. return (T)retval;
  369. }
  370. public static List<T> DeepCopyListByReflect<T>(List<T> objs)
  371. {
  372. List<T> list = new List<T>();
  373. if (objs!=null && objs.Count>0)
  374. {
  375. foreach(T t in objs)
  376. {
  377. list.Add(DeepCopyByReflect(t));
  378. }
  379. }
  380. return list;
  381. }
  382. /// <summary>
  383. /// 深拷贝,xml序列化与反序列化
  384. /// </summary>
  385. /// <typeparam name="T"></typeparam>
  386. /// <param name="xmlData"></param>
  387. /// <returns></returns>
  388. public static T DeserializeXML<T>(string xmlData) where T : new()
  389. {
  390. if (string.IsNullOrEmpty(xmlData))
  391. return default(T);
  392. TextReader tr = new StringReader(xmlData);
  393. T DocItms = new T();
  394. XmlSerializer xms = new XmlSerializer(DocItms.GetType());
  395. DocItms = (T)xms.Deserialize(tr);
  396. return DocItms == null ? default(T) : DocItms;
  397. }
  398. /// <summary>
  399. /// 图片裁剪
  400. /// </summary>原图
  401. /// <param name="b"></param>
  402. /// <param name="StartX">裁剪起始点横坐标</param>
  403. /// <param name="StartY">裁剪起始点纵坐标</param>
  404. /// <param name="iWidth">裁剪宽度</param>
  405. /// <param name="iHeight">裁剪高度</param>
  406. /// <returns></returns>
  407. public static Bitmap KiCut(Bitmap b, int StartX, int StartY, int iWidth, int iHeight)
  408. {
  409. if (b == null)
  410. {
  411. return null;
  412. }
  413. //不对超过原图尺寸的区域做处理,以黑色背景显示
  414. //int w = b.Width;
  415. //int h = b.Height;
  416. //if (StartX >= w || StartY >= h)
  417. //{
  418. // return null;
  419. //}
  420. //if (StartX + iWidth > w)
  421. //{
  422. // iWidth = w - StartX;
  423. //}
  424. //if (StartY + iHeight > h)
  425. //{
  426. // iHeight = h - StartY;
  427. //}
  428. try
  429. {
  430. Bitmap bmpOut = new Bitmap(iWidth, iHeight);
  431. Graphics g = Graphics.FromImage(bmpOut);
  432. g.Clear(Color.Black);
  433. g.DrawImage(b, new Rectangle(0, 0, iWidth, iHeight), new Rectangle(StartX, StartY, iWidth, iHeight), GraphicsUnit.Pixel);
  434. g.Dispose();
  435. return bmpOut;
  436. }
  437. catch
  438. {
  439. return null;
  440. }
  441. }
  442. }
  443. }