using OfficeOpenXml.Drawing; using OfficeOpenXml.Packaging.Ionic.Zlib; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Formats.Bmp; using SixLabors.ImageSharp.Formats.Gif; using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.Formats.Tiff; using SixLabors.ImageSharp.Formats.Webp; using System.IO; using System.Xml; namespace Masuit.Tools.Excel; public static class ImageDetector { /// /// 获取图像格式 /// /// /// public static ePictureType? GetPictureType(Stream ms) { ms.Seek(0, SeekOrigin.Begin); var pictureType = Image.DetectFormat(ms) switch { BmpFormat => ePictureType.Bmp, GifFormat => ePictureType.Gif, JpegFormat => ePictureType.Jpg, PngFormat => ePictureType.Png, TiffFormat => ePictureType.Tif, WebpFormat => ePictureType.WebP, _ => new ePictureType?() }; if (pictureType.HasValue) { ms.Seek(0, SeekOrigin.Begin); return pictureType; } var br = new BinaryReader(ms); if (IsIco(br)) { ms.Seek(0, SeekOrigin.Begin); return ePictureType.Ico; } if (IsEmf(br)) { ms.Seek(0, SeekOrigin.Begin); return ePictureType.Emf; } if (IsWmf(br)) { ms.Seek(0, SeekOrigin.Begin); return ePictureType.Wmf; } if (IsSvg(ms)) { ms.Seek(0, SeekOrigin.Begin); return ePictureType.Svg; } if (IsGZip(br)) { _ = ExtractImage(ToArray(ms), out ePictureType? pt); ms.Seek(0, SeekOrigin.Begin); return pt; } return null; } /// /// /// /// /// public static byte[] ToArray(Stream stream) { stream.Position = 0; byte[] bytes = new byte[stream.Length]; stream.Read(bytes, 0, bytes.Length); // 设置当前流的位置为流的开始 stream.Seek(0, SeekOrigin.Begin); return bytes; } private static bool IsGZip(BinaryReader br) { br.BaseStream.Position = 0; var sign = br.ReadBytes(2); return IsGZip(sign); } private static bool IsGZip(byte[] sign) { return sign.Length >= 2 && sign[0] == 0x1F && sign[1] == 0x8B; } internal static byte[] ExtractImage(byte[] img, out ePictureType? type) { if (IsGZip(img)) { try { var ms = new MemoryStream(img); var msOut = new MemoryStream(); const int bufferSize = 4096; var buffer = new byte[bufferSize]; using var z = new GZipStream(ms, CompressionMode.Decompress); int size = 0; do { size = z.Read(buffer, 0, bufferSize); if (size > 0) { msOut.Write(buffer, 0, size); } } while (size == bufferSize); msOut.Position = 0; var br = new BinaryReader(msOut); if (IsEmf(br)) { type = ePictureType.Emf; } else if (IsWmf(br)) { type = ePictureType.Wmf; } else { type = null; } msOut.Position = 0; return msOut.ToArray(); } catch { type = null; return img; } } type = null; return img; } #region Ico internal static bool IsIco(BinaryReader br) { br.BaseStream.Seek(0, SeekOrigin.Begin); var type0 = br.ReadInt16(); var type1 = br.ReadInt16(); return type0 == 0 && type1 == 1; } #endregion Ico #region Emf private static bool IsEmf(BinaryReader br) { br.BaseStream.Position = 0; var type = br.ReadInt32(); return type == 1; } #endregion Emf #region Wmf private static bool IsWmf(BinaryReader br) { br.BaseStream.Position = 0; var key = br.ReadUInt32(); return key == 0x9AC6CDD7; } #endregion Wmf #region Svg private static bool IsSvg(Stream ms) { try { ms.Position = 0; var reader = new XmlTextReader(ms); while (reader.Read()) { if (reader.LocalName == "svg" && reader.NodeType == XmlNodeType.Element) { return true; } } return false; } catch { return false; } } #endregion Svg }