You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

172 lines
6.2 KiB

2 years ago
2 years ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
2 years ago
4 years ago
  1. #if NET40 || NET461
  2. using Apewer;
  3. using Apewer.Internals;
  4. using Apewer.Internals.QrCode;
  5. using Apewer.Models;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Drawing;
  9. using System.Drawing.Drawing2D;
  10. using System.Drawing.Imaging;
  11. using System.IO;
  12. using System.Text;
  13. namespace Apewer.Surface
  14. {
  15. /// <summary>图像实用工具。</summary>
  16. public static class ImageUtility
  17. {
  18. internal static byte[] EmptyBytes { get { return new byte[0]; } }
  19. /// <summary>保存图像到文件。</summary>
  20. /// <exception cref="ArgumentNullException" />
  21. public static byte[] SaveAs(this Image image, ImageFormat format)
  22. {
  23. if (image == null) throw new ArgumentNullException(nameof(image));
  24. if (format == null) throw new ArgumentNullException(nameof(format));
  25. var memory = new MemoryStream();
  26. var bytes = null as byte[];
  27. try
  28. {
  29. image.Save(memory, format);
  30. bytes = memory.ToArray();
  31. }
  32. catch { }
  33. memory.Dispose();
  34. return bytes;
  35. }
  36. /// <summary>保存为 PNG 文件。</summary>
  37. /// <exception cref="ArgumentNullException" />
  38. public static byte[] SaveAsPng(this Image image)
  39. {
  40. return SaveAs(image, ImageFormat.Png);
  41. }
  42. /// <summary>保存为 JPEG 文件。</summary>
  43. /// <exception cref="ArgumentNullException" />
  44. public static byte[] SaveAsJpeg(this Image image)
  45. {
  46. return SaveAs(image, ImageFormat.Jpeg);
  47. }
  48. /// <summary>调整图像尺寸,生成新图像。</summary>
  49. /// <param name="image">原图像。</param>
  50. /// <param name="width">新图像的宽度,在缩放时此参数用于限定最大宽度。</param>
  51. /// <param name="height">新图像的高度,在缩放时此参数用于限定最大高度。</param>
  52. /// <param name="scale">保持原比例进行缩放。</param>
  53. /// <returns>新图像。</returns>
  54. public static Bitmap Resize(this Image image, int width, int height, bool scale = false)
  55. {
  56. if (image == null) throw new ArgumentNullException(nameof(image));
  57. if (width < 0) throw new ArgumentOutOfRangeException(nameof(width));
  58. if (height < 0) throw new ArgumentOutOfRangeException(nameof(height));
  59. var newWidth = width;
  60. var newHeight = height;
  61. if (scale)
  62. {
  63. newWidth = image.Width;
  64. newHeight = image.Height;
  65. var radio = Convert.ToDouble(newWidth) / Convert.ToDouble(newHeight);
  66. if (newWidth > width)
  67. {
  68. newWidth = width;
  69. newHeight = Convert.ToInt32(width / radio);
  70. }
  71. if (newHeight > height)
  72. {
  73. newWidth = Convert.ToInt32(height * radio);
  74. newHeight = height;
  75. }
  76. }
  77. var bitmap = new Bitmap(newWidth, newHeight);
  78. try
  79. {
  80. using (var graphic = Graphics.FromImage(bitmap))
  81. {
  82. graphic.CompositingMode = CompositingMode.SourceOver;
  83. graphic.CompositingQuality = CompositingQuality.HighQuality;
  84. graphic.SmoothingMode = SmoothingMode.AntiAlias;
  85. graphic.Clear(Color.Transparent);
  86. graphic.DrawImage(image, 0, 0, width, height);
  87. }
  88. return bitmap;
  89. }
  90. catch (Exception ex)
  91. {
  92. RuntimeUtility.Dispose(bitmap);
  93. throw ex;
  94. }
  95. }
  96. /// <summary>生成二维码图像,可指定色块边长像素值和纠错率,失败时返回 NULL 值。</summary>
  97. public static Bitmap GenerateQrCode(string text, int block = 8)
  98. {
  99. return GenerateQrCode(text, block, Color.Black, Color.White);
  100. }
  101. /// <summary>生成二维码图像,可指定色块边长像素值和纠错率,失败时返回 NULL 值。</summary>
  102. public static Bitmap GenerateQrCode(string text, int block, Color dark, Color light)
  103. {
  104. var t = text ?? "";
  105. var b = block > 1 ? block : 1;
  106. var ecclevel = QRCodeGenerator.ECCLevel.M;
  107. // var ecc = QrCodeEccLevel.M;
  108. // if (ecc == QrCodeEccLevel.L) ecclevel = QRCodeGenerator.ECCLevel.L;
  109. // else if (ecc == QrCodeEccLevel.M) ecclevel = QRCodeGenerator.ECCLevel.M;
  110. // else if (ecc == QrCodeEccLevel.Q) ecclevel = QRCodeGenerator.ECCLevel.Q;
  111. // else if (ecc == QrCodeEccLevel.H) ecclevel = QRCodeGenerator.ECCLevel.H;
  112. try
  113. {
  114. var generator = new QRCodeGenerator();
  115. var content = generator.CreateQrCode(t, ecclevel);
  116. var qrcode = new QRCode(content);
  117. var bitmap = qrcode.GetGraphic(b, dark, light, false);
  118. return bitmap;
  119. }
  120. catch { return null; }
  121. }
  122. /// <summary>从 RGBA 十六进制字符串获取颜色。</summary>
  123. public static Color GetColorByHex(string hex, Color @default)
  124. {
  125. var lower = hex.ToLower();
  126. if (lower == "none" || lower == "alpha" || lower == "transparent")
  127. {
  128. return Color.Transparent;
  129. }
  130. else
  131. {
  132. const string pool = "0123456789abcdef";
  133. lower = TextUtility.Restrict(lower, pool);
  134. if (lower.Length >= 6)
  135. {
  136. var r = pool.IndexOf(lower[0]) * 16 + pool.IndexOf(lower[1]);
  137. var g = pool.IndexOf(lower[2]) * 16 + pool.IndexOf(lower[3]);
  138. var b = pool.IndexOf(lower[4]) * 16 + pool.IndexOf(lower[5]);
  139. var a = 255;
  140. if (lower.Length >= 8)
  141. {
  142. a = pool.IndexOf(lower[6]) * 16 + pool.IndexOf(lower[7]);
  143. }
  144. var color = Color.FromArgb(a, r, g, b);
  145. return color;
  146. }
  147. }
  148. return @default;
  149. }
  150. }
  151. }
  152. #endif