下面就讲解一下,移动端上传照片,旋转,抠图,以及图片美白效果原理。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); }