forked from ppisljar/image-morph-js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
imgwarp.min.js
1 lines (1 loc) · 8.27 KB
/
imgwarp.min.js
1
var ImgWarper=ImgWarper||{};ImgWarper.Warper=function(t,i,r){this.alpha=r||1,this.gridSize=i||20,this.width=t.width,this.height=t.height,this.imgData=t.data,this.bilinearInterpolation=new ImgWarper.BilinearInterpolation(this.width,this.height),this.grid=[];for(var e=0;e<this.width;e+=this.gridSize)for(var n=0;n<this.height;n+=this.gridSize)a=new ImgWarper.Point(e,n),b=new ImgWarper.Point(e+this.gridSize,n),c=new ImgWarper.Point(e+this.gridSize,n+this.gridSize),d=new ImgWarper.Point(e,n+this.gridSize),this.grid.push([a,b,c,d])},ImgWarper.Warper.prototype.warp=function(t,i){for(var r=new ImgWarper.AffineDeformation(i,t,this.alpha),e=[],n=0;n<this.grid.length;++n)e[n]=[r.pointMover(this.grid[n][0]),r.pointMover(this.grid[n][1]),r.pointMover(this.grid[n][2]),r.pointMover(this.grid[n][3])];var a=this.bilinearInterpolation.generate(this.imgData,this.grid,e);return a},ImgWarper.AffineDeformation=function(t,i,r){return this.w=null,this.pRelative=null,this.qRelative=null,this.A=null,t.length!=i.length?void console.error("Points are not of same length."):(this.n=t.length,this.fromPoints=t,this.toPoints=i,void(this.alpha=r))},ImgWarper.AffineDeformation.prototype.pointMover=function(t){(null==this.pRelative||this.pRelative.length<this.n)&&(this.pRelative=new Array(this.n)),(null==this.qRelative||this.qRelative.length<this.n)&&(this.qRelative=new Array(this.n)),(null==this.w||this.w.length<this.n)&&(this.w=new Array(this.n)),(null==this.A||this.A.length<this.n)&&(this.A=new Array(this.n));for(var i=0;i<this.n;++i){var r=this.fromPoints[i].subtract(t);this.w[i]=Math.pow(r.x*r.x+r.y*r.y,-this.alpha)}for(var e=ImgWarper.Point.weightedAverage(this.fromPoints,this.w),n=ImgWarper.Point.weightedAverage(this.toPoints,this.w),i=0;i<this.n;++i)this.pRelative[i]=this.fromPoints[i].subtract(e),this.qRelative[i]=this.toPoints[i].subtract(n);for(var a=new ImgWarper.Matrix22(0,0,0,0),i=0;i<this.n;++i)a.addM(this.pRelative[i].wXtX(this.w[i]));a=a.inverse();for(var s=0;s<this.n;++s)this.A[s]=t.subtract(e).multiply(a).dotP(this.pRelative[s])*this.w[s];for(var o=n,s=0;s<this.n;++s)o=o.add(this.qRelative[s].multiply_d(this.A[s]));return o};var ImgWarper=ImgWarper||{};ImgWarper.BilinearInterpolation=function(t,i){this.width=t,this.height=i,this.imgTargetData=document.createElement("canvas").getContext("2d").createImageData(this.width,this.height)},ImgWarper.BilinearInterpolation.prototype.generate=function(t,i,r){this.imgData=t;for(var e=0;e<r.length;++e)this.fill(r[e],i[e]);return this.imgTargetData},ImgWarper.BilinearInterpolation.prototype.fill=function(t,i){var r,e,n,a,s=i[0].x,o=i[2].x,h=i[0].y,g=i[2].y;s=Math.max(s,0),h=Math.max(h,0),o=Math.min(o,this.width-1),g=Math.min(g,this.height-1);var p,m,f,l,d,u,I,P,c;for(r=s;o>=r;++r)for(p=(r-s)/(o-s),m=1-p,f=m*t[0].x+p*t[1].x,l=m*t[0].y+p*t[1].y,d=m*t[3].x+p*t[2].x,u=m*t[3].y+p*t[2].y,e=h;g>=e;++e)if(I=(e-h)/(g-h),P=1-I,n=f*P+d*I,a=l*P+u*I,c=4*(e*this.width+r),0>n||n>this.width-1||0>a||a>this.height-1)this.imgTargetData.data[c]=255,this.imgTargetData.data[c+1]=255,this.imgTargetData.data[c+2]=255,this.imgTargetData.data[c+3]=255;else{var y=Math.floor(n),W=Math.floor(a),v=4*(W*this.width+y);this.imgTargetData.data[c]=this.imgData[v],this.imgTargetData.data[c+1]=this.imgData[v+1],this.imgTargetData.data[c+2]=this.imgData[v+2],this.imgTargetData.data[c+3]=this.imgData[v+3]}};var ImgWarper=ImgWarper||{};ImgWarper.Matrix22=function(t,i,r,e){this.M11=t,this.M12=i,this.M21=r,this.M22=e},ImgWarper.Matrix22.prototype.adjugate=function(){return new ImgWarper.Matrix22(this.M22,-this.M12,-this.M21,this.M11)},ImgWarper.Matrix22.prototype.determinant=function(){return this.M11*this.M22-this.M12*this.M21},ImgWarper.Matrix22.prototype.multiply=function(t){return this.M11*=t,this.M12*=t,this.M21*=t,this.M22*=t,this},ImgWarper.Matrix22.prototype.addM=function(t){this.M11+=t.M11,this.M12+=t.M12,this.M21+=t.M21,this.M22+=t.M22},ImgWarper.Matrix22.prototype.inverse=function(){return this.adjugate().multiply(1/this.determinant())};var ImgWarper=ImgWarper||{};ImgWarper.Point=function(t,i){this.x=t,this.y=i},ImgWarper.Point.prototype.add=function(t){return new ImgWarper.Point(this.x+t.x,this.y+t.y)},ImgWarper.Point.prototype.subtract=function(t){return new ImgWarper.Point(this.x-t.x,this.y-t.y)},ImgWarper.Point.prototype.wXtX=function(t){return new ImgWarper.Matrix22(this.x*this.x*t,this.x*this.y*t,this.y*this.x*t,this.y*this.y*t)},ImgWarper.Point.prototype.dotP=function(t){return this.x*t.x+this.y*t.y},ImgWarper.Point.prototype.multiply=function(t){return new ImgWarper.Point(this.x*t.M11+this.y*t.M21,this.x*t.M12+this.y*t.M22)},ImgWarper.Point.prototype.multiply_d=function(t){return new ImgWarper.Point(this.x*t,this.y*t)},ImgWarper.Point.weightedAverage=function(t,i){var r,e=0,n=0,a=0;for(r=0;r<t.length;r++)e+=t[r].x*i[r],n+=t[r].y*i[r],a+=i[r];return new ImgWarper.Point(e/a,n/a)},ImgWarper.Point.prototype.InfintyNormDistanceTo=function(t){return Math.max(Math.abs(this.x-t.x),Math.abs(this.y-t.y))};var ImgWarper=ImgWarper||{};ImgWarper.PointDefiner=function(t,i,r){this.oriPoints=new Array,this.dstPoints=new Array;var e=t;this.canvas=t;var n=this;this.dragging_=!1,this.computing_=!1,this.image=i,this.imgData=r,$(e).unbind(),$(e).bind("mousedown",function(t){n.touchStart(t)}),$(e).bind("mousemove",function(t){n.touchDrag(t)}),$(e).bind("mouseup",function(t){n.touchEnd(t)}),this.currentPointIndex=-1},ImgWarper.PointDefiner.prototype.touchEnd=function(t){this.dragging_=!1},ImgWarper.PointDefiner.prototype.touchDrag=function(t){if(!(this.computing_||!this.dragging_||this.currentPointIndex<0)){this.computing_=!0,t.preventDefault();var i=t.offsetX||t.clientX-$(t.target).offset().left,r=t.offsetY||t.clientY-$(t.target).offset().top;movedPoint=new ImgWarper.Point(i,r),this.dstPoints[this.currentPointIndex]=new ImgWarper.Point(i,r),this.redraw(),this.computing_=!1}},ImgWarper.PointDefiner.prototype.redraw=function(){this.redrawCanvas()},ImgWarper.PointDefiner.prototype.touchStart=function(t){this.dragging_=!0,t.preventDefault();var i=t.offsetX||t.clientX-$(t.target).offset().left,r=t.offsetY||t.clientY-$(t.target).offset().top,e=new ImgWarper.Point(i,r);if(t.shiftKey){var n=this.getCurrentPointIndex(e);n>=0&&(this.oriPoints.splice(n,1),this.dstPoints.splice(n,1))}else this.oriPoints.push(e),this.dstPoints.push(e);this.redraw()},ImgWarper.PointDefiner.prototype.getCurrentPointIndex=function(t){for(var i=-1,r=0;r<this.dstPoints.length;r++)if(this.dstPoints[r].InfintyNormDistanceTo(t)<=20)return i=r,r;return i},ImgWarper.PointDefiner.prototype.redrawCanvas=function(t){var i=this.canvas.getContext("2d");i.clearRect(0,0,this.imgData.width,this.imgData.height),i.putImageData(this.imgData,0,0);for(var r=0;r<this.oriPoints.length;r++)r<this.dstPoints.length?(r==this.currentPointIndex?this.drawOnePoint(this.dstPoints[r],i,"orange"):this.drawOnePoint(this.dstPoints[r],i,"#6373CF"),i.beginPath(),i.lineWidth=3,i.moveTo(this.oriPoints[r].x,this.oriPoints[r].y),i.lineTo(this.dstPoints[r].x,this.dstPoints[r].y),i.stroke()):this.drawOnePoint(this.oriPoints[r],i,"#119a21");i.stroke()},ImgWarper.PointDefiner.prototype.drawOnePoint=function(t,i,r){var e=10;i.beginPath(),i.lineWidth=3,i.arc(parseInt(t.x),parseInt(t.y),e,0,2*Math.PI,!1),i.strokeStyle=r,i.stroke(),i.beginPath(),i.lineWidth=1,i.arc(parseInt(t.x),parseInt(t.y),3,0,2*Math.PI,!1),i.fillStyle=r,i.fill()},ImgWarper.Animator=function(t,i){this.pointDefiner1=t,this.pointDefiner2=i},ImgWarper.Animator.prototype.generate=function(t){this.frames=[];for(var i=this.calculatePositions(t),r=new ImgWarper.Warper(this.pointDefiner1.imgData),e=new ImgWarper.Warper(this.pointDefiner2.imgData),n=0;n<i.length;n++){var a=i[n],s=r.warp(this.pointDefiner1.oriPoints,a),o=e.warp(this.pointDefiner2.oriPoints,a),h=this.blendImages(s,o,n,i.length);this.frames.push(h)}},ImgWarper.Animator.prototype.calculatePositions=function(t){for(var i=[],r=0;t>=r;r++){for(var e=[],n=0;n<this.pointDefiner1.oriPoints.length;n++){var a=new ImgWarper.Point(this.pointDefiner1.oriPoints[n].x+(this.pointDefiner2.oriPoints[n].x-this.pointDefiner1.oriPoints[n].x)*r/t,this.pointDefiner1.oriPoints[n].y+(this.pointDefiner2.oriPoints[n].y-this.pointDefiner1.oriPoints[n].y)*r/t);e.push(a)}i.push(e)}return i},ImgWarper.Animator.prototype.blendImages=function(t,i,r,e){for(var n=document.createElement("canvas").getContext("2d").createImageData(t.width,t.height),a=0;a<t.data.length;a++)n.data[a]=t.data[a]+(i.data[a]-t.data[a])*r/e;return n};