Utility.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. using System;
  2. using System.Drawing;
  3. using System.Drawing.Drawing2D;
  4. using System.IO;
  5. using System.Windows.Forms;
  6. namespace PaintDotNet
  7. {
  8. /// <summary>
  9. /// Defines miscellaneous constants and static functions.
  10. /// </summary>
  11. public sealed class Utility
  12. {
  13. private Utility()
  14. {
  15. }
  16. public static Keys LetterOrDigitCharToKeys(char c)
  17. {
  18. if (c >= 'a' && c <= 'z')
  19. {
  20. return (Keys)((int)(c - 'a') + (int)Keys.A);
  21. }
  22. else if (c >= 'A' && c <= 'Z')
  23. {
  24. return (Keys)((int)(c - 'A') + (int)Keys.A);
  25. }
  26. else if (c >= '0' && c <= '9')
  27. {
  28. return (Keys)((int)(c - '0') + (int)Keys.D0);
  29. }
  30. else
  31. {
  32. return Keys.None;
  33. }
  34. }
  35. public static Control FindFocus()
  36. {
  37. foreach (Form form in Application.OpenForms)
  38. {
  39. Control focused = FindFocus(form);
  40. if (focused != null)
  41. {
  42. return focused;
  43. }
  44. }
  45. return null;
  46. }
  47. private static Control FindFocus(Control c)
  48. {
  49. if (c.Focused)
  50. {
  51. return c;
  52. }
  53. foreach (Control child in c.Controls)
  54. {
  55. Control f = FindFocus(child);
  56. if (f != null)
  57. {
  58. return f;
  59. }
  60. }
  61. return null;
  62. }
  63. public static void DrawColorRectangle(Graphics g, Rectangle rect, Color color, bool drawBorder)
  64. {
  65. int inflateAmt = drawBorder ? -2 : 0;
  66. Rectangle colorRectangle = Rectangle.Inflate(rect, inflateAmt, inflateAmt);
  67. Brush colorBrush = new LinearGradientBrush(colorRectangle, Color.FromArgb(255, color), color, 90.0f, false);
  68. HatchBrush backgroundBrush = new HatchBrush(HatchStyle.LargeCheckerBoard, Color.FromArgb(191, 191, 191), Color.FromArgb(255, 255, 255));
  69. if (drawBorder)
  70. {
  71. g.DrawRectangle(Pens.Black, rect.Left, rect.Top, rect.Width - 1, rect.Height - 1);
  72. g.DrawRectangle(Pens.White, rect.Left + 1, rect.Top + 1, rect.Width - 3, rect.Height - 3);
  73. }
  74. PixelOffsetMode oldPOM = g.PixelOffsetMode;
  75. g.PixelOffsetMode = PixelOffsetMode.Half;
  76. g.FillRectangle(backgroundBrush, colorRectangle);
  77. g.FillRectangle(colorBrush, colorRectangle);
  78. g.PixelOffsetMode = oldPOM;
  79. backgroundBrush.Dispose();
  80. colorBrush.Dispose();
  81. }
  82. public static Font CreateFont(string name, float size, FontStyle style)
  83. {
  84. Font returnFont;
  85. try
  86. {
  87. returnFont = new Font(name, size, style);
  88. }
  89. catch (Exception)
  90. {
  91. returnFont = new Font(FontFamily.GenericSansSerif, size);
  92. }
  93. return returnFont;
  94. }
  95. public static readonly Color TransparentKey = Color.FromArgb(192, 192, 192);
  96. private static bool allowGCFullCollect = true;
  97. public static bool AllowGCFullCollect
  98. {
  99. get
  100. {
  101. return allowGCFullCollect;
  102. }
  103. set
  104. {
  105. allowGCFullCollect = value;
  106. }
  107. }
  108. public static void GCFullCollect()
  109. {
  110. if (AllowGCFullCollect)
  111. {
  112. GC.Collect();
  113. GC.WaitForPendingFinalizers();
  114. GC.Collect();
  115. GC.WaitForPendingFinalizers();
  116. }
  117. }
  118. public static bool IsArrowKey(Keys keyData)
  119. {
  120. Keys key = keyData & Keys.KeyCode;
  121. if (key == Keys.Up || key == Keys.Down || key == Keys.Left || key == Keys.Right)
  122. {
  123. return true;
  124. }
  125. else
  126. {
  127. return false;
  128. }
  129. }
  130. public static bool DoesControlHaveMouseCaptured(Control control)
  131. {
  132. bool result = false;
  133. result |= control.Capture;
  134. foreach (Control c in control.Controls)
  135. {
  136. result |= DoesControlHaveMouseCaptured(c);
  137. }
  138. return result;
  139. }
  140. public static void SplitRectangle(Rectangle rect, Rectangle[] rects)
  141. {
  142. int height = rect.Height;
  143. for (int i = 0; i < rects.Length; ++i)
  144. {
  145. Rectangle newRect = Rectangle.FromLTRB(rect.Left,
  146. rect.Top + ((height * i) / rects.Length),
  147. rect.Right,
  148. rect.Top + ((height * (i + 1)) / rects.Length));
  149. rects[i] = newRect;
  150. }
  151. }
  152. public static bool CheckNumericUpDown(NumericUpDown upDown)
  153. {
  154. int a;
  155. bool result = int.TryParse(upDown.Text, out a);
  156. if (result && (a <= (int)upDown.Maximum) && (a >= (int)upDown.Minimum))
  157. {
  158. return true;
  159. }
  160. else
  161. {
  162. return false;
  163. }
  164. }
  165. public static void SetNumericUpDownValue(NumericUpDown upDown, decimal newValue)
  166. {
  167. if (upDown.Value != newValue)
  168. {
  169. upDown.Value = newValue;
  170. }
  171. }
  172. public static void SetNumericUpDownValue(NumericUpDown upDown, int newValue)
  173. {
  174. SetNumericUpDownValue(upDown, (decimal)newValue);
  175. }
  176. public static void ErrorBox(IWin32Window parent, string message)
  177. {
  178. MessageBox.Show(parent, message, PdnInfo.GetBareProductName(), MessageBoxButtons.OK, MessageBoxIcon.Error);
  179. }
  180. public static DialogResult AskYesNo(IWin32Window parent, string question)
  181. {
  182. return MessageBox.Show(parent, question, PdnInfo.GetBareProductName(), MessageBoxButtons.YesNo, MessageBoxIcon.Question);
  183. }
  184. public static Icon ImageToIcon(Image image)
  185. {
  186. return ImageToIcon(image, Utility.TransparentKey);
  187. }
  188. public static Icon ImageToIcon(Image image, bool disposeImage)
  189. {
  190. return ImageToIcon(image, Utility.TransparentKey, disposeImage);
  191. }
  192. public static Icon ImageToIcon(Image image, Color seeThru)
  193. {
  194. return ImageToIcon(image, seeThru, false);
  195. }
  196. /// <summary>
  197. /// Converts an Image to an Icon.
  198. /// </summary>
  199. /// <param name="image">The Image to convert to an icon. Must be an appropriate icon size (32x32, 16x16, etc).</param>
  200. /// <param name="seeThru">The color that will be treated as transparent in the icon.</param>
  201. /// <param name="disposeImage">Whether or not to dispose the passed-in Image.</param>
  202. /// <returns>An Icon representation of the Image.</returns>
  203. public static Icon ImageToIcon(Image image, Color seeThru, bool disposeImage)
  204. {
  205. Bitmap bitmap = new Bitmap(image);
  206. for (int y = 0; y < bitmap.Height; ++y)
  207. {
  208. for (int x = 0; x < bitmap.Width; ++x)
  209. {
  210. if (bitmap.GetPixel(x, y) == seeThru)
  211. {
  212. bitmap.SetPixel(x, y, Color.FromArgb(0));
  213. }
  214. }
  215. }
  216. Icon icon = Icon.FromHandle(bitmap.GetHicon());
  217. bitmap.Dispose();
  218. if (disposeImage)
  219. {
  220. image.Dispose();
  221. }
  222. return icon;
  223. }
  224. /// <summary>
  225. /// Converts a RectangleF to RectangleF by rounding down the Location and rounding
  226. /// up the Size.
  227. /// </summary>
  228. public static Rectangle RoundRectangle(RectangleF rectF)
  229. {
  230. float left = (float)Math.Floor(rectF.Left);
  231. float top = (float)Math.Floor(rectF.Top);
  232. float right = (float)Math.Ceiling(rectF.Right);
  233. float bottom = (float)Math.Ceiling(rectF.Bottom);
  234. return Rectangle.Truncate(RectangleF.FromLTRB(left, top, right, bottom));
  235. }
  236. /// <summary>
  237. /// Allows you to find the bounding box for a "region" that is described as an
  238. /// array of bounding boxes.
  239. /// </summary>
  240. /// <param name="rectsF">The "region" you want to find a bounding box for.</param>
  241. /// <returns>A RectangleF structure that surrounds the Region.</returns>
  242. public static RectangleF GetRegionBounds(RectangleF[] rectsF, int startIndex, int length)
  243. {
  244. if (rectsF.Length == 0)
  245. {
  246. return RectangleF.Empty;
  247. }
  248. float left = rectsF[startIndex].Left;
  249. float top = rectsF[startIndex].Top;
  250. float right = rectsF[startIndex].Right;
  251. float bottom = rectsF[startIndex].Bottom;
  252. for (int i = startIndex + 1; i < startIndex + length; ++i)
  253. {
  254. RectangleF rectF = rectsF[i];
  255. if (rectF.Left < left)
  256. {
  257. left = rectF.Left;
  258. }
  259. if (rectF.Top < top)
  260. {
  261. top = rectF.Top;
  262. }
  263. if (rectF.Right > right)
  264. {
  265. right = rectF.Right;
  266. }
  267. if (rectF.Bottom > bottom)
  268. {
  269. bottom = rectF.Bottom;
  270. }
  271. }
  272. return RectangleF.FromLTRB(left, top, right, bottom);
  273. }
  274. /// <summary>
  275. /// Allows you to find the bounding box for a "region" that is described as an
  276. /// array of bounding boxes.
  277. /// </summary>
  278. /// <param name="rectsF">The "region" you want to find a bounding box for.</param>
  279. /// <returns>A RectangleF structure that surrounds the Region.</returns>
  280. public static Rectangle GetRegionBounds(Rectangle[] rects, int startIndex, int length)
  281. {
  282. if (rects.Length == 0)
  283. {
  284. return Rectangle.Empty;
  285. }
  286. int left = rects[startIndex].Left;
  287. int top = rects[startIndex].Top;
  288. int right = rects[startIndex].Right;
  289. int bottom = rects[startIndex].Bottom;
  290. for (int i = startIndex + 1; i < startIndex + length; ++i)
  291. {
  292. Rectangle rect = rects[i];
  293. if (rect.Left < left)
  294. {
  295. left = rect.Left;
  296. }
  297. if (rect.Top < top)
  298. {
  299. top = rect.Top;
  300. }
  301. if (rect.Right > right)
  302. {
  303. right = rect.Right;
  304. }
  305. if (rect.Bottom > bottom)
  306. {
  307. bottom = rect.Bottom;
  308. }
  309. }
  310. return Rectangle.FromLTRB(left, top, right, bottom);
  311. }
  312. public static double Clamp(double x, double min, double max)
  313. {
  314. if (x < min)
  315. {
  316. return min;
  317. }
  318. else if (x > max)
  319. {
  320. return max;
  321. }
  322. else
  323. {
  324. return x;
  325. }
  326. }
  327. public static int Clamp(int x, int min, int max)
  328. {
  329. if (x < min)
  330. {
  331. return min;
  332. }
  333. else if (x > max)
  334. {
  335. return max;
  336. }
  337. else
  338. {
  339. return x;
  340. }
  341. }
  342. public static byte ClampToByte(double x)
  343. {
  344. if (x > 255)
  345. {
  346. return 255;
  347. }
  348. else if (x < 0)
  349. {
  350. return 0;
  351. }
  352. else
  353. {
  354. return (byte)x;
  355. }
  356. }
  357. public static byte ClampToByte(float x)
  358. {
  359. if (x > 255)
  360. {
  361. return 255;
  362. }
  363. else if (x < 0)
  364. {
  365. return 0;
  366. }
  367. else
  368. {
  369. return (byte)x;
  370. }
  371. }
  372. public static byte ClampToByte(int x)
  373. {
  374. if (x > 255)
  375. {
  376. return 255;
  377. }
  378. else if (x < 0)
  379. {
  380. return 0;
  381. }
  382. else
  383. {
  384. return (byte)x;
  385. }
  386. }
  387. public static float Lerp(float from, float to, float frac)
  388. {
  389. return (from + frac * (to - from));
  390. }
  391. public static double Lerp(double from, double to, double frac)
  392. {
  393. return (from + frac * (to - from));
  394. }
  395. public static void ShowHelp(Control parent,int type)
  396. {
  397. //string helpFileUrlFormat = PdnResources.GetString("HelpFile.Url.Format");
  398. //string baseSiteUrl = Application.StartupPath + @"\最新显微镜图像处理与分析系统 (修正版本)20210206.chm";//InvariantStrings.WebsiteUrl;
  399. //string helpFileUrl = baseSiteUrl;// string.Format(helpFileUrlFormat, baseSiteUrl);
  400. string filePath = Application.StartupPath + @"\最新显微镜图像处理与分析系统 (修正版本)20210206.chm";
  401. if (!System.IO.File.Exists(filePath))
  402. {
  403. return;
  404. }
  405. if (type == 1)
  406. {
  407. Help.ShowHelp(parent, filePath);
  408. }
  409. else {
  410. Help.ShowHelp(parent, filePath, HelpNavigator.Index);
  411. }
  412. //JScript\JScript
  413. //PdnInfo.OpenUrl(parent, helpFileUrl);
  414. }
  415. /// <summary>
  416. /// Reads a 16-bit unsigned integer from a Stream in little-endian format.
  417. /// </summary>
  418. /// <param name="stream"></param>
  419. /// <returns>-1 on failure, else the 16-bit unsigned integer that was read.</returns>
  420. public static int ReadUInt16(Stream stream)
  421. {
  422. int byte1 = stream.ReadByte();
  423. if (byte1 == -1)
  424. {
  425. return -1;
  426. }
  427. int byte2 = stream.ReadByte();
  428. if (byte2 == -1)
  429. {
  430. return -1;
  431. }
  432. return byte1 + (byte2 << 8);
  433. }
  434. public static void WriteUInt16(Stream stream, UInt16 word)
  435. {
  436. stream.WriteByte((byte)(word & 0xff));
  437. stream.WriteByte((byte)(word >> 8));
  438. }
  439. public static void WriteUInt24(Stream stream, int uint24)
  440. {
  441. stream.WriteByte((byte)(uint24 & 0xff));
  442. stream.WriteByte((byte)((uint24 >> 8) & 0xff));
  443. stream.WriteByte((byte)((uint24 >> 16) & 0xff));
  444. }
  445. public static void WriteUInt32(Stream stream, UInt32 uint32)
  446. {
  447. stream.WriteByte((byte)(uint32 & 0xff));
  448. stream.WriteByte((byte)((uint32 >> 8) & 0xff));
  449. stream.WriteByte((byte)((uint32 >> 16) & 0xff));
  450. stream.WriteByte((byte)((uint32 >> 24) & 0xff));
  451. }
  452. /// <summary>
  453. /// Reads a 24-bit unsigned integer from a Stream in little-endian format.
  454. /// </summary>
  455. /// <param name="stream"></param>
  456. /// <returns>-1 on failure, else the 24-bit unsigned integer that was read.</returns>
  457. public static int ReadUInt24(Stream stream)
  458. {
  459. int byte1 = stream.ReadByte();
  460. if (byte1 == -1)
  461. {
  462. return -1;
  463. }
  464. int byte2 = stream.ReadByte();
  465. if (byte2 == -1)
  466. {
  467. return -1;
  468. }
  469. int byte3 = stream.ReadByte();
  470. if (byte3 == -1)
  471. {
  472. return -1;
  473. }
  474. return byte1 + (byte2 << 8) + (byte3 << 16);
  475. }
  476. /// <summary>
  477. /// Reads a 32-bit unsigned integer from a Stream in little-endian format.
  478. /// </summary>
  479. /// <param name="stream"></param>
  480. /// <returns>-1 on failure, else the 32-bit unsigned integer that was read.</returns>
  481. public static long ReadUInt32(Stream stream)
  482. {
  483. int byte1 = stream.ReadByte();
  484. if (byte1 == -1)
  485. {
  486. return -1;
  487. }
  488. int byte2 = stream.ReadByte();
  489. if (byte2 == -1)
  490. {
  491. return -1;
  492. }
  493. int byte3 = stream.ReadByte();
  494. if (byte3 == -1)
  495. {
  496. return -1;
  497. }
  498. int byte4 = stream.ReadByte();
  499. if (byte4 == -1)
  500. {
  501. return -1;
  502. }
  503. return unchecked((long)((uint)(byte1 + (byte2 << 8) + (byte3 << 16) + (byte4 << 24))));
  504. }
  505. public static int ReadFromStream(Stream input, byte[] buffer, int offset, int count)
  506. {
  507. int totalBytesRead = 0;
  508. while (totalBytesRead < count)
  509. {
  510. int bytesRead = input.Read(buffer, offset + totalBytesRead, count - totalBytesRead);
  511. if (bytesRead == 0)
  512. {
  513. throw new IOException("ran out of data");
  514. }
  515. totalBytesRead += bytesRead;
  516. }
  517. return totalBytesRead;
  518. }
  519. public static void Swap<T>(ref T a, ref T b)
  520. {
  521. T t;
  522. t = a;
  523. a = b;
  524. b = t;
  525. }
  526. public static byte FastScaleByteByByte(byte a, byte b)
  527. {
  528. int r1 = a * b + 0x80;
  529. int r2 = ((r1 >> 8) + r1) >> 8;
  530. return (byte)r2;
  531. }
  532. }
  533. }