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.

193 lines
6.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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;
/// <summary>
/// 图片工具类
/// </summary>
public static class ImageUtil
{
/// <summary>
/// 获取外网Url图片的二进制数组
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public static async Task<byte[]> 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;
}
/// <summary>
/// 保存二进制流到文件
/// </summary>
/// <param name="content"></param>
/// <param name="fileName"></param>
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);
}
}
/// <summary>
/// 保存外网Url到文件
/// </summary>
/// <param name="url">外网图片Url</param>
/// <param name="fileName">要保存的文件名称</param>
/// <returns></returns>
public static async Task SaveFromUrlToFile(this string url, string fileName)
{
var bytes = await url.GetBytesFromUrl();
await WriteBytesToFile(bytes, fileName);
}
/// <summary>
/// 删除文件夹里面所有的文件
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
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);
}
}
/// <summary>
/// 无损压缩图片
/// </summary>
/// <param name="sourceFile">原图片地址</param>
/// <param name="compressFile">压缩后保存图片地址</param>
/// <param name="compressHeight">压缩后宽度</param>
/// <param name="compressWidth">压缩后高度</param>
/// <param name="flag">压缩质量(数字越小压缩率越高)</param>
/// <param name="size">压缩后图片的最大大小</param>
/// <param name="isFirst">是否为第一次调用</param>
/// <returns></returns>
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();
}
}
}