ImageUtilities.cs 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146
  1. using System;
  2. using System.Drawing;
  3. using System.Drawing.Drawing2D;
  4. using System.Drawing.Imaging;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Net.Http;
  8. using System.Net.Http.Headers;
  9. using System.Threading.Tasks;
  10. namespace Masuit.Tools.Media
  11. {
  12. /// <summary>
  13. /// 图片处理
  14. /// </summary>
  15. public static class ImageUtilities
  16. {
  17. #region 正方型裁剪并缩放
  18. /// <summary>
  19. /// 正方型裁剪
  20. /// 以图片中心为轴心,截取正方型,然后等比缩放
  21. /// 用于头像处理
  22. /// </summary>
  23. /// <param name="fromFile">原图Stream对象</param>
  24. /// <param name="fileSaveUrl">缩略图存放地址</param>
  25. /// <param name="side">指定的边长(正方型)</param>
  26. /// <param name="quality">质量(范围0-100)</param>
  27. public static void CutForSquare(this Stream fromFile, string fileSaveUrl, int side, int quality)
  28. {
  29. //创建目录
  30. string dir = Path.GetDirectoryName(fileSaveUrl);
  31. if (!Directory.Exists(dir))
  32. {
  33. Directory.CreateDirectory(dir);
  34. }
  35. //原始图片(获取原始图片创建对象,并使用流中嵌入的颜色管理信息)
  36. Image initImage = Image.FromStream(fromFile, true);
  37. //原图宽高均小于模版,不作处理,直接保存
  38. if ((initImage.Width <= side) && (initImage.Height <= side))
  39. {
  40. initImage.Save(fileSaveUrl, ImageFormat.Jpeg);
  41. }
  42. else
  43. {
  44. //原始图片的宽、高
  45. int initWidth = initImage.Width;
  46. int initHeight = initImage.Height;
  47. //非正方型先裁剪为正方型
  48. if (initWidth != initHeight)
  49. {
  50. //截图对象
  51. Image pickedImage;
  52. Graphics pickedG;
  53. //宽大于高的横图
  54. if (initWidth > initHeight)
  55. {
  56. //对象实例化
  57. pickedImage = new Bitmap(initHeight, initHeight);
  58. pickedG = Graphics.FromImage(pickedImage);
  59. //设置质量
  60. pickedG.InterpolationMode = InterpolationMode.HighQualityBicubic;
  61. pickedG.SmoothingMode = SmoothingMode.HighQuality;
  62. //定位
  63. Rectangle fromR = new Rectangle((initWidth - initHeight) / 2, 0, initHeight, initHeight);
  64. Rectangle toR = new Rectangle(0, 0, initHeight, initHeight);
  65. //画图
  66. pickedG.DrawImage(initImage, toR, fromR, GraphicsUnit.Pixel);
  67. //重置宽
  68. initWidth = initHeight;
  69. }
  70. //高大于宽的竖图
  71. else
  72. {
  73. //对象实例化
  74. pickedImage = new Bitmap(initWidth, initWidth);
  75. pickedG = Graphics.FromImage(pickedImage);
  76. //设置质量
  77. pickedG.InterpolationMode = InterpolationMode.HighQualityBicubic;
  78. pickedG.SmoothingMode = SmoothingMode.HighQuality;
  79. //定位
  80. Rectangle fromR = new Rectangle(0, (initHeight - initWidth) / 2, initWidth, initWidth);
  81. Rectangle toR = new Rectangle(0, 0, initWidth, initWidth);
  82. //画图
  83. pickedG.DrawImage(initImage, toR, fromR, GraphicsUnit.Pixel);
  84. //重置高
  85. initHeight = initWidth;
  86. }
  87. //将截图对象赋给原图
  88. initImage = (Image)pickedImage.Clone();
  89. //释放截图资源
  90. pickedG.Dispose();
  91. pickedImage.Dispose();
  92. }
  93. //缩略图对象
  94. Image resultImage = new Bitmap(side, side);
  95. Graphics resultG = Graphics.FromImage(resultImage);
  96. //设置质量
  97. resultG.InterpolationMode = InterpolationMode.HighQualityBicubic;
  98. resultG.SmoothingMode = SmoothingMode.HighQuality;
  99. //用指定背景色清空画布
  100. resultG.Clear(Color.White);
  101. //绘制缩略图
  102. resultG.DrawImage(initImage, new Rectangle(0, 0, side, side), new Rectangle(0, 0, initWidth, initHeight), GraphicsUnit.Pixel);
  103. //关键质量控制
  104. //获取系统编码类型数组,包含了jpeg,bmp,png,gif,tiff
  105. ImageCodecInfo[] icis = ImageCodecInfo.GetImageEncoders();
  106. ImageCodecInfo ici = null;
  107. foreach (ImageCodecInfo i in icis)
  108. {
  109. if ((i.MimeType == "image/jpeg") || (i.MimeType == "image/bmp") || (i.MimeType == "image/png") || (i.MimeType == "image/gif"))
  110. ici = i;
  111. }
  112. EncoderParameters ep = new EncoderParameters(1);
  113. ep.Param[0] = new EncoderParameter(Encoder.Quality, quality);
  114. //保存缩略图
  115. resultImage.Save(fileSaveUrl, ici, ep);
  116. //释放关键质量控制所用资源
  117. ep.Dispose();
  118. //释放缩略图资源
  119. resultG.Dispose();
  120. resultImage.Dispose();
  121. //释放原始图片资源
  122. initImage.Dispose();
  123. }
  124. }
  125. #endregion
  126. #region 自定义裁剪并缩放
  127. /// <summary>
  128. /// 指定长宽裁剪
  129. /// 按模版比例最大范围的裁剪图片并缩放至模版尺寸
  130. /// </summary>
  131. /// <param name="fromFile">原图Stream对象</param>
  132. /// <param name="fileSaveUrl">保存路径</param>
  133. /// <param name="maxWidth">最大宽(单位:px)</param>
  134. /// <param name="maxHeight">最大高(单位:px)</param>
  135. /// <param name="quality">质量(范围0-100)</param>
  136. public static void CutForCustom(this Stream fromFile, string fileSaveUrl, int maxWidth, int maxHeight, int quality)
  137. {
  138. //从文件获取原始图片,并使用流中嵌入的颜色管理信息
  139. Image initImage = Image.FromStream(fromFile, true);
  140. //原图宽高均小于模版,不作处理,直接保存
  141. if ((initImage.Width <= maxWidth) && (initImage.Height <= maxHeight))
  142. {
  143. initImage.Save(fileSaveUrl, ImageFormat.Jpeg);
  144. }
  145. else
  146. {
  147. //模版的宽高比例
  148. double templateRate = (double)maxWidth / maxHeight;
  149. //原图片的宽高比例
  150. double initRate = (double)initImage.Width / initImage.Height;
  151. //原图与模版比例相等,直接缩放
  152. if (templateRate == initRate)
  153. {
  154. //按模版大小生成最终图片
  155. Image templateImage = new Bitmap(maxWidth, maxHeight);
  156. Graphics templateG = Graphics.FromImage(templateImage);
  157. templateG.InterpolationMode = InterpolationMode.High;
  158. templateG.SmoothingMode = SmoothingMode.HighQuality;
  159. templateG.Clear(Color.White);
  160. templateG.DrawImage(initImage, new Rectangle(0, 0, maxWidth, maxHeight), new Rectangle(0, 0, initImage.Width, initImage.Height), GraphicsUnit.Pixel);
  161. templateImage.Save(fileSaveUrl, ImageFormat.Jpeg);
  162. }
  163. //原图与模版比例不等,裁剪后缩放
  164. else
  165. {
  166. //裁剪对象
  167. Image pickedImage;
  168. Graphics pickedG;
  169. //定位
  170. Rectangle fromR = new Rectangle(0, 0, 0, 0); //原图裁剪定位
  171. Rectangle toR = new Rectangle(0, 0, 0, 0); //目标定位
  172. //宽为标准进行裁剪
  173. if (templateRate > initRate)
  174. {
  175. //裁剪对象实例化
  176. pickedImage = new Bitmap(initImage.Width, (int)Math.Floor(initImage.Width / templateRate));
  177. pickedG = Graphics.FromImage(pickedImage);
  178. //裁剪源定位
  179. fromR.X = 0;
  180. fromR.Y = (int)Math.Floor((initImage.Height - initImage.Width / templateRate) / 2);
  181. fromR.Width = initImage.Width;
  182. fromR.Height = (int)Math.Floor(initImage.Width / templateRate);
  183. //裁剪目标定位
  184. toR.X = 0;
  185. toR.Y = 0;
  186. toR.Width = initImage.Width;
  187. toR.Height = (int)Math.Floor(initImage.Width / templateRate);
  188. }
  189. //高为标准进行裁剪
  190. else
  191. {
  192. pickedImage = new Bitmap((int)Math.Floor(initImage.Height * templateRate), initImage.Height);
  193. pickedG = Graphics.FromImage(pickedImage);
  194. fromR.X = (int)Math.Floor((initImage.Width - initImage.Height * templateRate) / 2);
  195. fromR.Y = 0;
  196. fromR.Width = (int)Math.Floor(initImage.Height * templateRate);
  197. fromR.Height = initImage.Height;
  198. toR.X = 0;
  199. toR.Y = 0;
  200. toR.Width = (int)Math.Floor(initImage.Height * templateRate);
  201. toR.Height = initImage.Height;
  202. }
  203. //设置质量
  204. pickedG.InterpolationMode = InterpolationMode.HighQualityBicubic;
  205. pickedG.SmoothingMode = SmoothingMode.HighQuality;
  206. //裁剪
  207. pickedG.DrawImage(initImage, toR, fromR, GraphicsUnit.Pixel);
  208. //按模版大小生成最终图片
  209. Image templateImage = new Bitmap(maxWidth, maxHeight);
  210. Graphics templateG = Graphics.FromImage(templateImage);
  211. templateG.InterpolationMode = InterpolationMode.High;
  212. templateG.SmoothingMode = SmoothingMode.HighQuality;
  213. templateG.Clear(Color.White);
  214. templateG.DrawImage(pickedImage, new Rectangle(0, 0, maxWidth, maxHeight), new Rectangle(0, 0, pickedImage.Width, pickedImage.Height), GraphicsUnit.Pixel);
  215. //关键质量控制
  216. //获取系统编码类型数组,包含了jpeg,bmp,png,gif,tiff
  217. ImageCodecInfo[] icis = ImageCodecInfo.GetImageEncoders();
  218. ImageCodecInfo ici = null;
  219. foreach (ImageCodecInfo i in icis)
  220. {
  221. if ((i.MimeType == "image/jpeg") || (i.MimeType == "image/bmp") || (i.MimeType == "image/png") || (i.MimeType == "image/gif"))
  222. ici = i;
  223. }
  224. EncoderParameters ep = new EncoderParameters(1);
  225. ep.Param[0] = new EncoderParameter(Encoder.Quality, quality);
  226. //保存缩略图
  227. templateImage.Save(fileSaveUrl, ici, ep);
  228. //templateImage.Save(fileSaveUrl, System.Drawing.Imaging.ImageFormat.Jpeg);
  229. //释放资源
  230. templateG.Dispose();
  231. templateImage.Dispose();
  232. pickedG.Dispose();
  233. pickedImage.Dispose();
  234. }
  235. }
  236. //释放资源
  237. initImage.Dispose();
  238. }
  239. #endregion
  240. #region 等比缩放
  241. /// <summary>
  242. /// 图片等比缩放
  243. /// </summary>
  244. /// <param name="fromFile">原图Stream对象</param>
  245. /// <param name="savePath">缩略图存放地址</param>
  246. /// <param name="targetWidth">指定的最大宽度</param>
  247. /// <param name="targetHeight">指定的最大高度</param>
  248. /// <param name="watermarkText">水印文字(为""表示不使用水印)</param>
  249. /// <param name="watermarkImage">水印图片路径(为""表示不使用水印)</param>
  250. public static void ZoomAuto(this Stream fromFile, string savePath, double targetWidth, double targetHeight, string watermarkText, string watermarkImage)
  251. {
  252. //创建目录
  253. string dir = Path.GetDirectoryName(savePath);
  254. if (!Directory.Exists(dir))
  255. Directory.CreateDirectory(dir);
  256. //原始图片(获取原始图片创建对象,并使用流中嵌入的颜色管理信息)
  257. Image initImage = Image.FromStream(fromFile, true);
  258. //原图宽高均小于模版,不作处理,直接保存
  259. if ((initImage.Width <= targetWidth) && (initImage.Height <= targetHeight))
  260. {
  261. //文字水印
  262. if (watermarkText != "")
  263. {
  264. using (Graphics gWater = Graphics.FromImage(initImage))
  265. {
  266. Font fontWater = new Font("黑体", 10);
  267. Brush brushWater = new SolidBrush(Color.White);
  268. gWater.DrawString(watermarkText, fontWater, brushWater, 10, 10);
  269. gWater.Dispose();
  270. }
  271. }
  272. //透明图片水印
  273. if (watermarkImage != "")
  274. {
  275. if (File.Exists(watermarkImage))
  276. {
  277. using (Image wrImage = Image.FromFile(watermarkImage))
  278. {
  279. //水印绘制条件:原始图片宽高均大于或等于水印图片
  280. if ((initImage.Width >= wrImage.Width) && (initImage.Height >= wrImage.Height))
  281. {
  282. Graphics gWater = Graphics.FromImage(initImage);
  283. //透明属性
  284. ImageAttributes imgAttributes = new ImageAttributes();
  285. ColorMap colorMap = new ColorMap();
  286. colorMap.OldColor = Color.FromArgb(255, 0, 255, 0);
  287. colorMap.NewColor = Color.FromArgb(0, 0, 0, 0);
  288. ColorMap[] remapTable = { colorMap };
  289. imgAttributes.SetRemapTable(remapTable, ColorAdjustType.Bitmap);
  290. float[][] colorMatrixElements =
  291. {
  292. new[] {1.0f, 0.0f, 0.0f, 0.0f, 0.0f},
  293. new[] {0.0f, 1.0f, 0.0f, 0.0f, 0.0f},
  294. new[] {0.0f, 0.0f, 1.0f, 0.0f, 0.0f},
  295. new[] {0.0f, 0.0f, 0.0f, 0.5f, 0.0f}, //透明度:0.5
  296. new[] {0.0f, 0.0f, 0.0f, 0.0f, 1.0f}
  297. };
  298. ColorMatrix wmColorMatrix = new ColorMatrix(colorMatrixElements);
  299. imgAttributes.SetColorMatrix(wmColorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
  300. gWater.DrawImage(wrImage, new Rectangle(initImage.Width - wrImage.Width, initImage.Height - wrImage.Height, wrImage.Width, wrImage.Height), 0, 0, wrImage.Width, wrImage.Height, GraphicsUnit.Pixel, imgAttributes);
  301. gWater.Dispose();
  302. }
  303. wrImage.Dispose();
  304. }
  305. }
  306. }
  307. //保存
  308. initImage.Save(savePath, ImageFormat.Jpeg);
  309. }
  310. else
  311. {
  312. //缩略图宽、高计算
  313. double newWidth = initImage.Width;
  314. double newHeight = initImage.Height;
  315. //宽大于高或宽等于高(横图或正方)
  316. if ((initImage.Width > initImage.Height) || (initImage.Width == initImage.Height))
  317. {
  318. //如果宽大于模版
  319. if (initImage.Width > targetWidth)
  320. {
  321. //宽按模版,高按比例缩放
  322. newWidth = targetWidth;
  323. newHeight = initImage.Height * (targetWidth / initImage.Width);
  324. }
  325. }
  326. //高大于宽(竖图)
  327. else
  328. {
  329. //如果高大于模版
  330. if (initImage.Height > targetHeight)
  331. {
  332. //高按模版,宽按比例缩放
  333. newHeight = targetHeight;
  334. newWidth = initImage.Width * (targetHeight / initImage.Height);
  335. }
  336. }
  337. //生成新图
  338. //新建一个bmp图片
  339. Image newImage = new Bitmap((int)newWidth, (int)newHeight);
  340. //新建一个画板
  341. Graphics newG = Graphics.FromImage(newImage);
  342. //设置质量
  343. newG.InterpolationMode = InterpolationMode.HighQualityBicubic;
  344. newG.SmoothingMode = SmoothingMode.HighQuality;
  345. //置背景色
  346. newG.Clear(Color.White);
  347. //画图
  348. newG.DrawImage(initImage, new Rectangle(0, 0, newImage.Width, newImage.Height), new Rectangle(0, 0, initImage.Width, initImage.Height), GraphicsUnit.Pixel);
  349. //文字水印
  350. if (watermarkText != "")
  351. {
  352. using (Graphics gWater = Graphics.FromImage(newImage))
  353. {
  354. Font fontWater = new Font("宋体", 10);
  355. Brush brushWater = new SolidBrush(Color.White);
  356. gWater.DrawString(watermarkText, fontWater, brushWater, 10, 10);
  357. gWater.Dispose();
  358. }
  359. }
  360. //透明图片水印
  361. if (watermarkImage != "")
  362. {
  363. if (File.Exists(watermarkImage))
  364. {
  365. using (Image wrImage = Image.FromFile(watermarkImage))
  366. {
  367. //水印绘制条件:原始图片宽高均大于或等于水印图片
  368. if ((newImage.Width >= wrImage.Width) && (newImage.Height >= wrImage.Height))
  369. {
  370. Graphics gWater = Graphics.FromImage(newImage);
  371. //透明属性
  372. ImageAttributes imgAttributes = new ImageAttributes();
  373. ColorMap colorMap = new ColorMap();
  374. colorMap.OldColor = Color.FromArgb(255, 0, 255, 0);
  375. colorMap.NewColor = Color.FromArgb(0, 0, 0, 0);
  376. ColorMap[] remapTable = { colorMap };
  377. imgAttributes.SetRemapTable(remapTable, ColorAdjustType.Bitmap);
  378. float[][] colorMatrixElements =
  379. {
  380. new[] {1.0f, 0.0f, 0.0f, 0.0f, 0.0f},
  381. new[] {0.0f, 1.0f, 0.0f, 0.0f, 0.0f},
  382. new[] {0.0f, 0.0f, 1.0f, 0.0f, 0.0f},
  383. new[] {0.0f, 0.0f, 0.0f, 0.5f, 0.0f}, //透明度:0.5
  384. new[] {0.0f, 0.0f, 0.0f, 0.0f, 1.0f}
  385. };
  386. ColorMatrix wmColorMatrix = new ColorMatrix(colorMatrixElements);
  387. imgAttributes.SetColorMatrix(wmColorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
  388. gWater.DrawImage(wrImage, new Rectangle(newImage.Width - wrImage.Width, newImage.Height - wrImage.Height, wrImage.Width, wrImage.Height), 0, 0, wrImage.Width, wrImage.Height, GraphicsUnit.Pixel, imgAttributes);
  389. gWater.Dispose();
  390. }
  391. wrImage.Dispose();
  392. }
  393. }
  394. }
  395. //保存缩略图
  396. newImage.Save(savePath, ImageFormat.Jpeg);
  397. //释放资源
  398. newG.Dispose();
  399. newImage.Dispose();
  400. initImage.Dispose();
  401. }
  402. }
  403. #endregion
  404. #region 判断文件类型是否为WEB格式图片
  405. /// <summary>
  406. /// 判断文件类型是否为WEB格式图片
  407. /// (注:JPG,GIF,BMP,PNG)
  408. /// </summary>
  409. /// <param name="contentType">HttpPostedFile.ContentType</param>
  410. /// <returns>是否为WEB格式图片</returns>
  411. public static bool IsWebImage(string contentType)
  412. {
  413. if ((contentType == "image/pjpeg") || (contentType == "image/jpeg") || (contentType == "image/gif") || (contentType == "image/bmp") || (contentType == "image/png"))
  414. return true;
  415. return false;
  416. }
  417. #endregion
  418. #region 裁剪图片
  419. /// <summary>
  420. /// 裁剪图片 -- 用GDI+
  421. /// </summary>
  422. /// <param name="b">原始Bitmap</param>
  423. /// <param name="rec">裁剪区域</param>
  424. /// <returns>剪裁后的Bitmap</returns>
  425. public static Bitmap CutImage(this Bitmap b, Rectangle rec)
  426. {
  427. if (b == null)
  428. return null;
  429. int w = b.Width;
  430. int h = b.Height;
  431. if ((rec.X >= w) || (rec.Y >= h))
  432. return null;
  433. if (rec.X + rec.Width > w)
  434. rec.Width = w - rec.X;
  435. if (rec.Y + rec.Height > h)
  436. rec.Height = h - rec.Y;
  437. try
  438. {
  439. Bitmap bmpOut = new Bitmap(rec.Width, rec.Height, PixelFormat.Format24bppRgb);
  440. Graphics g = Graphics.FromImage(bmpOut);
  441. g.DrawImage(b, new Rectangle(0, 0, rec.Width, rec.Height), new Rectangle(rec.X, rec.Y, rec.Width, rec.Height), GraphicsUnit.Pixel);
  442. g.Dispose();
  443. return bmpOut;
  444. }
  445. catch (Exception)
  446. {
  447. return null;
  448. }
  449. }
  450. #endregion
  451. #region 缩放图片
  452. /// <summary>
  453. /// Resize图片
  454. /// </summary>
  455. /// <param name="bmp">原始Bitmap </param>
  456. /// <param name="newWidth">新的宽度</param>
  457. /// <param name="newHeight">新的高度</param>
  458. /// <returns>处理以后的图片</returns>
  459. public static Bitmap ResizeImage(this Bitmap bmp, int newWidth, int newHeight)
  460. {
  461. try
  462. {
  463. Bitmap b = new Bitmap(newWidth, newHeight);
  464. Graphics g = Graphics.FromImage(b);
  465. // 插值算法的质量
  466. g.InterpolationMode = InterpolationMode.HighQualityBicubic;
  467. g.DrawImage(bmp, new Rectangle(0, 0, newWidth, newHeight), new Rectangle(0, 0, bmp.Width, bmp.Height), GraphicsUnit.Pixel);
  468. g.Dispose();
  469. return b;
  470. }
  471. catch (Exception)
  472. {
  473. return null;
  474. }
  475. }
  476. #endregion
  477. #region 裁剪并缩放
  478. /// <summary>
  479. /// 裁剪并缩放
  480. /// </summary>
  481. /// <param name="bmp">原始图片</param>
  482. /// <param name="rec">裁剪的矩形区域</param>
  483. /// <param name="newWidth">新的宽度</param>
  484. /// <param name="newHeight">新的高度</param>
  485. /// <returns>处理以后的图片</returns>
  486. public static Bitmap CutAndResize(this Bitmap bmp, Rectangle rec, int newWidth, int newHeight) => bmp.CutImage(rec).ResizeImage(newWidth, newHeight);
  487. #endregion
  488. #region 无损压缩图片
  489. /// <summary>
  490. /// 无损压缩图片
  491. /// </summary>
  492. /// <param name="sFile">原图片地址</param>
  493. /// <param name="dFile">压缩后保存图片地址</param>
  494. /// <param name="flag">压缩质量(数字越小压缩率越高)1-100</param>
  495. /// <param name="size">压缩后图片的最大大小</param>
  496. /// <param name="sfsc">是否是第一次调用</param>
  497. /// <returns></returns>
  498. public static bool CompressImage(string sFile, string dFile, int flag = 90, int size = 1024, bool sfsc = true)
  499. {
  500. //如果是第一次调用,原始图像的大小小于要压缩的大小,则直接复制文件,并且返回true
  501. FileInfo firstFileInfo = new FileInfo(sFile);
  502. if (sfsc && firstFileInfo.Length < size * 1024)
  503. {
  504. firstFileInfo.CopyTo(dFile);
  505. return true;
  506. }
  507. using (Image iSource = Image.FromFile(sFile))
  508. {
  509. ImageFormat tFormat = iSource.RawFormat;
  510. int dHeight = iSource.Height;
  511. int dWidth = iSource.Width;
  512. int sW, sH;
  513. //按比例缩放
  514. Size temSize = new Size(iSource.Width, iSource.Height);
  515. if (temSize.Width > dHeight || temSize.Width > dWidth)
  516. {
  517. if ((temSize.Width * dHeight) > (temSize.Width * dWidth))
  518. {
  519. sW = dWidth;
  520. sH = (dWidth * temSize.Height) / temSize.Width;
  521. }
  522. else
  523. {
  524. sH = dHeight;
  525. sW = (temSize.Width * dHeight) / temSize.Height;
  526. }
  527. }
  528. else
  529. {
  530. sW = temSize.Width;
  531. sH = temSize.Height;
  532. }
  533. using (Bitmap bmp = new Bitmap(dWidth, dHeight))
  534. {
  535. using (Graphics g = Graphics.FromImage(bmp))
  536. {
  537. g.Clear(Color.WhiteSmoke);
  538. g.CompositingQuality = CompositingQuality.HighQuality;
  539. g.SmoothingMode = SmoothingMode.HighQuality;
  540. g.InterpolationMode = InterpolationMode.HighQualityBicubic;
  541. g.DrawImage(iSource, new Rectangle((dWidth - sW) / 2, (dHeight - sH) / 2, sW, sH), 0, 0, iSource.Width, iSource.Height, GraphicsUnit.Pixel);
  542. }
  543. //以下代码为保存图片时,设置压缩质量
  544. using (EncoderParameters ep = new EncoderParameters())
  545. {
  546. long[] qy = new long[1];
  547. qy[0] = flag;//设置压缩的比例1-100
  548. using (EncoderParameter eParam = new EncoderParameter(Encoder.Quality, qy))
  549. {
  550. ep.Param[0] = eParam;
  551. try
  552. {
  553. ImageCodecInfo[] arrayIci = ImageCodecInfo.GetImageEncoders();
  554. ImageCodecInfo jpegIcIinfo = arrayIci.FirstOrDefault(t => t.FormatDescription.Equals("JPEG"));
  555. if (jpegIcIinfo != null)
  556. {
  557. bmp.Save(dFile, jpegIcIinfo, ep);//dFile是压缩后的新路径
  558. FileInfo fi = new FileInfo(dFile);
  559. if (fi.Length > 1024 * size)
  560. {
  561. flag = flag - 10;
  562. CompressImage(sFile, dFile, flag, size, false);
  563. }
  564. }
  565. else
  566. {
  567. bmp.Save(dFile, tFormat);
  568. }
  569. return true;
  570. }
  571. catch
  572. {
  573. return false;
  574. }
  575. }
  576. }
  577. }
  578. }
  579. }
  580. #endregion
  581. #region 缩略图
  582. /// <summary>
  583. /// 生成缩略图
  584. /// </summary>
  585. /// <param name="originalImage">原图</param>
  586. /// <param name="thumbnailPath">缩略图路径(物理路径)</param>
  587. /// <param name="width">缩略图宽度</param>
  588. /// <param name="height">缩略图高度</param>
  589. /// <param name="mode">生成缩略图的方式</param>
  590. public static void MakeThumbnail(this Image originalImage, string thumbnailPath, int width, int height, string mode)
  591. {
  592. int towidth = width;
  593. int toheight = height;
  594. int x = 0;
  595. int y = 0;
  596. int ow = originalImage.Width;
  597. int oh = originalImage.Height;
  598. switch (mode)
  599. {
  600. case "HW": //指定高宽缩放(可能变形)
  601. break;
  602. case "W": //指定宽,高按比例
  603. toheight = originalImage.Height * width / originalImage.Width;
  604. break;
  605. case "H": //指定高,宽按比例
  606. towidth = originalImage.Width * height / originalImage.Height;
  607. break;
  608. case "Cut": //指定高宽裁减(不变形)
  609. if (originalImage.Width / (double)originalImage.Height > towidth / (double)toheight)
  610. {
  611. oh = originalImage.Height;
  612. ow = originalImage.Height * towidth / toheight;
  613. y = 0;
  614. x = (originalImage.Width - ow) / 2;
  615. }
  616. else
  617. {
  618. ow = originalImage.Width;
  619. oh = originalImage.Width * height / towidth;
  620. x = 0;
  621. y = (originalImage.Height - oh) / 2;
  622. }
  623. break;
  624. }
  625. //新建一个bmp图片
  626. Image bitmap = new Bitmap(towidth, toheight);
  627. //新建一个画板
  628. Graphics g = Graphics.FromImage(bitmap);
  629. //设置高质量插值法
  630. g.InterpolationMode = InterpolationMode.High;
  631. //设置高质量,低速度呈现平滑程度
  632. g.SmoothingMode = SmoothingMode.HighQuality;
  633. //清空画布并以透明背景色填充
  634. g.Clear(Color.Transparent);
  635. //在指定位置并且按指定大小绘制原图片的指定部分
  636. //第一个:对哪张图片进行操作。
  637. //二:画多么大。
  638. //三:画那块区域。
  639. g.DrawImage(originalImage, new Rectangle(0, 0, towidth, toheight), new Rectangle(x, y, ow, oh), GraphicsUnit.Pixel);
  640. try
  641. {
  642. //以jpg格式保存缩略图
  643. bitmap.Save(thumbnailPath, ImageFormat.Jpeg);
  644. }
  645. finally
  646. {
  647. originalImage.Dispose();
  648. bitmap.Dispose();
  649. g.Dispose();
  650. }
  651. }
  652. #endregion
  653. #region 调整光暗
  654. /// <summary>
  655. /// 调整光暗
  656. /// </summary>
  657. /// <param name="mybm">原始图片</param>
  658. /// <param name="width">原始图片的长度</param>
  659. /// <param name="height">原始图片的高度</param>
  660. /// <param name="val">增加或减少的光暗值</param>
  661. public static Bitmap LDPic(this Bitmap mybm, int width, int height, int val)
  662. {
  663. Bitmap bm = new Bitmap(width, height); //初始化一个记录经过处理后的图片对象
  664. int x, y; //x、y是循环次数,后面三个是记录红绿蓝三个值的
  665. Color pixel;
  666. for (x = 0; x < width; x++)
  667. {
  668. for (y = 0; y < height; y++)
  669. {
  670. pixel = mybm.GetPixel(x, y); //获取当前像素的值
  671. var resultR = pixel.R + val; //x、y是循环次数,后面三个是记录红绿蓝三个值的
  672. var resultG = pixel.G + val; //x、y是循环次数,后面三个是记录红绿蓝三个值的
  673. var resultB = pixel.B + val; //x、y是循环次数,后面三个是记录红绿蓝三个值的
  674. bm.SetPixel(x, y, Color.FromArgb(resultR, resultG, resultB)); //绘图
  675. }
  676. }
  677. return bm;
  678. }
  679. #endregion
  680. #region 反色处理
  681. /// <summary>
  682. /// 反色处理
  683. /// </summary>
  684. /// <param name="mybm">原始图片</param>
  685. /// <param name="width">原始图片的长度</param>
  686. /// <param name="height">原始图片的高度</param>
  687. public static Bitmap RePic(this Bitmap mybm, int width, int height)
  688. {
  689. Bitmap bm = new Bitmap(width, height); //初始化一个记录处理后的图片的对象
  690. int x, y, resultR, resultG, resultB;
  691. Color pixel;
  692. for (x = 0; x < width; x++)
  693. {
  694. for (y = 0; y < height; y++)
  695. {
  696. pixel = mybm.GetPixel(x, y); //获取当前坐标的像素值
  697. resultR = 255 - pixel.R; //反红
  698. resultG = 255 - pixel.G; //反绿
  699. resultB = 255 - pixel.B; //反蓝
  700. bm.SetPixel(x, y, Color.FromArgb(resultR, resultG, resultB)); //绘图
  701. }
  702. }
  703. return bm;
  704. }
  705. #endregion
  706. #region 浮雕处理
  707. /// <summary>
  708. /// 浮雕处理
  709. /// </summary>
  710. /// <param name="oldBitmap">原始图片</param>
  711. /// <param name="width">原始图片的长度</param>
  712. /// <param name="height">原始图片的高度</param>
  713. public static Bitmap Relief(this Bitmap oldBitmap, int width, int height)
  714. {
  715. Bitmap newBitmap = new Bitmap(width, height);
  716. for (int x = 0; x < width - 1; x++)
  717. {
  718. for (int y = 0; y < height - 1; y++)
  719. {
  720. var color1 = oldBitmap.GetPixel(x, y);
  721. var color2 = oldBitmap.GetPixel(x + 1, y + 1);
  722. var r = Math.Abs(color1.R - color2.R + 128);
  723. var g = Math.Abs(color1.G - color2.G + 128);
  724. var b = Math.Abs(color1.B - color2.B + 128);
  725. if (r > 255) r = 255;
  726. if (r < 0) r = 0;
  727. if (g > 255) g = 255;
  728. if (g < 0) g = 0;
  729. if (b > 255) b = 255;
  730. if (b < 0) b = 0;
  731. newBitmap.SetPixel(x, y, Color.FromArgb(r, g, b));
  732. }
  733. }
  734. return newBitmap;
  735. }
  736. #endregion
  737. #region 拉伸图片
  738. /// <summary>
  739. /// 拉伸图片
  740. /// </summary>
  741. /// <param name="bmp">原始图片</param>
  742. /// <param name="newW">新的宽度</param>
  743. /// <param name="newH">新的高度</param>
  744. public static async Task<Bitmap> ResizeImageAsync(this Bitmap bmp, int newW, int newH)
  745. {
  746. try
  747. {
  748. using (Bitmap bap = new Bitmap(newW, newH))
  749. {
  750. return await Task.Run(() =>
  751. {
  752. using (Graphics g = Graphics.FromImage(bap))
  753. {
  754. g.InterpolationMode = InterpolationMode.HighQualityBicubic;
  755. g.DrawImage(bap, new Rectangle(0, 0, newW, newH), new Rectangle(0, 0, bap.Width, bap.Height), GraphicsUnit.Pixel);
  756. }
  757. return bap;
  758. }).ConfigureAwait(false);
  759. }
  760. }
  761. catch (Exception)
  762. {
  763. return null;
  764. }
  765. }
  766. #endregion
  767. #region 滤色处理
  768. /// <summary>
  769. /// 滤色处理
  770. /// </summary>
  771. /// <param name="mybm">原始图片</param>
  772. /// <param name="width">原始图片的长度</param>
  773. /// <param name="height">原始图片的高度</param>
  774. public static Bitmap FilPic(this Bitmap mybm, int width, int height)
  775. {
  776. using (Bitmap bm = new Bitmap(width, height)) //初始化一个记录滤色效果的图片对象
  777. {
  778. int x, y;
  779. Color pixel;
  780. for (x = 0; x < width; x++)
  781. {
  782. for (y = 0; y < height; y++)
  783. {
  784. pixel = mybm.GetPixel(x, y); //获取当前坐标的像素值
  785. bm.SetPixel(x, y, Color.FromArgb(0, pixel.G, pixel.B)); //绘图
  786. }
  787. }
  788. return bm;
  789. }
  790. }
  791. #endregion
  792. #region 左右翻转
  793. /// <summary>
  794. /// 左右翻转
  795. /// </summary>
  796. /// <param name="mybm">原始图片</param>
  797. /// <param name="width">原始图片的长度</param>
  798. /// <param name="height">原始图片的高度</param>
  799. public static Bitmap RevPicLR(this Bitmap mybm, int width, int height)
  800. {
  801. using (Bitmap bm = new Bitmap(width, height))
  802. {
  803. int x, y, z; //x,y是循环次数,z是用来记录像素点的x坐标的变化的
  804. Color pixel;
  805. for (y = height - 1; y >= 0; y--)
  806. {
  807. for (x = width - 1, z = 0; x >= 0; x--)
  808. {
  809. pixel = mybm.GetPixel(x, y); //获取当前像素的值
  810. bm.SetPixel(z++, y, Color.FromArgb(pixel.R, pixel.G, pixel.B)); //绘图
  811. }
  812. }
  813. return bm;
  814. }
  815. }
  816. #endregion
  817. #region 上下翻转
  818. /// <summary>
  819. /// 上下翻转
  820. /// </summary>
  821. /// <param name="mybm">原始图片</param>
  822. /// <param name="width">原始图片的长度</param>
  823. /// <param name="height">原始图片的高度</param>
  824. public static Bitmap RevPicUD(this Bitmap mybm, int width, int height)
  825. {
  826. Bitmap bm = new Bitmap(width, height);
  827. using (bm)
  828. {
  829. int x, y, z;
  830. Color pixel;
  831. for (x = 0; x < width; x++)
  832. {
  833. for (y = height - 1, z = 0; y >= 0; y--)
  834. {
  835. pixel = mybm.GetPixel(x, y); //获取当前像素的值
  836. bm.SetPixel(x, z++, Color.FromArgb(pixel.R, pixel.G, pixel.B)); //绘图
  837. }
  838. }
  839. return bm;
  840. }
  841. }
  842. #endregion
  843. #region 压缩图片
  844. /// <summary>
  845. /// 压缩到指定尺寸
  846. /// </summary>
  847. /// <param name="img"></param>
  848. /// <param name="newfile">新文件</param>
  849. public static bool Compress(this Image img, string newfile)
  850. {
  851. try
  852. {
  853. Size newSize = new Size(100, 125);
  854. Bitmap outBmp = new Bitmap(newSize.Width, newSize.Height);
  855. Graphics g = Graphics.FromImage(outBmp);
  856. g.CompositingQuality = CompositingQuality.HighQuality;
  857. g.SmoothingMode = SmoothingMode.HighQuality;
  858. g.InterpolationMode = InterpolationMode.HighQualityBicubic;
  859. g.DrawImage(img, new Rectangle(0, 0, newSize.Width, newSize.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel);
  860. g.Dispose();
  861. var encoderParams = new EncoderParameters();
  862. var quality = new long[1];
  863. quality[0] = 100;
  864. encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, quality);
  865. ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders();
  866. ImageCodecInfo jpegICI = null;
  867. for (int x = 0; x < arrayICI.Length; x++)
  868. {
  869. if (arrayICI[x].FormatDescription.Equals("JPEG"))
  870. {
  871. jpegICI = arrayICI[x]; //设置JPEG编码
  872. break;
  873. }
  874. }
  875. if (jpegICI != null) outBmp.Save(newfile, ImageFormat.Jpeg);
  876. outBmp.Dispose();
  877. return true;
  878. }
  879. catch (Exception)
  880. {
  881. return false;
  882. }
  883. }
  884. #endregion
  885. #region 图片灰度化
  886. /// <summary>
  887. /// 图片灰度化
  888. /// </summary>
  889. /// <param name="c">输入颜色</param>
  890. /// <returns>输出颜色</returns>
  891. public static Color Gray(this Color c)
  892. {
  893. int rgb = Convert.ToInt32(0.3 * c.R + 0.59 * c.G + 0.11 * c.B);
  894. return Color.FromArgb(rgb, rgb, rgb);
  895. }
  896. #endregion
  897. #region 转换为黑白图片
  898. /// <summary>
  899. /// 转换为黑白图片
  900. /// </summary>
  901. /// <param name="mybm">要进行处理的图片</param>
  902. /// <param name="width">图片的长度</param>
  903. /// <param name="height">图片的高度</param>
  904. public static Bitmap BWPic(this Bitmap mybm, int width, int height)
  905. {
  906. Bitmap bm = new Bitmap(width, height);
  907. using (bm)
  908. {
  909. int x, y, result; //x,y是循环次数,result是记录处理后的像素值
  910. Color pixel;
  911. for (x = 0; x < width; x++)
  912. {
  913. for (y = 0; y < height; y++)
  914. {
  915. pixel = mybm.GetPixel(x, y); //获取当前坐标的像素值
  916. result = (pixel.R + pixel.G + pixel.B) / 3; //取红绿蓝三色的平均值
  917. bm.SetPixel(x, y, Color.FromArgb(result, result, result));
  918. }
  919. }
  920. return bm;
  921. }
  922. }
  923. #endregion
  924. #region 获取图片中的各帧
  925. /// <summary>
  926. /// 获取图片中的各帧
  927. /// </summary>
  928. /// <param name="gif">源gif</param>
  929. /// <param name="pSavedPath">保存路径</param>
  930. public static void GetFrames(this Image gif, string pSavedPath)
  931. {
  932. using (gif)
  933. {
  934. FrameDimension fd = new FrameDimension(gif.FrameDimensionsList[0]);
  935. int count = gif.GetFrameCount(fd); //获取帧数(gif图片可能包含多帧,其它格式图片一般仅一帧)
  936. for (int i = 0; i < count; i++) //以Jpeg格式保存各帧
  937. {
  938. gif.SelectActiveFrame(fd, i);
  939. gif.Save(pSavedPath + "\\frame_" + i + ".jpg", ImageFormat.Jpeg);
  940. }
  941. }
  942. }
  943. #endregion
  944. /// <summary>
  945. /// 将dataUri保存为图片
  946. /// </summary>
  947. /// <param name="source">dataUri数据源</param>
  948. /// <returns></returns>
  949. /// <exception cref="Exception">操作失败。</exception>
  950. public static Bitmap SaveDataUriAsImageFile(this string source)
  951. {
  952. string strbase64 = source.Substring(source.IndexOf(',') + 1);
  953. strbase64 = strbase64.Trim('\0');
  954. Bitmap bmp2;
  955. byte[] arr = Convert.FromBase64String(strbase64);
  956. using (var ms = new MemoryStream(arr))
  957. {
  958. var bmp = new Bitmap(ms);
  959. //新建第二个bitmap类型的bmp2变量。
  960. bmp2 = new Bitmap(bmp, bmp.Width, bmp.Height);
  961. //将第一个bmp拷贝到bmp2中
  962. Graphics draw = Graphics.FromImage(bmp2);
  963. using (draw)
  964. {
  965. draw.DrawImage(bmp, 0, 0, bmp.Width, bmp.Height);
  966. }
  967. }
  968. return bmp2;
  969. }
  970. /// <summary>
  971. /// 上传图片到百度图床
  972. /// </summary>
  973. /// <param name="stream"></param>
  974. /// <returns></returns>
  975. public static async Task<string> UploadImageAsync(Stream stream)
  976. {
  977. using (HttpClient httpClient = new HttpClient()
  978. {
  979. BaseAddress = new Uri("https://sm.ms"),
  980. })
  981. {
  982. httpClient.DefaultRequestHeaders.UserAgent.Add(ProductInfoHeaderValue.Parse("Mozilla/5.0"));
  983. using (var bc = new StreamContent(stream))
  984. {
  985. bc.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
  986. {
  987. FileName = "1.jpg",
  988. Name = "smfile"
  989. };
  990. bc.Headers.ContentType = MediaTypeHeaderValue.Parse("image/jpeg");
  991. using (var content = new MultipartFormDataContent { bc })
  992. {
  993. return await await httpClient.PostAsync("/api/upload", content).ContinueWith(async t =>
  994. {
  995. if (t.IsCanceled || t.IsFaulted)
  996. {
  997. Console.WriteLine("发送请求出错了" + t.Exception);
  998. return string.Empty;
  999. }
  1000. var res = await t;
  1001. if (res.IsSuccessStatusCode)
  1002. {
  1003. string s = await res.Content.ReadAsStringAsync();
  1004. //var token = JObject.Parse(s);
  1005. //if ((int)token["errno"] == 0)
  1006. //{
  1007. // s = (string)token["data"]["imageUrl"];
  1008. // return s;
  1009. //}
  1010. //s = (string)token["errmsg"];
  1011. return s;
  1012. }
  1013. return string.Empty;
  1014. });
  1015. }
  1016. }
  1017. }
  1018. }
  1019. } //end class
  1020. }