一、背景
最近段時間,開發寫值工具項目中,出現圖片加載問題API,響應時間緩慢;為了優化圖片加載問題,我進行圖片壓縮方法,然后API的圖片加載還是慢,最終在自己無意中亂寫找到了根本的原因。
二、問題
優化圖片加載問題
三、原因
1. 在API中,圖片轉換byte[ ]方法,用BMP的格式圖片導致的API圖片加載很慢;
returnImage.Save(mstream2, System.Drawing.Imaging.ImageFormat.Bmp);
2. BMP 不支持壓縮,這會造成文件非常大
四、解決方法
1. 壓縮高質量圖片
① 這個壓縮圖片方法加載更快,
//無損壓縮圖片 public Image GetImageThumbnail(Image image, double scaleFactor = 0.3) { using (image) { var newWidth = (int)(image.Width * scaleFactor); var newHeight = (int)(image.Height * scaleFactor); var thumbnailImg = new Bitmap(newWidth, newHeight); var thumbGraph = Graphics.FromImage(thumbnailImg); thumbGraph.CompositingQuality = CompositingQuality.HighQuality; thumbGraph.SmoothingMode = SmoothingMode.HighQuality; thumbGraph.InterpolationMode = InterpolationMode.HighQualityBicubic; var imageRectangle = new Rectangle(0, 0, newWidth, newHeight); thumbGraph.DrawImage(image, imageRectangle); return thumbnailImg; } }
② 壓縮圖片方法比①慢很多

/// <summary> /// 無損壓縮圖片 /// </summary> /// <param name="sFile">原圖片地址</param> /// <param name="dFile">壓縮后保存圖片地址</param> /// <param name="flag">壓縮質量(數字越小壓縮率越高)1-100</param> /// <param name="size">壓縮后圖片的最大大小</param> /// <param name="sfsc">是否是第一次調用</param> /// <returns></returns> public Image CompressImage(Image iSource, Stream stream, int flag = 90, int size = 300, bool sfsc = true) { //Image iSource = Image.FromFile(sFile); ImageFormat tFormat = iSource.RawFormat; ////如果是第一次調用,原始圖像的大小小於要壓縮的大小,則直接復制文件,並且返回true //FileInfo firstFileInfo = new FileInfo(sFile); //if (sfsc == true && firstFileInfo.Length < size * 1024) //{ // firstFileInfo.CopyTo(dFile); // return true; //} int dHeight = iSource.Height / 2; int dWidth = iSource.Width / 2; int sW = 0, sH = 0; //按比例縮放 Size tem_size = new Size(iSource.Width, iSource.Height); if (tem_size.Width > dHeight || tem_size.Width > dWidth) { if ((tem_size.Width * dHeight) > (tem_size.Width * dWidth)) { sW = dWidth; sH = (dWidth * tem_size.Height) / tem_size.Width; } else { sH = dHeight; sW = (tem_size.Width * dHeight) / tem_size.Height; } } else { sW = tem_size.Width; sH = tem_size.Height; } var ob = new Bitmap(dWidth, dHeight); Graphics g = Graphics.FromImage(ob); g.Clear(Color.WhiteSmoke); g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; g.DrawImage(iSource, new Rectangle((dWidth - sW) / 2, (dHeight - sH) / 2, sW, sH), 0, 0, iSource.Width, iSource.Height, GraphicsUnit.Pixel); g.Dispose(); //以下代碼為保存圖片時,設置壓縮質量 EncoderParameters ep = new EncoderParameters(); long[] qy = new long[1]; qy[0] = flag;//設置壓縮的比例1-100 EncoderParameter eParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy); ep.Param[0] = eParam; try { ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders(); ImageCodecInfo jpegICIinfo = null; for (int x = 0; x < arrayICI.Length; x++) { if (arrayICI[x].FormatDescription.Equals("JPEG")) { jpegICIinfo = arrayICI[x]; break; } } if (jpegICIinfo != null) { ob.Save(stream, jpegICIinfo, ep);//dFile是壓縮后的新路徑 ///FileInfo fi = new FileInfo(); //if (fi.Length > 1024 * size) //{ // flag = flag - 10; // CompressImage(iSource, stream, flag, size, false); //} } else { ob.Save(stream, tFormat); } //return true; return ob; } catch { return ob; } //finally //{ // iSource.Dispose(); // //ob.Dispose(); //} }
2. API中,用JPEG的格式
//二進制轉換圖片的方法 MemoryStream mstream = new MemoryStream(assetinfor.imagedate);
Image imadate = Image.FromStream(mstream); var returnImage = assetinfor.GetImageThumbnail(imadate);
//圖片再轉換byte[]方法 MemoryStream mstream2 = new MemoryStream(); //var returnImage = assetinfor.CompressImage(imadate, mstream2); //returnImage.Save(mstream2, System.Drawing.Imaging.ImageFormat.Bmp); returnImage.Save(mstream2, System.Drawing.Imaging.ImageFormat.Jpeg); byte[] byData = new Byte[mstream2.Length]; mstream2.Position = 0; mstream2.Read(byData, 0, byData.Length); mstream2.Close(); this.images = Convert.ToBase64String(byData);
//釋放資源 mstream.Dispose(); mstream2.Dispose(); } /// <summary> /// 圖片 /// </summary> public string images { get; set; }
3. JPEG的圖片格式支持高級壓縮
五、C#中image和byte[ ]的互相轉換
1、如圖所示,項目中所應用到的轉換;
2. image和byte[ ]的互相轉換
① 參數是圖片路徑:返回Byte[]類型
//參數是圖片的路徑 public byte[] GetPictureData(string imagePath) { FileStream fs = new FileStream(imagePath, FileMode.Open); byte[] byteData = new byte[fs.Length]; fs.Read(byteData, 0, byteData.Length); fs.Close(); return byteData; }
② 參數類型是Image對象,返回Byte[]類型
//將Image轉換成流數據,並保存為byte[] public byte[] PhotoImageInsert(System.Drawing.Image imgPhoto) { MemoryStream mstream = new MemoryStream(); imgPhoto.Save(mstream, System.Drawing.Imaging.ImageFormat.Bmp); byte[] byData = new Byte[mstream.Length]; mstream.Position = 0; mstream.Read(byData, 0, byData.Length); mstream.Close(); return byData; }
③ 參數是Byte[]類型,返回值是Image對象
public System.Drawing.Image ReturnPhoto(byte[] streamByte) { System.IO.MemoryStream ms = new System.IO.MemoryStream(streamByte); System.Drawing.Image img = System.Drawing.Image.FromStream(ms); return img; }
④ 參數是Byte[] 類型,沒有返回值(ASP.NET輸出圖片)
public void WritePhoto(byte[] streamByte) { // Response.ContentType 的默認值為默認值為“text/html” Response.ContentType = "image/GIF"; //圖片輸出的類型有: image/GIF image/JPEG Response.BinaryWrite(streamByte);
}
六、GIF,JPG, BMP和JPEG的圖片有什么區別
① BMP:Windows 位圖
詳細說明:Windows 位圖可以用任何顏色深度(從黑白到 24 位顏色)存儲單個光柵圖像。Windows 位圖文件格式與其他 Microsoft Windows 程序兼容,BMP 文件適用於 Windows 中的牆紙。
缺點:BMP 不支持壓縮,這會造成文件非常大,BMP 文件不受 Web 瀏覽器支持。
優點:BMP 支持 1 位到 24 位顏色深度,BMP 格式與現有 Windows 程序(尤其是較舊的程序)廣泛兼容。
② PNG:可移植網絡圖形
詳細說明:PNG 圖片以任何顏色深度存儲單個光柵圖像。PNG 是與平台無關的格式。
優點:PNG 支持高級別無損耗壓縮; PNG 支持 alpha 通道透明度; PNG 支持伽瑪校正; PNG 支持交錯; PNG 接受最新的 Web 瀏覽器支持。
缺點: 較舊的瀏覽器和程序可能不支持 PNG 文件。 作為 Internet 文件格式,與 JPEG 的有損耗壓縮相比,PNG 提供的壓縮量較少。 作為 Internet 文件格式,PNG 對多圖像文件或動畫文件不提供任何支持。GIF 格式支持多圖像文件和動畫文件。
③ JPEG:聯合攝影專家組
詳細說明:JPEG 圖片以 24 位顏色存儲單個光柵圖像。JPEG 是與平台無關的格式,支持最高級別的壓縮,不過,這種壓縮是有損耗的。漸近式 JPEG 文件支持交錯。可以提高或降低 JPEG 文件壓縮的級別。但是,文件大小是以圖像質量為代價的。壓縮比率可以高達 100:1。(JPEG 格式可在 10:1 到 20:1 的比率下輕松地壓縮文件,而圖片質量不會下降。)JPEG 壓縮可以很好地處理寫實攝影作品。
優點:攝影作品或寫實作品支持高級壓縮。 利用可變的壓縮比可以控制文件大小。 支持交錯(對於漸近式 JPEG 文件)。 JPEG 廣泛支持 Internet 標准。
缺點:有損耗壓縮會使原始圖片數據質量下降。 當您編輯和重新保存 JPEG 文件時,JPEG 會混合原始圖片數據的質量下降。這種下降是累積性的。 JPEG 不適用於所含顏色很少、具有大塊顏色相近的區域或亮度差異十分明顯的較簡單的圖片
④ GIF:圖形交換格式
詳細說明:GIF 圖片以 8 位顏色或 256 色存儲單個光柵圖像數據或多個光柵圖像數據。GIF 圖 片支持透明度、壓縮、交錯和多圖像圖片(動畫 GIF)。GIF 透明度不是 alpha 通道透明度,不能支持半透明效果。GIF 壓縮是 LZW 壓縮,壓縮比大概為 3:1。GIF 文件規范的 GIF89a 版本中支持動畫 GIF。
優點: GIF 廣泛支持 Internet 標准。 支持無損耗壓縮和透明度。 動畫 GIF 很流行,易於使用許多 GIF 動畫程序創建。
缺點: GIF 只支持 256 色調色板,因此,詳細的圖片和寫實攝影圖像會丟失顏色信息,而看起來卻是經過調色的。 在大多數情況下,無損耗壓縮效果不如 JPEG 格式或 PNG 格式。 GIF 支持有限的透明度,沒有半透明效果或褪色效果(例如,alpha 通道透明度提供的效果)。