using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Threading.Tasks; using Furion.RemoteRequest.Extensions; namespace GDZZ.Core; /// /// 图片工具类 /// public static class ImageUtil { /// /// 获取外网Url图片的二进制数组 /// /// /// public static async Task GetBytesFromUrl(this string url) { // 得到图片流 var result = await url.GetAsStreamAsync(); using var binaryReader = new BinaryReader(result.Stream); // 读取二进制文件流 var resultBytes = binaryReader.ReadBytes(result.Stream.Length.ParseToInt()); binaryReader.Close(); return resultBytes; } /// /// 保存二进制流到文件 /// /// /// public static async Task WriteBytesToFile(byte[] content, string fileName) { // 检测文件夹是否存在 if (!Directory.Exists(fileName[..fileName.LastIndexOf("/", StringComparison.Ordinal)])) { Directory.CreateDirectory(fileName[..fileName.LastIndexOf("/", StringComparison.Ordinal)]); } // 检测文件是否存在 if (!File.Exists(fileName)) { await File.WriteAllBytesAsync(fileName, content); } } /// /// 保存外网Url到文件 /// /// 外网图片Url /// 要保存的文件名称 /// public static async Task SaveFromUrlToFile(this string url, string fileName) { var bytes = await url.GetBytesFromUrl(); await WriteBytesToFile(bytes, fileName); } /// /// 删除文件夹里面所有的文件 /// /// /// public static void DeleteFile(this string fileName) { foreach (var entry in Directory.GetFileSystemEntries(fileName)) { if (!File.Exists(entry)) continue; var name = Path.GetFileNameWithoutExtension(entry); File.Delete(entry); } } /// /// 无损压缩图片 /// /// 原图片地址 /// 压缩后保存图片地址 /// 压缩后宽度 /// 压缩后高度 /// 压缩质量(数字越小压缩率越高) /// 压缩后图片的最大大小 /// 是否为第一次调用 /// public static bool CompressImage(string sourceFile, string compressFile, int compressHeight = 750, int compressWidth = 1334, int flag = 90, int size = 110, bool isFirst = true) { // 如果是第一次调用,原始图像的大小小于要压缩的大小,则直接复制文件,并且返回True var firstFileInfo = new FileInfo(sourceFile); if (isFirst && firstFileInfo.Length < size * 1024) { firstFileInfo.CopyTo(compressFile); return true; } var imageSource = Image.FromFile(sourceFile); var imageFormat = imageSource.RawFormat; var sourceWidth = 0; var sourceHeight = 0; // 按比例缩放 var temSize = new Size(imageSource.Width, imageSource.Height); // 处理大小,如果是0,原大小 if (compressHeight.IsNullOrZero()) { compressHeight = temSize.Height; } if (compressWidth.IsNullOrZero()) { compressWidth = temSize.Width; } if (temSize.Width > compressHeight || temSize.Width > compressWidth) { if ((temSize.Width * compressHeight) > (temSize.Width * compressWidth)) { sourceWidth = compressWidth; sourceHeight = (compressWidth * temSize.Height) / temSize.Width; } else { sourceWidth = compressHeight; sourceHeight = (temSize.Height * compressHeight) / temSize.Height; } } else { sourceWidth = temSize.Width; sourceHeight = temSize.Height; } var bitmap = new Bitmap(compressWidth, compressHeight); var graphics = Graphics.FromImage(bitmap); graphics.Clear(Color.Transparent); graphics.CompositingQuality = CompositingQuality.HighQuality; graphics.SmoothingMode = SmoothingMode.HighQuality; graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; graphics.DrawImage(imageSource, new Rectangle((compressWidth - sourceWidth) / 2, (compressHeight - sourceHeight) / 2, sourceWidth, sourceHeight), 0, 0, imageSource.Width, imageSource.Height, GraphicsUnit.Pixel); graphics.Dispose(); // 设置压缩质量 var encoderParameters = new EncoderParameters {Param = {[0] = new EncoderParameter(Encoder.Quality, new long[] {flag})}}; try { // 找到系统中可用的图片编码器信息 var imageCodecInfos = ImageCodecInfo.GetImageEncoders(); var jpegIciInfo = imageCodecInfos.FirstOrDefault(t => t.FormatDescription.Equals("JPEG")); // 如果编码器存在的,可以压缩 if (jpegIciInfo != null) { bitmap.Save(compressFile, jpegIciInfo, encoderParameters); var fileInfo = new FileInfo(compressFile); if (fileInfo.Length <= 1024 * size) return true; flag -= 10; CompressImage(sourceFile, compressFile, compressHeight, compressWidth, flag, size, false); } else { bitmap.Save(compressFile, imageFormat); } return true; } catch { return false; } finally { imageSource.Dispose(); bitmap.Dispose(); } } }