下面就講解一下,移動端上傳照片,旋轉,摳圖,以及圖片美白效果原理。php
下面是兩種上傳照片的方法jquery
一、此方法被廢棄,但願能給你們一點提示,和思考的空間web
a、經過改變file的值獲取圖片路徑,並把路徑添加到img元素中,在頁面中展現 b、圖片上傳,能夠用form表單上傳,可是獲取不到返回值,能夠用ajaxfileupload.js上傳
<img id="pic" src="image/index3_photo.png" class="index3_photo" width="167" height="218"> <input id="upload" name="upload" accept="image/*" type="file" style="display: none"/> <script> $("#pic").click(function () { $("#upload").click(); //隱藏了input:file樣式後,點擊頭像就能夠本地上傳 $("#upload").on("change",function(){ var objUrl = getObjectURL(this.files[0]) ; //獲取圖片的路徑,該路徑不是圖片在本地的路徑 if (objUrl) { var img=new Image() img.src=objUrl img.onload= function () { $("#pic").attr({ "src":objUrl, }) ; //將圖片路徑存入src中,顯示出圖片 } } }); }); //創建一個可存取到該file的url function getObjectURL(file) { var url = null ; if (window.createObjectURL!=undefined) { // basic url = window.createObjectURL(file) ; } else if (window.URL!=undefined) { // mozilla(firefox) url = window.URL.createObjectURL(file) ; } else if (window.webkitURL!=undefined) { // webkit or chrome url = window.webkitURL.createObjectURL(file) ; } return url ; } $.ajaxFileUpload({ url: '/file.php', //用於文件上傳的服務器端請求地址 secureuri: false, //是否須要安全協議,通常設置爲false fileElementId: 'upload', //文件上傳域的ID dataType : 'content', //返回值類型 通常設置爲json success: function (data) //服務器成功響應處理函數 { var data = eval('('+data+')') }, error: function (data, status, e)//服務器響應失敗處理函數 { alert(e); } }) </script>
二、經過canvas畫布上傳照片,此方法被推薦ajax
a、照片展現,經過file獲取圖片路徑,畫到canvas上,在用base64轉化一下 b、上傳圖片,經過ajax post上傳
<input type="file" id="upload"> <canvas id="canvas"></canvas> <script src="jquery-2.2.1.min.js"></script> <script> $("#upload").bind("change", function () { var file=document.getElementById("upload").files[0] var URL=window.URL||window.webkitURL; var blob=URL.createObjectURL(file) var img=new Image() img.src=blob img.onload= function () { drawCanvas(img) } }) var base64 function drawCanvas(img,i){ var canvas=document.createElement("canvas") var ctx=canvas.getContext("2d"),imgW=img.width,imgH=img.height,resultW,resultH resultW=imgW>640?640:imgW; resultH=imgH/imgW*resultW canvas.width=resultW canvas.height=resultH $("body").append(canvas) ctx.drawImage(img,0,0,resultW,resultH) base64 = canvas.toDataURL("image/jpeg") } $.post("url",{base64:base64}, function (data) { },"json") </script>
總結:之因此先第二種方案,由於第一種方法,直接上傳最原始圖片,圖片尺寸大小都會影響服務器的速度,並且圖片太大會致使上傳失敗,而用canvas先縮放圖片尺寸大小,能夠很好的完成上傳
在上傳過程當中,若是不對圖片進行處理,會由於拍攝角度,圖片展現效果不會達到預期效果,並且不會進行五官識別
此方法主要藉助exif.js獲取照片拍攝角度進行旋轉chrome
checkImgAngel=function(n,m,h){ EXIF.getData(n, function () { EXIF.getAllTags(n); var imgOrient= EXIF.getTag(n, 'Orientation'); switch(imgOrient){ case 6://須要順時針(向左)90度旋轉 rotateImg(n,'left'); break; case 8://須要逆時針(向右)90度旋轉 rotateImg(n,'right'); break; case 3://須要180度旋轉 rotateImg(n,'right');//轉兩次 rotateImg(n,'right'); break; } }) } function rotateImg(img, direction) { var canvas = document.createElement("canvas") var ctx = canvas.getContext("2d") $(document.body).append(canvas) var min_step = 0; var max_step = 3; if (img == null)return; var height = img.height; var width = img.width; var step = 2; if (step == null) { step = min_step; } if (direction == 'right') { step++; step > max_step && (step = min_step); } else { step--; step < min_step && (step = max_step); } //旋轉角度以弧度值爲參數 var degree = step * 90 * Math.PI / 180; var ctx = canvas.getContext('2d'); switch (step) { case 0: canvas.width = width; canvas.height = height; ctx.drawImage(img, 0, 0); break; case 1: canvas.width = height; canvas.height = width; ctx.rotate(degree); ctx.drawImage(img, 0, -height); break; case 2: canvas.width = width; canvas.height = height; ctx.rotate(degree); ctx.drawImage(img, -width, -height); break; case 3: canvas.width = height; canvas.height = width; ctx.rotate(degree); ctx.drawImage(img, -width, 0); break; } }
此效果須要藉助騰訊優圖API完成,騰訊優圖會提供人臉五官座標,經過canvas的clip()方法,對人臉進行摳圖json
function drawLine(data,status){ var data = setData1(data,status)//接口返回數據並處理 ctx.save(); var len=data.length ctx.beginPath(); ctx.moveTo(data[0].x,data[0].y) for(var i=1;i<len;i++){ ctx.lineTo(data[i].x,data[i].y) } ctx.closePath(); ctx.clip(); ctx.drawImage(img, 0, 0); ctx.restore() }
注意:由於返回的座標並不全是五官的輪廓座標,因此須要開發人員先對數據進行處理,剔除不須要的座標canvas
主要原理是canvas的getImageData方法,獲取到每個像素點的rgba值,進行運算,在經過putImageData方法,從新渲染圖片,先經過isPointInPath方法,把須要美白的部分點push到一個數組中數組
對臉部點進行處理,push到imgDataArr數組中安全
var imgDataArr=[] function drawLine(data,status){ var data = setData1(data,status)//接口返回數據並處理 var len=data.length ctx.beginPath(); ctx.moveTo(data[0].x,data[0].y) for(var i=1;i<len;i++){ ctx.lineTo(data[i].x,data[i].y) } ctx.closePath(); ctx.restore() getData() } function getData(){ var w = canvas.width var h = canvas.height; var resultw; var resulth for(var i=0;i<w;i++){ for(var j=0;j<h;j++){ resultw=j resulth=i if(ctx.isPointInPath(resultw,resulth)){ imgDataArr.push(i*w+j) } } } }
經過接口返回的臉部五官數據獲取像素點,經過drawLine()在canvas上畫出臉部模型,在經過isPointInPath方法,收集臉部數據服務器
美白效果
function setImagedata(){ var imgData = ctx.getImageData(0,0,canvas.width,canvas.height) for(var i= 0 ;i<imgDataArr.length;i++){ imgData.data[imgDataArr[i]*4+0]=imgData.data[imgDataArr[i]*4+0]+50 imgData.data[imgDataArr[i]*4+1]=imgData.data[imgDataArr[i]*4+1]+50 imgData.data[imgDataArr[i]*4+2]=imgData.data[imgDataArr[i]*4+2]+50 imgData.data[imgDataArr[i]*4+3]=255 } ctx.putImageData(imgData,0,0); }