import{sleep,waitFor}from"../base/helpers.mjs";function noop(t){let s=t[this.thread.y][this.thread.x];this.color(s[0],s[1],s[2],s[3])}function makeSeed(t,s){return new Array(t).fill(null).map((()=>new Array(s).fill(null).map((()=>Math.random()))))}class ImageFilter{static filterFunction=noop;constructor(t,s=!0,e={}){this.source=t,this.image=new Image,this.executeOnLoad=s,this.image.onload=()=>this.onload(),this.image.src=t,this.loaded=!1,this.initializationConstants={...e},this.constants={}}onload(){this.loaded=!0,void 0===this.canvas&&(this.canvas=document.createElement("canvas")),this.canvas.width=this.image.width,this.canvas.height=this.image.height,this.canvas.classList.add("image-filter"),this.reset(this.executeOnLoad)}setImage(t){this.source=t,this.loaded=!1,this.image=new Image,this.image.onload=()=>{this.canvas.width=this.image.width,this.canvas.height=this.image.height,this.constants.seed=this.seed,this.loaded=!0,this.execute()},this.image.src=t}awaitLoad(){return waitFor((()=>this.loaded))}get context(){return null!==this.canvasContext&&void 0!==this.canvasContext||(this.canvasContext=this.canvas.getContext("webgl",{preserveDrawingBuffer:!0})),this.canvasContext}get imageSource(){return this.canvas.toDataURL("image/jpg")}compileKernel(){return new Promise((t=>{this.getGPU().then((s=>{const e=s.createKernel(this.constructor.filterFunction).setConstants({...this.constants}).setOutput([this.image.width,this.image.height]).setGraphical(!0);t(e)}))}))}execute(){return new Promise((t=>{this.compileKernel().then((s=>{s(this.image),t()}))}))}get seed(){return makeSeed(this.image.height,this.image.width)}getGPU(){if(void 0!==this.gpu)return Promise.resolve(this.gpu);let t=GPU.GPU;return void 0===GPU.GPU&&"function"==typeof GPU&&(t=GPU),new Promise((s=>{this.awaitLoad().then((()=>{this.gpu=new t({canvas:this.canvas,context:this.context}),s(this.gpu)}))}))}getCanvas(){return new Promise((t=>{this.awaitLoad().then((()=>{t(this.canvas)}))}))}getImage(){return new Promise((t=>{this.awaitLoad().then((()=>{let s=new Image;s.onload=()=>{t(s)},s.src=this.imageSource}))}))}reset(t=!0){this.constants={width:this.image.width,height:this.image.height,seed:this.seed,...this.initializationConstants},t&&this.execute()}setConstants(t,s=!0){this.constants.width=this.image.width,this.constants.height=this.image.height,this.constants.seed=this.seed,s&&this.execute()}static testFilter(t=10,s=10){let e=new this;e.reset(!1);let i={...e.constants},a={x:0,y:0},n=new Array(t).fill(null).map((()=>new Array(s).fill(null))),h=new Array(t).fill(null).map((()=>new Array(s).fill(null).map((()=>[Math.random(),Math.random(),Math.random(),1])))),r={constants:i,thread:a,color:(t,s,e,i)=>n[a.y][a.x]=[t,s,e,i]};i.width=s,i.height=t,i.seed=makeSeed(t,s);for(let e=0;e<t;e++)for(let t=0;t<s;t++)r.thread.y=e,r.thread.x=t,this.filterFunction.call(r,h);return n}}function matrixConvolution(t){const s=this.thread.x,e=this.thread.y;let i=[0,0,0];for(let a=-this.constants.radius;a<=this.constants.radius;a++)for(let n=-this.constants.radius;n<=this.constants.radius;n++){const h=Math.min(Math.max(0,e+a),this.constants.height-1),r=Math.min(Math.max(0,s+n),this.constants.width-1),o=t[h][r],c=this.constants.matrix[a+this.constants.radius][n+this.constants.radius];i[0]=i[0]+o[0]*c,i[1]=i[1]+o[1]*c,i[2]=i[2]+o[2]*c}this.color(i[0],i[1],i[2],1)}class MatrixImageFilter extends ImageFilter{static filterFunction=matrixConvolution;getMatrix(){let t=new Array(2*this.constants.radius+1).fill(null).map((()=>new Array(2*this.constants.radius+1).fill(0)));return t[this.constants.radius][this.constants.radius]=1,t}reset(t=!0){super.reset(!1),this.constants.radius=1,this.constants.matrix=this.getMatrix(),t&&this.execute()}setConstants(t,s=!0){super.setConstants(t,!1),this.constants.radius=parseInt(void 0===t.radius?this.constants.radius:t.radius),this.constants.matrix=this.getMatrix(),s&&this.execute()}set radius(t){this.constants.radius=parseInt(t),this.constants.matrix=this.getMatrix(),this.execute()}}class WeightedMatrixImageFilter extends MatrixImageFilter{reset(t=!0){super.reset(!1),this.constants.weight=0,this.constants.matrix=this.getMatrix(),t&&this.execute()}setConstants(t,s=!0){this.constants.weight=parseInt(void 0===t.weight?this.constants.weight:t.weight),super.setConstants(t,s)}set weight(t){this.constants.weight=parseInt(t),this.constants.matrix=this.getMatrix(),this.execute()}}export{ImageFilter,MatrixImageFilter,WeightedMatrixImageFilter};
