頭像裁剪是一個經常用到的功能,實現原理也較為簡單,就是在本地選擇好所需裁剪圖片的坐標,將坐標發送到服務器,由服務器執行圖片裁剪操作。
jQuery插件Jcrop提供了強大的圖片裁剪坐標選擇插件。一下來介紹它的用法。本處采用了AJAX本地上傳一張圖片的方法讓用戶裁剪。很多驗證沒有做,因為作為一個關於Jcrop的例子,很多驗證不如與本文研究的范疇。服務器端采用MVC3實現。
直接貼代碼,詳解注釋里面有了。
一、前台頁面代碼。
<link href="http://www.cnblogs.com/Content/jquery.Jcrop.css" rel="stylesheet" type="text/css" /> <script src="http://www.cnblogs.com/Content/jquery-1.7.1.js" type="text/javascript"></script> <script src="http://www.cnblogs.com/Content/ajaxfileupload.js" type="text/javascript"></script> <script src="http://www.cnblogs.com/Content/jquery.Jcrop.js" type="text/javascript"></script> <script type="text/javascript"> $(function () { $(":button").click(function () { //當點擊上傳按鈕時,AJAX上傳圖片到服務器 ajaxFileUpload(); }) }) //當裁剪框變動時,將左上角相對圖片的X坐標與Y坐標,寬度以及高度放到<input type="hidden">中(上傳到服務器上裁剪會用到) function showCoords(c) { $("#p1").text(c.x + " " + c.y + " " + c.w + " " + c.h ); $("#x1").val(c.x); $("#y1").val(c.y); $("#cw").val(c.w); $("#ch").val(c.h); } //當AJAX上傳圖片操作 function ajaxFileUpload() { $.ajaxFileUpload ( { url: '/uploadandcut/upload?action=up', //用於文件上傳的服務器端請求地址up參數標記此次是上傳操作還是裁剪操作 secureuri: false, //一般設置為false,是否安全上傳 fileElementId: 'file1', //文件上傳控件的id屬性 <input type="file" id="file" name="file" /> dataType: 'json', //返回值類型 一般設置為json 期望服務器傳回的數據類型 success: function (data, status) //服務器成功響應處理函數 { //上傳成功后在將服務器上剛剛上傳的圖片顯示在img1上 $("#img1").attr("src", data.imgurl); if (typeof (data.error) != 'undefined') { if (data.error != '') { alert(data.error); } else { alert(data.msg); } } //同時啟動裁剪操作,觸發裁剪框顯示,讓用戶選擇圖片區域 $("#img1").Jcrop({ bgColor: 'black', bgOpacity: .4, setSelect: [100, 100, 150,150], //設定4個角的初始位置 aspectRatio: 1 / 1, onChange: showCoords, //當裁剪框變動時執行的函數 onSelect: showCoords, //當選擇完成時執行的函數 }); }, error: function (data, status, e)//服務器響應失敗處理函數 { alert(e); } } ) return false; } </script> <div> <p><input type="file" id="file1" name="file" /></p> <input type="button" value="上傳" /> <p><img id="img1" alt="上傳成功啦!" src="" /></p> <p id="p1"></p> <form id="FaceUpload" name="FaceUpload" method="post" enctype="multipart/form-data" action="/uploadandcut/Upload?action=cut"> <input type="hidden" id="x1" name="x1" value="0" /> <input type="hidden" id="y1" name="y1" value="0" /> <input type="hidden" id="cw" name="cw" value="0" /> <input type="hidden" id="ch" name="ch" value="0" /> <input type="submit" value="裁剪上傳" /> </form> </div>
二、后台代碼
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Drawing; namespace UploadAndCut.Controllers { public class UploadAndCutController : Controller { /// <summary> /// 打開頁面 /// </summary> /// <returns></returns> public ActionResult Index() { return View(); } /// <summary> /// 上傳操作,包括提交表單與AJAX上傳圖片 /// </summary> /// <returns></returns> public ActionResult Upload() { string action = HttpContext.Request.QueryString["action"]; //判斷用戶的操作類型 switch (action.ToLower()) { #region 當為上傳圖片操作時 case "up": foreach (string upload in Request.Files) { if (!Request.Files[upload].HasFile()) { continue; } string ExtensionName = Path.GetExtension(Request.Files[upload].FileName).ToLower(); if (ExtensionName != ".jpg" && ExtensionName != ".png" && ExtensionName != ".gif" && ExtensionName != ".bmp") { return Redirect("/Tips/tip?error=您上傳的圖片不符合格式!"); } string ImgPath = Server.MapPath("/uploads/" + "img" + ExtensionName); Request.Files[upload].SaveAs(ImgPath); } string error = ""; string msg = "上傳成功"; string imgurl = "/uploads/img.jpg"; string res = "{ error:'" + error + "', msg:'" + msg + "',imgurl:'" + imgurl + "'}"; return Content(res); break; #endregion #region 當為裁剪圖片操作時 case "cut": string strx1 = HttpContext.Request.Form["x1"]; string stry1 = HttpContext.Request.Form["y1"]; string strcw = HttpContext.Request.Form["cw"]; string strch = HttpContext.Request.Form["ch"]; int intx1 = Convert.ToInt32(strx1); int inty1 = Convert.ToInt32(stry1); int intcw = Convert.ToInt32(strcw); int intch = Convert.ToInt32(strch); Stream imgStream = GetLocalStream(Server.MapPath("/uploads/" + "img.jpg")); //System.Drawing.Image initImage = System.Drawing.Image.FromStream(imgStream); Cut(imgStream, Server.MapPath("/uploads/img.jpg"), intx1, inty1, intcw, intch, 100); return Redirect("/uploadandcut/index"); break; #endregion default: return null; break; } } /// <summary> /// 將一個文件讀成字符流 /// </summary> /// <param name="InFilePath"></param> /// <returns></returns> public static Stream GetLocalStream(string InFilePath) { return new MemoryStream(ReadFileReturnBytes(InFilePath)); } /// <summary>從文件中讀取二進制數據</summary> /// <param name="filePath">文件路徑</param> /// <returns> byte[]二進制數據</returns> public static byte[] ReadFileReturnBytes(string filePath) { FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); BinaryReader br = new BinaryReader(fs); byte[] buff = br.ReadBytes((int)fs.Length); br.Close(); fs.Close(); return buff; } #region 裁剪操作 public static void Cut(System.IO.Stream fromFile, string fileSaveUrl, int xPosition, int yPosition, int width, int height, int quality) { //創建目錄 //原始圖片(獲取原始圖片創建對象,並使用流中嵌入的顏色管理信息) System.Drawing.Image initImage = System.Drawing.Image.FromStream(fromFile, true); //原始圖片的寬、高 int initWidth = initImage.Width; int initHeight = initImage.Height; if (xPosition + width > initWidth) width = initWidth - xPosition; if (yPosition + height > initHeight) height = initHeight - yPosition; //與原圖相等直接保存 if ((width >= initWidth && height >= initHeight) || (width < 1 && height < 1)) { initImage.Save(fileSaveUrl, System.Drawing.Imaging.ImageFormat.Jpeg); } else { System.Drawing.Image pickedImage = null; System.Drawing.Graphics pickedG = null; //對象實例化 pickedImage = new System.Drawing.Bitmap(width, height); pickedG = System.Drawing.Graphics.FromImage(pickedImage); //設置質量 pickedG.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; pickedG.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //定位 System.Drawing.Rectangle fromR = new System.Drawing.Rectangle(xPosition, yPosition, width, height); System.Drawing.Rectangle toR = new System.Drawing.Rectangle(0, 0, width, height); //畫圖 pickedG.DrawImage(initImage, toR, fromR, System.Drawing.GraphicsUnit.Pixel); //關鍵質量控制 //獲取系統編碼類型數組,包含了jpeg,bmp,png,gif,tiff System.Drawing.Imaging.ImageCodecInfo[] icis = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders(); System.Drawing.Imaging.ImageCodecInfo ici = null; foreach (System.Drawing.Imaging.ImageCodecInfo i in icis) { if (i.MimeType == "image/jpeg" || i.MimeType == "image/bmp" || i.MimeType == "image/png" || i.MimeType == "image/gif") { ici = i; } } System.Drawing.Imaging.EncoderParameters ep = new System.Drawing.Imaging.EncoderParameters(1); ep.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)quality); //保存縮略圖 pickedImage.Save(fileSaveUrl, ici, ep); //釋放關鍵質量控制所用資源 ep.Dispose(); //釋放截圖資源 pickedG.Dispose(); pickedImage.Dispose(); //釋放原始圖片資源 initImage.Dispose(); } } #endregion } }
還有一個擴展方法,在DEMO里面會有,不粘貼了。DEMO下載地址