圖片縮放的相關處理
最近自己做的點東西上用到了圖片的處理,不過沒有找到合適的圖片處理相關算法,倒是找到了幾個獲取縮略圖的算法。代碼不長,簡單看了看原理也比較簡單(其實不是簡單是C#的封裝的太多了,所以顯得比較簡單)。既然沒有相關的統一調用的代碼,索性,我來整理一套相關的處理代碼然後公開出來吧。
圖片處理的相關分析
其實我要用的圖片處理非常簡單,就是簡單的壓縮一下圖片。然後把圖片設置到對應大小而已。但是對於設置的方式,C#基礎的函數中使用的Rect范圍設置。這個范圍設置計算起來可能相對頭疼一些。所以我在考慮要不要讓調用者在忽略Rect這個參數的情況愉快的調用接口呢?於是乎,我定義了幾個圖片縮放類型(Full、Zoom、Overflow、Original)。然後默認的讓原始圖片的中心點與輸出圖片的中心點對齊。然後根據縮放類型來對圖片進行不同的縮放模式。
縮放模式
調用的范例
ImageHelper.GetInstance().ImageCompress(InputFile, Path.Combine(OutPutPath, item_file), new System.Drawing.Size(500, 300), ImageZoomType.Full, 50);
樣品展示
原始圖片
Full 300*500
Full 500 * 300
Original 300 * 500
Original 500 * 300
Overflow 300 * 500
Overflow 500 * 300
Zoom 300 * 500
Zoom 500 * 300
存在的不足
後續的內容
圖片處理不光是縮放,還有其他的很多東西比較實用(截圖、壓縮、按高縮放、按寬縮放、添加水印、添加隱藏水印),我准備把圖片常用的相關處理。整理成一個幫助類,方便遷入到各個項目中去。
所以我建立了一個專門的圖片處理的開源項目方便後續功能加入,地址如下:http://git.oschina.net/anxin1225/ImageCompress
壓縮相關的代碼
using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ImageCompress { public struct AnchorPoint { //public AnchorPoint() : this(0, 0) { } public AnchorPoint(double x, double y) { X = x; Y = y; } public double X, Y; } public enum ImageZoomType { Full, Zoom, Overflow, Original, } public delegate void ImageHandle(Image image, Bitmap bitmap); public class ImageHelper { private ImageHelper() { } private static ImageHelper _image_helper = null; private Dictionary<ImageZoomType, ImageHandle> _name_to_handle = new Dictionary<ImageZoomType, ImageHandle>(); public static ImageHelper GetInstance() { if (_image_helper == null) { _image_helper = new ImageHelper(); //填滿 _image_helper._name_to_handle[ImageZoomType.Full] = (image, bitmap) => { _image_helper.DrawImage(image, bitmap, new Rectangle(new Point(0, 0), bitmap.Size)); }; //原始 _image_helper._name_to_handle[ImageZoomType.Original] = (image, bitmap) => { _image_helper.DrawImage(image, bitmap, 1, new AnchorPoint(0.5, 0.5), new AnchorPoint(0.5, 0.5)); }; //溢出 _image_helper._name_to_handle[ImageZoomType.Overflow] = (image, bitmap) => { float proportion_x = (float)bitmap.Width / image.Width; float proportion_y = (float)bitmap.Height / image.Height; _image_helper.DrawImage(image, bitmap, proportion_x > proportion_y ? proportion_x : proportion_y, new AnchorPoint(0.5, 0.5), new AnchorPoint(0.5, 0.5)); }; //縮放 _image_helper._name_to_handle[ImageZoomType.Zoom] = (image, bitmap) => { float proportion_x = (float)bitmap.Width / image.Width; float proportion_y = (float)bitmap.Height / image.Height; _image_helper.DrawImage(image, bitmap, proportion_x < proportion_y ? proportion_x : proportion_y, new AnchorPoint(0.5, 0.5), new AnchorPoint(0.5, 0.5)); }; } return _image_helper; } /// <summary> /// 壓縮圖片 /// </summary> /// <param name="source_path">源數據位置</param> /// <param name="save_path">保存數據位置</param> /// <param name="save_size">保存圖片大小</param> /// <param name="ztype">縮放模式</param> /// <param name="flag">圖片保存品質</param> /// <returns>是否完成壓縮</returns> public bool ImageCompress(string source_path, string save_path, Size save_size, ImageZoomType ztype, int flag) { bool success = false; Image source = null; while (true) { source = LoadImage(source_path); if (source == null) break; Bitmap bitmap = new Bitmap(save_size.Width, save_size.Height); if (_name_to_handle.ContainsKey(ztype)) { _name_to_handle[ztype](source, bitmap); } else { break; } success = SaveImage(bitmap, save_path, source.RawFormat, flag); break; } if (source != null) source.Dispose(); return success; } public Image LoadImage(string source_path) { Image image = null; while (true) { if (!File.Exists(source_path)) break; try { image = Image.FromFile(source_path); } catch { break; } break; } return image; } /// <summary> /// 將BitMap保存到磁盤上 /// </summary> /// <param name="image">需要保存的圖片</param> /// <param name="save_path">保存的路徑</param> /// <param name="format">保存格式</param> /// <param name="flag">保存質量</param> /// <returns></returns> public bool SaveImage(Bitmap image, string save_path, ImageFormat format, int flag) { //以下代碼為保存圖片時,設置壓縮質量 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) { image.Save(save_path, jpegICIinfo, ep);//dFile是壓縮後的新路徑 } else { image.Save(save_path, format); } return true; } catch { return false; } finally { image.Dispose(); } } /// <summary> /// 畫圖 /// </summary> /// <param name="source">原始圖像</param> /// <param name="output">輸出圖像</param> /// <param name="souce_scale">原始圖像的縮放值</param> /// <param name="souce_anchor"></param> /// <param name="graphics_anchor"></param> public void DrawImage(Image source, Bitmap output, float souce_scale, AnchorPoint souce_anchor, AnchorPoint graphics_anchor) { DrawImage(source, output, souce_scale, souce_anchor, new Point((int)(output.Width * graphics_anchor.X), (int)(output.Height * graphics_anchor.Y))); } /// <summary> /// 畫圖 /// </summary> /// <param name="source">原始圖像</param> /// <param name="output">輸出凸顯</param> /// <param name="source_scale">圖像的所放值</param> /// <param name="source_anchor">源圖像錨點</param> /// <param name="souce_point">圖像位置</param> public void DrawImage(Image source, Bitmap output, float source_scale, AnchorPoint source_anchor, Point souce_point) { var pic_po = new Point((int)(souce_point.X - source.Size.Width * source_scale * source_anchor.X), (int)(souce_point.Y - source.Size.Height * source_scale * source_anchor.Y)); DrawImage(source, output, new Rectangle(pic_po, new Size((int)(source.Width * source_scale), (int)(source.Height * source_scale)))); } /// <summary> /// 畫圖 /// </summary> /// <param name="source"></param> /// <param name="output"></param> /// <param name="rect"></param> public void DrawImage(Image source, Bitmap output, Rectangle rect) { Graphics g = Graphics.FromImage(output); g.Clear(Color.WhiteSmoke); g.CompositingQuality = CompositingQuality.HighQuality; g.SmoothingMode = SmoothingMode.HighQuality; g.InterpolationMode = InterpolationMode.HighQualityBicubic; g.DrawImage(source, rect, 0, 0, source.Width, source.Height, GraphicsUnit.Pixel); g.Dispose(); } } }
PS:為了美觀本文中的原始圖片並不是原始圖片,因為原始圖片太大了。會造成頁面滑動,所以我上傳了一張較小的圖片。Git的圖片則是原始的圖片