ImageDetector.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. using OfficeOpenXml.Drawing;
  2. using OfficeOpenXml.Packaging.Ionic.Zlib;
  3. using SixLabors.ImageSharp;
  4. using SixLabors.ImageSharp.Formats.Bmp;
  5. using SixLabors.ImageSharp.Formats.Gif;
  6. using SixLabors.ImageSharp.Formats.Jpeg;
  7. using SixLabors.ImageSharp.Formats.Png;
  8. using SixLabors.ImageSharp.Formats.Tiff;
  9. using SixLabors.ImageSharp.Formats.Webp;
  10. using System.IO;
  11. using System.Xml;
  12. namespace Masuit.Tools.Excel;
  13. public static class ImageDetector
  14. {
  15. /// <summary>
  16. /// 获取图像格式
  17. /// </summary>
  18. /// <param name="ms"></param>
  19. /// <returns></returns>
  20. public static ePictureType? GetPictureType(Stream ms)
  21. {
  22. ms.Seek(0, SeekOrigin.Begin);
  23. var pictureType = Image.DetectFormat(ms) switch
  24. {
  25. BmpFormat => ePictureType.Bmp,
  26. GifFormat => ePictureType.Gif,
  27. JpegFormat => ePictureType.Jpg,
  28. PngFormat => ePictureType.Png,
  29. TiffFormat => ePictureType.Tif,
  30. WebpFormat => ePictureType.WebP,
  31. _ => new ePictureType?()
  32. };
  33. if (pictureType.HasValue)
  34. {
  35. ms.Seek(0, SeekOrigin.Begin);
  36. return pictureType;
  37. }
  38. var br = new BinaryReader(ms);
  39. if (IsIco(br))
  40. {
  41. ms.Seek(0, SeekOrigin.Begin);
  42. return ePictureType.Ico;
  43. }
  44. if (IsEmf(br))
  45. {
  46. ms.Seek(0, SeekOrigin.Begin);
  47. return ePictureType.Emf;
  48. }
  49. if (IsWmf(br))
  50. {
  51. ms.Seek(0, SeekOrigin.Begin);
  52. return ePictureType.Wmf;
  53. }
  54. if (IsSvg(ms))
  55. {
  56. ms.Seek(0, SeekOrigin.Begin);
  57. return ePictureType.Svg;
  58. }
  59. if (IsGZip(br))
  60. {
  61. _ = ExtractImage(ToArray(ms), out ePictureType? pt);
  62. ms.Seek(0, SeekOrigin.Begin);
  63. return pt;
  64. }
  65. return null;
  66. }
  67. /// <summary>
  68. ///
  69. /// </summary>
  70. /// <param name="stream"></param>
  71. /// <returns></returns>
  72. public static byte[] ToArray(Stream stream)
  73. {
  74. stream.Position = 0;
  75. byte[] bytes = new byte[stream.Length];
  76. stream.Read(bytes, 0, bytes.Length);
  77. // 设置当前流的位置为流的开始
  78. stream.Seek(0, SeekOrigin.Begin);
  79. return bytes;
  80. }
  81. private static bool IsGZip(BinaryReader br)
  82. {
  83. br.BaseStream.Position = 0;
  84. var sign = br.ReadBytes(2);
  85. return IsGZip(sign);
  86. }
  87. private static bool IsGZip(byte[] sign)
  88. {
  89. return sign.Length >= 2 && sign[0] == 0x1F && sign[1] == 0x8B;
  90. }
  91. internal static byte[] ExtractImage(byte[] img, out ePictureType? type)
  92. {
  93. if (IsGZip(img))
  94. {
  95. try
  96. {
  97. var ms = new MemoryStream(img);
  98. var msOut = new MemoryStream();
  99. const int bufferSize = 4096;
  100. var buffer = new byte[bufferSize];
  101. using var z = new GZipStream(ms, CompressionMode.Decompress);
  102. int size = 0;
  103. do
  104. {
  105. size = z.Read(buffer, 0, bufferSize);
  106. if (size > 0)
  107. {
  108. msOut.Write(buffer, 0, size);
  109. }
  110. }
  111. while (size == bufferSize);
  112. msOut.Position = 0;
  113. var br = new BinaryReader(msOut);
  114. if (IsEmf(br))
  115. {
  116. type = ePictureType.Emf;
  117. }
  118. else if (IsWmf(br))
  119. {
  120. type = ePictureType.Wmf;
  121. }
  122. else
  123. {
  124. type = null;
  125. }
  126. msOut.Position = 0;
  127. return msOut.ToArray();
  128. }
  129. catch
  130. {
  131. type = null;
  132. return img;
  133. }
  134. }
  135. type = null;
  136. return img;
  137. }
  138. #region Ico
  139. internal static bool IsIco(BinaryReader br)
  140. {
  141. br.BaseStream.Seek(0, SeekOrigin.Begin);
  142. var type0 = br.ReadInt16();
  143. var type1 = br.ReadInt16();
  144. return type0 == 0 && type1 == 1;
  145. }
  146. #endregion Ico
  147. #region Emf
  148. private static bool IsEmf(BinaryReader br)
  149. {
  150. br.BaseStream.Position = 0;
  151. var type = br.ReadInt32();
  152. return type == 1;
  153. }
  154. #endregion Emf
  155. #region Wmf
  156. private static bool IsWmf(BinaryReader br)
  157. {
  158. br.BaseStream.Position = 0;
  159. var key = br.ReadUInt32();
  160. return key == 0x9AC6CDD7;
  161. }
  162. #endregion Wmf
  163. #region Svg
  164. private static bool IsSvg(Stream ms)
  165. {
  166. try
  167. {
  168. ms.Position = 0;
  169. var reader = new XmlTextReader(ms);
  170. while (reader.Read())
  171. {
  172. if (reader.LocalName == "svg" && reader.NodeType == XmlNodeType.Element)
  173. {
  174. return true;
  175. }
  176. }
  177. return false;
  178. }
  179. catch
  180. {
  181. return false;
  182. }
  183. }
  184. #endregion Svg
  185. }