#if NET40 || NET461 using Apewer; using Apewer.Internals; using Apewer.Internals.QrCode; using Apewer.Models; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.IO; using System.Text; namespace Apewer.Surface { /// 图像实用工具。 public static class ImageUtility { internal static byte[] EmptyBytes { get { return new byte[0]; } } /// 保存图像到文件。 /// public static byte[] SaveAs(this Image image, ImageFormat format) { if (image == null) throw new ArgumentNullException(nameof(image)); if (format == null) throw new ArgumentNullException(nameof(format)); var memory = new MemoryStream(); var bytes = null as byte[]; try { image.Save(memory, format); bytes = memory.ToArray(); } catch { } memory.Dispose(); return bytes; } /// 保存为 PNG 文件。 /// public static byte[] SaveAsPng(this Image image) { return SaveAs(image, ImageFormat.Png); } /// 保存为 JPEG 文件。 /// public static byte[] SaveAsJpeg(this Image image) { return SaveAs(image, ImageFormat.Jpeg); } /// 调整图像尺寸,生成新图像。 /// 原图像。 /// 新图像的宽度,在缩放时此参数用于限定最大宽度。 /// 新图像的高度,在缩放时此参数用于限定最大高度。 /// 保持原比例进行缩放。 /// 新图像。 public static Bitmap Resize(this Image image, int width, int height, bool scale = false) { if (image == null) throw new ArgumentNullException(nameof(image)); if (width < 0) throw new ArgumentOutOfRangeException(nameof(width)); if (height < 0) throw new ArgumentOutOfRangeException(nameof(height)); var newWidth = width; var newHeight = height; if (scale) { newWidth = image.Width; newHeight = image.Height; var radio = Convert.ToDouble(newWidth) / Convert.ToDouble(newHeight); if (newWidth > width) { newWidth = width; newHeight = Convert.ToInt32(width / radio); } if (newHeight > height) { newWidth = Convert.ToInt32(height * radio); newHeight = height; } } var bitmap = new Bitmap(newWidth, newHeight); try { using (var graphic = Graphics.FromImage(bitmap)) { graphic.CompositingMode = CompositingMode.SourceOver; graphic.CompositingQuality = CompositingQuality.HighQuality; graphic.SmoothingMode = SmoothingMode.AntiAlias; graphic.Clear(Color.Transparent); graphic.DrawImage(image, 0, 0, width, height); } return bitmap; } catch (Exception ex) { RuntimeUtility.Dispose(bitmap); throw ex; } } /// 生成二维码图像,可指定色块边长像素值和纠错率,失败时返回 NULL 值。 public static Bitmap GenerateQrCode(string text, int block = 8) { return GenerateQrCode(text, block, Color.Black, Color.White); } /// 生成二维码图像,可指定色块边长像素值和纠错率,失败时返回 NULL 值。 public static Bitmap GenerateQrCode(string text, int block, Color dark, Color light) { var t = text ?? ""; var b = block > 1 ? block : 1; var ecclevel = QRCodeGenerator.ECCLevel.M; // var ecc = QrCodeEccLevel.M; // if (ecc == QrCodeEccLevel.L) ecclevel = QRCodeGenerator.ECCLevel.L; // else if (ecc == QrCodeEccLevel.M) ecclevel = QRCodeGenerator.ECCLevel.M; // else if (ecc == QrCodeEccLevel.Q) ecclevel = QRCodeGenerator.ECCLevel.Q; // else if (ecc == QrCodeEccLevel.H) ecclevel = QRCodeGenerator.ECCLevel.H; try { var generator = new QRCodeGenerator(); var content = generator.CreateQrCode(t, ecclevel); var qrcode = new QRCode(content); var bitmap = qrcode.GetGraphic(b, dark, light, false); return bitmap; } catch { return null; } } /// 从 RGBA 十六进制字符串获取颜色。 public static Color GetColorByHex(string hex, Color @default) { var lower = hex.ToLower(); if (lower == "none" || lower == "alpha" || lower == "transparent") { return Color.Transparent; } else { const string pool = "0123456789abcdef"; lower = TextUtility.Restrict(lower, pool); if (lower.Length >= 6) { var r = pool.IndexOf(lower[0]) * 16 + pool.IndexOf(lower[1]); var g = pool.IndexOf(lower[2]) * 16 + pool.IndexOf(lower[3]); var b = pool.IndexOf(lower[4]) * 16 + pool.IndexOf(lower[5]); var a = 255; if (lower.Length >= 8) { a = pool.IndexOf(lower[6]) * 16 + pool.IndexOf(lower[7]); } var color = Color.FromArgb(a, r, g, b); return color; } } return @default; } } } #endif