標籤:style blog color 使用 檔案 width
最近在做圖片上傳功能,類似於朋友圈的功能,現在的手機像素都比較高,手機上的圖片一般都比較大(幾M),對於大圖,在上傳之前,我們需要對圖片進行壓縮(解析度和品質),再上傳到伺服器,以減少網路流量傳輸
實現思路:
判斷圖片是否大於指定的大小
否:原圖上傳
是:通過BitmapImage檢測出圖片解析度,然後將解析度限制在1200*1200解析度以內(保持寬高比),然後通過SaveJpeg方法寫入到流中
筆者測試,絕大部分圖片處理後都能控制在300kb以內(部分超過一點)
using System;using System.IO;using System.Windows;using System.Windows.Controls;using System.Windows.Media.Imaging;namespace XTuOne.Utility.Helpers{ public class ImageHelper { /// <summary> /// 壓縮圖片 /// </summary> /// <param name="imageStream">輸入</param> /// <param name="quality">壓縮品質</param> /// <param name="maxKb">最大大小(單位kb)只供參考</param> public static Stream CompressImage(Stream imageStream, int quality = 80, int maxKb = 300) { if (imageStream.Length > 300*1024) { if (imageStream.CanSeek) { imageStream.Seek(0, SeekOrigin.Begin); } var bitmapImage = new BitmapImage(); bitmapImage.SetSource(imageStream); var writeableBitmap = new WriteableBitmap(bitmapImage); var tempStreamm = new MemoryStream(); var size = GetSize(bitmapImage.PixelWidth, bitmapImage.PixelHeight); writeableBitmap.SaveJpeg(tempStreamm, (int)size.Width, (int)size.Height, 0, 80); return tempStreamm; } return imageStream; } private static Size GetSize(Size size) { return GetSize(size.Width, size.Height); } private static Size GetSize(double width, double height) { if (width > height) { if (width > 1200) { return new Size(1200, Convert.ToInt32(height * 1200 / width)); } return new Size(width, height); } else { if (height > 1200) { return new Size(Convert.ToInt32(width * 1200 / height), 1200); } return new Size(width, height); } } }}
測試中發現一個問題:如果圖片太大(5000*5000)的話,BitmapImage讀取出來的寬高會被限制在4096*4096之內,如果超過4096,則取4096,保持寬高比,所以如果圖片過大,通過BitmapImage是無法擷取到圖片的真實解析度的
下面示範讀取SavePicture檔案夾中的圖片,並進行壓縮
var library = new MediaLibrary(); foreach (var savedPicture in library.SavedPictures) { using (var stream = savedPicture.GetImage()) { using (var tempStream = ImageHelper.CompressImage(stream)) { Debug.WriteLine("圖片壓縮前大小:{0:f2}kb, 圖片壓縮後大小:{1:f2}kb", stream.Length/1024.0, tempStream.Length/1024.0); } GC.Collect(); } }
注意:對圖片的處理(特別是比較大的圖片)很容易造成記憶體不足的情況(筆者在測試的時候,處理到第三張圖片(比較大的圖片5-10M)的時候就會出現記憶體不足的情況)
所以在使用的時候,沒用的Stream應該及時釋放掉(using),如果有多張圖片需要處理
為了防止記憶體不足造成異常,可以通過延遲處理,在處理完一張圖片後,等待100毫秒,然後繼續
//延遲0.1秒 await Task.Delay(100);