intellicrop
Version:
Simple JavaScript solution to edge detection assisted image cropping.
3 lines (2 loc) • 19.2 kB
JavaScript
import t,{Mat as e,CV_8UC3 as s,cvtColor as i,COLOR_RGBA2GRAY as r,resize as h,Size as o,adaptiveThreshold as n,CALIB_CB_ADAPTIVE_THRESH as a,THRESH_BINARY as c,erode as l,CV_8U as g,Canny as d,dilate as m,HoughLines as b,COLOR_GRAY2RGBA as p,line as u,circle as x,Point as P,imshow as v}from"@techstark/opencv-js/";class M{static loopDiff(t,e,s,i){let r=Math.abs(t-e);return Math.min(r,i-s-r)}static maxIndex(t,e){if(!t.length)return;let s=0,i=e?e(t[0]):t[0];for(let r=1;r<t.length;r++){let h=e?e(t[r]):t[r];h>i&&(s=r,i=h)}return s}static maxValue(t,e){if(!t.length)return;let s=t[0],i=e?e(t[0]):t[0];for(let r=1;r<t.length;r++){let h=e?e(t[r]):t[r];h>i&&(s=t[r],i=h)}return s}static areaToBounds(t,e){let s=Math.sqrt(t*e);return[s,t/s]}static ptDiff(t,e){return[e[0]-t[0],e[1]-t[1]]}static ptDistance(t,e){return Math.sqrt(Math.pow(t[0]-e[0],2)+Math.pow(t[1]-e[1],2))}static ptRelativeDistance(t,e,s){let i=this.ptDistance(e,s),r=this.ptDistance(t,e),h=this.ptDistance(t,s);return(r<h&&h>i?-1:1)*(0===i?0:r/i)}static src2dstPt(t,e,s){return[t[0]*(s.cols/e.cols),t[1]*(s.rows/e.rows)]}static closestPoint(t,e){let{theta:s,rho:i}=t,r=-Math.sin(s),h=Math.cos(s),o=i*h,n=-i*r,a=r*(e[0]-o)+h*(e[1]-n);return[o+r*a,n+h*a]}static lineThrough(t,e){let s=e[0]-t[0],i=e[1]-t[1];return{rho:-(i*t[0]-s*t[1])/Math.sqrt(s**2+i**2),theta:Math.atan2(i,s)+Math.PI/2}}static shortestDistance(t,e){return Math.abs(e[0]*Math.cos(t.theta)+e[1]*Math.sin(t.theta)-t.rho)}static ptWithinBounds(t,e){return t[0]>=0&&t[0]<e[0]&&t[1]>=0&&t[1]<e[1]}static ptClipBounds(t,e){return[Math.min(Math.max(t[0],0),e[0]-1),Math.min(Math.max(t[1],0),e[1]-1)]}static ptClipBoundsRect(t,e){return[Math.min(Math.max(t[0],e.left),e.right),Math.min(Math.max(t[1],e.top),e.bottom)]}static mean(t){return t.reduce((t,e)=>t+e)/t.length}static stdDev(t,e){return e??=this.mean(t),Math.sqrt(t.map(t=>Math.pow(t-e,2)).reduce((t,e)=>t+e)/t.length)}static area(t){let e=0,s=Object.keys(t);for(let i=0;i<s.length;i++){let r=s[i],h=s[(i+1)%s.length],o=t[r],n=t[h];e+=o[0]*n[1]-n[0]*o[1]}return Math.abs(e)/2}static lineCenter(t,e){return[t[0]+(e[0]-t[0])/2,t[1]+(e[1]-t[1])/2]}static edgeCenters(t){return{t:this.lineCenter(t.tl,t.tr),r:this.lineCenter(t.tr,t.br),b:this.lineCenter(t.br,t.bl),l:this.lineCenter(t.bl,t.tl)}}static withinRadius(t,e,s){let i=t[0],r=t[1],h=e[0]-s,o=e[0]+s,n=e[1]-s,a=e[1]+s;return i>=h&&i<=o&&r>=n&&r<=a}static cornerCenter(t){let{tl:e,tr:s,br:i,bl:r}=t;return[(e[0]+s[0]+i[0]+r[0])/4,(e[1]+s[1]+i[1]+r[1])/4]}static rotateKey(t,e,s){let i=Object.keys(t),r=this.rotateVal(i.findIndex(t=>e===t),s,i.length);return i[r]}static rotateVal(t,e,s){return((t+e)%s+s)%s}static mapObj(t,e){return Object.keys(t).reduce((s,i)=>(s[i]=e(t[i],i),s),{})}static ptAtAngle(t,e,s){return[t[0]+s*Math.cos(e),t[1]+s*Math.sin(e)]}static angleBetween(t,e){return Math.atan2(e[1]-t[1],e[0]-t[0])}}class f{static{this.RHO_THRES=.05}static{this.THETA_THRES=Math.PI/180*4}static{this.MAX_TILT=Math.PI/180*35}static{this.PARSE_LINES_AMOUNT=8}static{this.MIN_AREA=.2}static detect(t,f){let C;let w=t.cols,R=t.rows,L={tl:[0,0],tr:[w,0],br:[w,R],bl:[0,R]},T=e.zeros(0,0,s),I=M.areaToBounds(1e5,t.cols/t.rows),E=I[0],y=I[1],D=Math.sqrt(E*E+y*y),G=new e,O=new e;i(t,T,r,0),h(T,T,new o(...I)),n(T,T,255,a,c,15,0),l(T,T,e.ones(5,5,g)),d(T,T,0,160,3,!0),m(T,T,e.ones(4,4,g)),f&&(C=T.clone()),b(T,G,2,Math.PI/180,50,0,0,Math.PI/2-this.MAX_TILT,Math.PI/2+this.MAX_TILT),b(T,O,2,Math.PI/180,50,0,0,-this.MAX_TILT,this.MAX_TILT);let k=this.parseLines(G,D),A=this.parseLines(O,D),H=this.getScoredIntersections(k,A,E,y);if(H.forEach(e=>e.pt=M.src2dstPt(e.pt,T,t)),C){for(let e of(h(C,C,new o(t.cols,t.rows)),i(C,C,p,0),[...k,...A])){let s=e.rho*(t.cols/T.cols),i=e.theta,r=Math.cos(i),h=Math.sin(i),o=r*s,n=h*s;u(C,{x:o-1e4*h,y:n+1e4*r},{x:o+1e4*h,y:n-1e4*r},[255,0,127,255],4)}for(let t=0;t<H.length;t++){let e=H[t];x(C,new P(...e.pt),20,[255-255*Math.pow(e.score,8),255*Math.pow(e.score,8),127,255],4)}v(f,C)}let S=M.area(L);if(H.length>4){let t=this.getScoredCorners(H,S);if(t.length)return M.maxValue(t,t=>t.score).corners}let z=this.getOutmostCorners(H,L)?.corners;if(z&&M.area(z)/S>this.MIN_AREA)return z}static parseLines(t,e){let s=[];for(let i=0;i<t.rows&&s.length<this.PARSE_LINES_AMOUNT;i++){let r=t.data32F[2*i],h=t.data32F[2*i+1];s.some(t=>Math.abs(r-t.rho)<this.RHO_THRES*e&&M.loopDiff(h,t.theta,0,Math.PI)<this.THETA_THRES)||s.push({rho:r,theta:h})}return s}static getScoredIntersections(t,e,s,i){let r=[];for(let h=0;h<t.length;h++){let o=t[h];for(let n=0;n<e.length;n++){let a=e[n],c=Math.cos(o.theta),l=Math.sin(o.theta),g=Math.cos(a.theta),d=Math.sin(a.theta),m=c*d-l*g;if(0!==m){let b=(d*o.rho-l*a.rho)/m,p=(c*a.rho-g*o.rho)/m,u=M.loopDiff(a.theta,o.theta,0,Math.PI),x=Math.max(1-2*M.loopDiff(u,Math.PI/2,0,Math.PI)/Math.PI,0),P=1-(h/t.length+n/e.length)/2;b>0&&p>0&&b<s&&p<i&&r.push({pt:[b,p],score:x+P,hLine:o,vLine:a})}}}return r}static getOutmostCorners(t,e){if(t.length<4)return;t=t.slice();let s={score:0,corners:e};for(let e in s.corners){let i=t.splice(M.maxIndex(t,t=>-M.ptDistance(t.pt,s.corners[e])),1)[0];s.corners[e]=i.pt,s.score+=i.score}return s}static getScoredCorners(t,e){let s=[];return t.forEach(i=>{let r=t.filter(t=>i.hLine===t.hLine&&i.pt[0]<t.pt[0]),h=t.filter(t=>i.vLine===t.vLine&&i.pt[1]<t.pt[1]);r.forEach(r=>{h.forEach(h=>{let o=t.find(t=>t.hLine===h.hLine&&t.vLine===r.vLine);if(o){let t={tl:i.pt,tr:r.pt,br:o.pt,bl:h.pt},n=M.area(t)/e;n>this.MIN_AREA&&s.push({corners:t,score:i.score+r.score+o.score+h.score+n})}})})}),s}}class C{static async initialization(){return new Promise(e=>{t.getBuildInformation?e():t.onRuntimeInitialized=()=>{e()}})}static isReady(){return!!t.getBuildInformation}constructor(e,s,i){this.rotations=0,this.onResize=()=>this.adjustDimensions();let r={useEdgeDetection:!0,theme:{backgroundColor:"black",surroundingOverlayColor:"rgba(0,0,0,0.333)",cornerGrabberRadius:.5,cornerGrabberColor:"white",edgeThickness:.2,edgeColor:"white",edgeGrabberRadius:i?.theme?.cornerGrabberRadius?.8*i.theme.cornerGrabberRadius:.4,edgeGrabberColor:i?.theme?.cornerGrabberColor??"white",centerGrabberRadius:i?.theme?.cornerGrabberRadius?1.2*i.theme.cornerGrabberRadius:.6,centerGrabberColor:i?.theme?.cornerGrabberColor??"rgba(255,255,255,0.5)",grabberExpansionFactor:1.2,grabberHitboxFactor:1.5,crossLineThickness:i?.theme?.edgeThickness??.2,crossLineColor:i?.theme?.edgeColor??"rgba(255,255,255,0.5)",zoomLensRadius:i?.theme?.cornerGrabberRadius?8*i.theme.cornerGrabberRadius:4,zoomLensMargin:i?.theme?.cornerGrabberRadius?2*i.theme.cornerGrabberRadius:1,zoomLensFactor:2,zoomLensBorderThickness:i?.theme?.edgeThickness?i?.theme?.edgeThickness*.5:.1,zoomLensBorderColor:"black",zoomLensOverlayColor:i?.theme?.surroundingOverlayColor??"rgba(0,0,0,0.333)"}};this.canvas=e,this.ctx=e.getContext("2d"),this.img=s,this.imgMat=t.imread(s),this.options={useEdgeDetection:!i.corners&&(i.useEdgeDetection??r.useEdgeDetection),theme:Object.assign(r.theme,i?.theme),debugCanvas:i.debugCanvas,debugLogs:i.debugLogs,corners:i.corners,rotations:i.rotations},this.options.rotations&&(this.rotations=M.rotateVal(i.rotations,0,4)),this.imgW=this.rotations%2==0?this.imgMat.cols:this.imgMat.rows,this.imgH=this.rotations%2==0?this.imgMat.rows:this.imgMat.cols,this.canvas.width=this.imgW,this.canvas.height=this.imgH,this.adjustDimensions(),setTimeout(()=>{this.options.useEdgeDetection&&(this.options.debugLogs&&console.time("edgedetection"),this.corners=f.detect(this.imgMat,this.options.debugCanvas),this.options.debugLogs&&console.timeEnd("edgedetection")),this.corners||(this.corners=this.options.corners??{tl:[0,0],tr:[this.imgW,0],br:[this.imgW,this.imgH],bl:[0,this.imgH]}),this.updateCenters(),this.registerListeners(),this.render()},1)}registerListeners(){let t,e,s;this.onPointerDown=i=>{if(i.preventDefault(),i.stopPropagation(),this.setDragged(this.getGrabber([i.clientX,i.clientY])),this.dragged){if(t=this.rotations%2==0?[this.imgW,this.imgH]:[this.imgH,this.imgW],this.dragged in this.edgeCenters){let s=this.edgeCenters[this.dragged],i=this.edgeCenters[M.rotateKey(this.edgeCenters,this.dragged,2)],r=M.lineThrough(s,i),h=Object.keys(this.corners),o=Object.keys(this.edgeCenters),n=[],a=-1/0,c=1/0;for(let e=0;e<2;e++){let s=o.indexOf(this.dragged),i=h[M.rotateVal(s,e,h.length)],r=h[M.rotateVal(s,-e-1,h.length)],l=this.corners[i],g=this.corners[r],d=l[0]-g[0],m=l[1]-g[1],b=-g[0]/d,p=(t[0]-g[0])/d,u=-g[1]/m,x=(t[1]-g[1])/m;a=Math.max(a,...[b,p,u,x].filter(t=>t<0)),c=Math.min(c,...[b,p,u,x].filter(t=>t>1)),n[e]={key:i,towardsKey:r,deltaX:d,deltaY:m}}e={dragLine:r,edgeCenter:s,oppositeEdgeCenter:i,moveCorners:n,scalarMin:a,scalarMax:c}}else this.dragged in this.viewCenter&&(s={cornerOffsets:M.mapObj(this.corners,t=>M.ptDiff(this.viewCenter.c,t))});window.addEventListener("pointermove",this.onPointerMove),window.addEventListener("pointerup",this.onPointerUp)}};let i=!1;this.onPointerMove=r=>{r.preventDefault(),r.stopPropagation(),this.dragged&&!i&&(window.requestAnimationFrame(()=>{if(i=!1,this.dragged in this.corners)this.corners[this.dragged]=M.ptClipBounds(this.cl2imgPt([r.clientX,r.clientY]),t);else if(this.dragged in this.edgeCenters){let{dragLine:t,edgeCenter:s,oppositeEdgeCenter:i,moveCorners:h,scalarMin:o,scalarMax:n}=e,a=M.closestPoint(t,this.cl2imgPt([r.clientX,r.clientY])),c=Math.min(Math.max(M.ptRelativeDistance(a,i,s),o),n);for(let t of h){let e=this.corners[t.towardsKey];this.corners[t.key]=[e[0]+t.deltaX*c,e[1]+t.deltaY*c]}}else if(this.dragged in this.viewCenter){let e=Object.values(s.cornerOffsets),i=M.ptClipBoundsRect(this.cl2imgPt([r.clientX,r.clientY]),{left:Math.max(...e.map(t=>-t[0])),right:Math.min(...e.map(e=>t[0]-e[0])),top:Math.max(...e.map(t=>-t[1])),bottom:Math.min(...e.map(e=>t[1]-e[1]))});this.corners=M.mapObj(s.cornerOffsets,t=>[t[0]+i[0],t[1]+i[1]])}this.updateCenters(),this.render()}),i=!0)},this.onPointerUp=t=>{t.preventDefault(),t.stopPropagation(),this.setDragged(void 0),window.removeEventListener("pointermove",this.onPointerMove),window.removeEventListener("pointerup",this.onPointerUp),this.render()},this.onMouseMove=t=>{if(this.dragged)return;t.preventDefault(),t.stopPropagation();let e=this.hovered;this.setHovered(this.getGrabber([t.clientX,t.clientY])),this.hovered!==e&&this.render()},this.canvas.addEventListener("pointerdown",this.onPointerDown),this.canvas.addEventListener("mousemove",this.onMouseMove),window.addEventListener("resize",this.onResize)}getGrabber(t){let e;let s=this.cl2imgPt(t),i=this.remPx*this.options.theme.grabberHitboxFactor;for(let t in e=this.options.theme.cornerGrabberRadius*i,this.corners){let i=this.corners[t];if(M.withinRadius(s,i,e))return t}for(let t in e=this.options.theme.edgeGrabberRadius*i,this.edgeCenters){let i=this.edgeCenters[t];if(M.withinRadius(s,i,e))return t}if(e=this.options.theme.centerGrabberRadius*i,M.withinRadius(s,this.viewCenter.c,e))return"c"}discard(){window.removeEventListener("resize",this.onResize),this.canvas.removeEventListener("pointerdown",this.onPointerDown),window.removeEventListener("pointermove",this.onPointerMove),window.removeEventListener("pointerup",this.onPointerUp)}adjustDimensions(){let t=this.canvas.getBoundingClientRect(),e=this.imgH/t.height;this.remPx=parseFloat(getComputedStyle(document.documentElement).fontSize)*e,this.canvas.width=this.imgW+this.options.theme.cornerGrabberRadius*this.remPx*2,this.canvas.height=this.imgH+this.options.theme.cornerGrabberRadius*this.remPx*2,this.render()}render(){this.ctx.fillStyle=this.options.theme.backgroundColor,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height);let t=0,e=0;if(this.rotations&&(this.ctx.translate(this.canvas.width/2,this.canvas.height/2),this.ctx.rotate(this.rotations*(Math.PI/2)),t=this.rotations%2==0?-this.canvas.width/2:-this.canvas.height/2,e=this.rotations%2==0?-this.canvas.height/2:-this.canvas.width/2),this.ctx.drawImage(this.img,t+this.options.theme.cornerGrabberRadius*this.remPx,e+this.options.theme.cornerGrabberRadius*this.remPx,this.imgMat.cols,this.imgMat.rows),this.rotations&&(this.ctx.rotate(-this.rotations*(Math.PI/2)),this.ctx.translate(-this.canvas.width/2,-this.canvas.height/2)),this.corners){let t=Object.keys(this.corners),e=Object.keys(this.edgeCenters);if(this.options.theme.surroundingOverlayColor&&(this.ctx.beginPath(),this.ctx.fillStyle=this.options.theme.surroundingOverlayColor,this.ctx.moveTo(...this.img2ctxPt([0,0])),this.ctx.lineTo(...this.img2ctxPt([this.imgMat.cols,0])),this.ctx.lineTo(...this.img2ctxPt([this.imgMat.cols,this.imgMat.rows])),this.ctx.lineTo(...this.img2ctxPt([0,this.imgMat.rows])),this.ctx.lineTo(...this.img2ctxPt([0,0])),this.ctx.closePath(),this.ctx.moveTo(...this.img2ctxPt(this.corners.tl)),this.ctx.lineTo(...this.img2ctxPt(this.corners.tr)),this.ctx.lineTo(...this.img2ctxPt(this.corners.br)),this.ctx.lineTo(...this.img2ctxPt(this.corners.bl)),this.ctx.lineTo(...this.img2ctxPt(this.corners.tl)),this.ctx.closePath(),this.ctx.fill("evenodd")),this.options.theme.edgeThickness)for(let e=0;e<t.length;e++){let s=t[e],i=t[(e+1)%t.length],r=this.corners[s],h=this.corners[i],o=this.img2ctxPt(r),n=this.img2ctxPt(h);this.ctx.beginPath(),this.ctx.strokeStyle=this.options.theme.edgeColor,this.ctx.lineWidth=this.options.theme.edgeThickness*this.remPx,this.ctx.moveTo(...o),this.ctx.lineTo(...n),this.ctx.stroke()}if(this.options.theme.crossLineThickness)for(let t of[[this.edgeCenters.t,this.edgeCenters.b],[this.edgeCenters.l,this.edgeCenters.r]]){let e=this.img2ctxPt(t[0]),s=this.img2ctxPt(t[1]);this.ctx.beginPath(),this.ctx.strokeStyle=this.options.theme.crossLineColor,this.ctx.lineWidth=this.options.theme.crossLineThickness*this.remPx,this.ctx.moveTo(...e),this.ctx.lineTo(...s),this.ctx.stroke()}for(let s=0;s<t.length;s++){let i=t[s],r=e[s],h=this.corners[i],o=this.edgeCenters[r],n=this.img2ctxPt(h),a=this.img2ctxPt(o),c=this.hovered===i?this.options.theme.grabberExpansionFactor:1;if(this.ctx.beginPath(),this.ctx.fillStyle=this.options.theme.cornerGrabberColor,this.ctx.arc(...n,this.options.theme.cornerGrabberRadius*this.remPx*c,0,2*Math.PI),this.ctx.fill(),this.options.theme.edgeGrabberRadius){let t=this.hovered===r?this.options.theme.grabberExpansionFactor:1;this.ctx.beginPath(),this.ctx.fillStyle=this.options.theme.edgeGrabberColor,this.ctx.arc(...a,this.options.theme.edgeGrabberRadius*this.remPx*t,0,2*Math.PI),this.ctx.fill()}}if(this.options.theme.centerGrabberRadius){let t="c"===this.hovered?this.options.theme.grabberExpansionFactor:1,e=this.img2ctxPt(this.viewCenter.c);this.ctx.beginPath(),this.ctx.fillStyle=this.options.theme.centerGrabberColor,this.ctx.arc(...e,this.options.theme.centerGrabberRadius*this.remPx*t,0,2*Math.PI),this.ctx.fill()}if(this.options.theme.zoomLensRadius&&this.dragged&&!(this.dragged in this.viewCenter)){let t,e,s,i;if(this.dragged in this.corners)t=this.corners[this.dragged],e=({tl:[1,1],tr:[-1,1],br:[-1,-1],bl:[1,-1]})[this.dragged],s=M.angleBetween(this.corners[this.dragged],this.corners[M.rotateKey(this.corners,this.dragged,-1)]),i=M.angleBetween(this.corners[this.dragged],this.corners[M.rotateKey(this.corners,this.dragged,1)]);else if(this.dragged in this.edgeCenters){t=this.edgeCenters[this.dragged],e=({t:[0,1],r:[-1,0],b:[0,-1],l:[1,0]})[this.dragged];let r=Object.keys(this.corners),h=Object.keys(this.edgeCenters).indexOf(this.dragged),o=r[M.rotateVal(h,0,r.length)];i=(s=M.angleBetween(this.edgeCenters[this.dragged],this.corners[o]))+Math.PI}s+=this.rotations*(Math.PI/2),i+=this.rotations*(Math.PI/2);let r=this.img2ctxPt(t);r=[r[0]+e[0]*(this.options.theme.zoomLensRadius+this.options.theme.zoomLensMargin)*this.remPx,r[1]+e[1]*(this.options.theme.zoomLensRadius+this.options.theme.zoomLensMargin)*this.remPx];let h=this.options.theme.zoomLensRadius*this.remPx,o=h/(this.options.theme.zoomLensFactor||1);this.ctx.beginPath(),this.ctx.strokeStyle=this.options.theme.zoomLensBorderColor,this.ctx.lineWidth=this.options.theme.zoomLensBorderThickness*this.remPx,this.ctx.arc(...r,h,0,2*Math.PI),this.ctx.stroke(),this.ctx.save(),this.ctx.beginPath(),this.ctx.arc(...r,this.options.theme.zoomLensRadius*this.remPx,0,2*Math.PI),this.ctx.clip(),this.ctx.fillStyle=this.options.theme.backgroundColor,this.ctx.fillRect(r[0]-h,r[1]-h,2*h,2*h),this.rotations&&(this.ctx.translate(r[0],r[1]),this.ctx.rotate(this.rotations*(Math.PI/2)),this.ctx.translate(-r[0],-r[1])),this.ctx.drawImage(this.img,t[0]-o,t[1]-o,2*o,2*o,r[0]-h,r[1]-h,2*h,2*h),this.ctx.restore(),this.ctx.beginPath(),this.ctx.fillStyle=this.options.theme.zoomLensOverlayColor,this.ctx.moveTo(...r),this.ctx.lineTo(...M.ptAtAngle(r,s,h)),this.ctx.arc(...r,h,s,i),this.ctx.lineTo(...r),this.ctx.fill()}}else this.ctx.fillStyle="rgba(0,0,0,0.5)",this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)}setDragged(t){this.dragged=t,this.canvas.style.cursor=t?"grabbing":"default",this.setHovered(t)}setHovered(t){this.hovered=t,this.dragged||(this.canvas.style.cursor=t?"grab":"default")}getResult(e,s){let i=new t.Mat,r=t.matFromArray(4,1,t.CV_32FC2,[...this.corners.tl,...this.corners.tr,...this.corners.bl,...this.corners.br]),h=(M.ptDistance(this.corners.tl,this.corners.tr)+M.ptDistance(this.corners.bl,this.corners.br))/2,o=(M.ptDistance(this.corners.tl,this.corners.bl)+M.ptDistance(this.corners.tr,this.corners.br))/2,n=t.matFromArray(4,1,t.CV_32FC2,[0,0,h,0,0,o,h,o]),a=t.getPerspectiveTransform(r,n);t.warpPerspective(this.imgMat,i,a,new t.Size(h,o),t.INTER_LINEAR,t.BORDER_CONSTANT,new t.Scalar);let c=new Image,l=document.createElement("canvas");return t.imshow(l,i),c.src=l.toDataURL(e,s),c}rotateLeft(){this.rotate("left")}rotateRight(){this.rotate("right")}rotate(t){let e="left"===t,{tl:s,tr:i,br:r,bl:h}=this.corners;this.corners={tl:e?i:h,tr:e?r:s,br:e?h:i,bl:e?s:r},this.rotations=M.rotateVal(this.rotations,e?-1:1,4),this.imgW=this.rotations%2==0?this.imgMat.cols:this.imgMat.rows,this.imgH=this.rotations%2==0?this.imgMat.rows:this.imgMat.cols,this.canvas.width=this.imgW,this.canvas.height=this.imgH,this.updateCenters(),this.adjustDimensions()}updateCenters(){this.edgeCenters=this.corners?M.edgeCenters(this.corners):void 0,this.viewCenter=this.corners?{c:M.cornerCenter(this.corners)}:void 0}getRotations(){return this.rotations}getCorners(){let{tl:t,tr:e,br:s,bl:i}=this.corners;return{tl:[t[0],t[1]],tr:[e[0],e[1]],br:[s[0],s[1]],bl:[i[0],i[1]]}}img2ctxPt(t){let e=this.options.theme.cornerGrabberRadius;return 0===this.rotations?[t[0]+e*this.remPx,t[1]+e*this.remPx]:1===this.rotations?[this.imgW-t[1]+e*this.remPx,t[0]+e*this.remPx]:2===this.rotations?[this.imgW-t[0]+e*this.remPx,this.imgH-t[1]+e*this.remPx]:3===this.rotations?[t[1]+e*this.remPx,this.imgH-t[0]+e*this.remPx]:void 0}ctx2imgPt(t){let e=this.options.theme.cornerGrabberRadius;return 0===this.rotations?[t[0]-e*this.remPx,t[1]-e*this.remPx]:1===this.rotations?[t[1]-e*this.remPx,this.imgW-t[0]+e*this.remPx]:2===this.rotations?[this.imgW-t[0]+e*this.remPx,this.imgH-t[1]+e*this.remPx]:3===this.rotations?[this.imgH-t[1]+e*this.remPx,t[0]-e*this.remPx]:void 0}cl2imgPt(t){let e=this.canvas.getBoundingClientRect(),s=this.canvas.width/e.width,i=this.canvas.height/e.height;return this.ctx2imgPt([(t[0]-e.left)*s,(t[1]-e.top)*i])}}export{C as default};
//# sourceMappingURL=intellicrop.js.map