asciify-engine 4.2.0 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/{ambient-motion-CqF5-eZ2.d.cts → ambient-motion-C2qG4xUI.d.cts} +16 -1
- package/dist/{ambient-motion-CqF5-eZ2.d.ts → ambient-motion-C2qG4xUI.d.ts} +16 -1
- package/dist/core.cjs +1 -1
- package/dist/core.d.cts +4 -4
- package/dist/core.d.ts +4 -4
- package/dist/core.js +1 -1
- package/dist/hover.cjs +1 -1
- package/dist/hover.d.cts +3 -3
- package/dist/hover.d.ts +3 -3
- package/dist/hover.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/{model-CDiABFst.d.cts → model-CIiVhaQf.d.cts} +2 -2
- package/dist/{model-BbKQNvhk.d.ts → model-S1T5tuQG.d.ts} +2 -2
- package/dist/studio.cjs +1 -1
- package/dist/studio.d.cts +3 -3
- package/dist/studio.d.ts +3 -3
- package/dist/studio.js +1 -1
- package/dist/{types-BeXEm4UY.d.cts → types-CZdZg9Mw.d.cts} +1 -1
- package/dist/{types-BeXEm4UY.d.ts → types-CZdZg9Mw.d.ts} +1 -1
- package/package.json +1 -1
- package/skills/asciify-engine/SKILL.md +2 -2
- package/skills/asciify-engine/references/studio-workspace.md +18 -0
package/dist/studio.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var t=["ascii","blocks","braille","dots","lines","cross","diagonal","diamond","mixed","pixel","mosaic","lego","voxel","disco","dither","hex","led","cmyk"],e=["none","bayer2","bayer4","bayer8","bayer16","floyd-steinberg","atkinson","stucki","sierra","sierra-lite","burkes","jarvis","halftone","lines","noise","vertical-lines","diagonal-lines","radial"],i=["source-over","multiply","screen","overlay","soft-light","hard-light","color-dodge","color-burn","hue","saturation","color","luminosity"],s={original:[],gray4:["#000000","#555555","#aaaaaa","#ffffff"],gray8:["#000000","#242424","#494949","#6d6d6d","#929292","#b6b6b6","#dbdbdb","#ffffff"],rgb8:["#000000","#ff0000","#00ff00","#0000ff","#ffff00","#ff00ff","#00ffff","#ffffff"],cyberpunk:["#08081a","#3c1670","#ed299a","#29dfef","#fff7bf"],pastel:["#393448","#a5b4d4","#9ed9c6","#e7aac1","#f5e8be"],mono:["#080808","#f2f2e8"],asciify:["#080808","#625b38","#a19558","#e8b900"],gameboy:["#0f380f","#306230","#8bac0f","#9bbc0f"],cga:["#000000","#55ffff","#ff55ff","#ffffff"],pico8:["#000000","#1d2b53","#7e2553","#008751","#ab5236","#5f574f","#c2c3c7","#fff1e8","#ff004d","#ffa300","#ffec27","#00e436","#29adff","#83769c","#ff77a8","#ffccaa"],c64:["#000000","#ffffff","#880000","#aaffee","#cc44cc","#00cc55","#0000aa","#eeee77","#dd8855","#664400","#ff7777","#333333","#777777","#aaff66","#0088ff","#bbbbbb"],amber:["#100b00","#5f3b00","#c98014","#ffd17c"],ice:["#081b29","#25586e","#69a6b3","#d9ece7"],risograph:["#f4ebd0","#f2594b","#2853a5","#29232e"],sepia:["#201b17","#6b5039","#b49868","#f6e6c5"],nord:["#2e3440","#4c566a","#88c0d0","#eceff4"],dusk:["#211b35","#654271","#c3788c","#f5c9a3"],forest:["#101f1b","#355747","#87a16f","#e4e3ba"],ocean:["#071b33","#17577f","#3fa7a4","#d9efde"],newsprint:["#191919","#666666","#aaaaaa","#eee9df"],custom:["#080808","#e8b900"]},a={version:1,aspectRatio:"original",style:"ascii",cellSize:6,charset:" .:-=+*#%@",colorMode:"accent",ink:"#e8b900",crop:{x:.5,y:.5,zoom:1,rotation:0},backdrop:{mode:"solid",color:"#080808",color2:"#393323",blur:12,opacity:1},color:{brightness:0,contrast:1,saturation:1,grayscale:0,tint:"#e8b900",amount:0,blend:"source-over"},dither:{algorithm:"none",palette:"mono",colors:["#080808","#e8b900"],amount:1,scale:2,threshold:.5,motion:"none",speed:1,direction:45,colorSpace:"rgb"},mask:{enabled:!1,invert:!1,shapes:[]},lights:[],effects:{bloom:0,characterBloom:0,grain:0,dust:0,scanlines:0,crt:0,prism:0,rgbSplit:0,sharpen:0,vignette:0,glitch:0,pixelate:0,blur:0,blurType:"gaussian",angle:0,focus:.5,halftone:0},motion:{type:"none",speed:1,amount:1},hover:{effect:"trail",strength:.55,radius:.2,edgeSafe:!1}},r=t=>t&&"object"==typeof t&&!Array.isArray(t)?t:{},o=(t,e,i,s)=>"number"==typeof t&&Number.isFinite(t)?Math.min(s,Math.max(i,t)):e,n=(t,e)=>"string"==typeof t&&/^#[\da-f]{6}$/i.test(t)?t:e,h=(t,e,i)=>e.includes(t)?t:i;function l(l={}){const c=r(l),f=a;if(void 0!==c.version&&1!==c.version)throw new Error("Unsupported studio settings version. Update asciify-engine.");const m=r(c.crop),d=r(c.backdrop),u=r(c.color),g=r(c.dither),p=r(c.mask),M=r(c.effects),x=r(c.motion),v=r(c.hover),b={...f.effects};for(const t of["bloom","characterBloom","grain","dust","scanlines","crt","prism","rgbSplit","sharpen","vignette","glitch","pixelate","halftone"])b[t]=o(M[t],0,0,1);b.blur=o(M.blur,0,0,24),b.blurType=h(M.blurType,["gaussian","directional","radial","progressive"],f.effects.blurType),b.angle=o(M.angle,0,-180,180),b.focus=o(M.focus,.5,0,1);let w=2048;return{version:1,aspectRatio:h(c.aspectRatio,["original","16:9","9:16","1:1","4:3","3:4","21:9"],"original"),style:h(c.style,t,f.style),cellSize:o(c.cellSize,f.cellSize,["pixel","mosaic","lego","voxel","disco","dots","hex","led","cmyk"].includes(String(c.style))?1:3,60),charset:"string"==typeof c.charset&&c.charset.length?Array.from(c.charset).slice(0,128).join(""):f.charset,colorMode:h(c.colorMode,["accent","source","gray"],f.colorMode),ink:n(c.ink,f.ink),crop:{x:o(m.x,.5,0,1),y:o(m.y,.5,0,1),zoom:o(m.zoom,1,1,5),rotation:90*Math.round(o(m.rotation,0,-360,360)/90)},backdrop:{mode:h(d.mode,["solid","transparent","source","blurred","gradient"],f.backdrop.mode),color:n(d.color,f.backdrop.color),color2:n(d.color2,f.backdrop.color2),blur:o(d.blur,12,0,32),opacity:o(d.opacity,1,0,1)},color:{brightness:o(u.brightness,0,-1,1),contrast:o(u.contrast,1,0,3),saturation:o(u.saturation,1,0,3),grayscale:o(u.grayscale,0,0,1),tint:n(u.tint,f.color.tint),amount:o(u.amount,0,0,1),blend:h(u.blend,i,f.color.blend)},dither:{algorithm:h(g.algorithm,e,"none"),palette:"string"==typeof g.palette&&Object.prototype.hasOwnProperty.call(s,g.palette)?g.palette:"mono",colors:Array.isArray(g.colors)&&g.colors.length>=2?g.colors.slice(0,32).map(t=>n(t,"#000000")):[...f.dither.colors],amount:o(g.amount,1,0,2),scale:Math.round(o(g.scale,2,1,12)),threshold:o(g.threshold,.5,0,1),motion:h(g.motion,["none","drift","shimmer"],"none"),speed:o(g.speed,1,.1,3),direction:o(g.direction,45,-180,180),colorSpace:h(g.colorSpace,["rgb","luminance"],"rgb")},mask:{enabled:!0===p.enabled,invert:!0===p.invert,shapes:Array.isArray(p.shapes)?p.shapes.slice(0,64).map(t=>{const e=r(t),i=h(e.kind,["rectangle","ellipse","brush"],"rectangle"),s="brush"===i&&Array.isArray(e.points)?e.points.slice(0,w).map(t=>Array.isArray(t)?[Math.round(1e4*o(t[0],0,0,1))/1e4,Math.round(1e4*o(t[1],0,0,1))/1e4]:[0,0]):[];return w-=s.length,{kind:i,x:o(e.x,0,0,1),y:o(e.y,0,0,1),width:o(e.width,.5,0,1),height:o(e.height,.5,0,1),size:o(e.size,.05,.005,.5),points:s}}):[]},lights:Array.isArray(c.lights)?c.lights.slice(0,4).map(t=>{const e=r(t);return{x:o(e.x,.5,0,1),y:o(e.y,.5,0,1),radius:o(e.radius,.3,.02,1),intensity:o(e.intensity,.5,0,1),color:n(e.color,"#ffffff")}}):[],effects:b,motion:{type:h(x.type,["none","caustics","current","reform"],"none"),speed:o(x.speed,1,.1,3),amount:o(x.amount,1,0,2)},hover:{effect:h(v.effect,["none","trail","water","contour","dissolve","silk","vortex"],"trail"),strength:o(v.strength,.55,0,1),radius:o(v.radius,.2,.1,1),edgeSafe:!0===v.edgeSafe}}}function c(t){return JSON.stringify(l(t))}function f(t){if(t.length>1e5)throw new Error("Settings exceed 100 KB.");return l(JSON.parse(t))}function m(t,e,i,s,a){const r=Math.abs(a.rotation/90)%2==1,o=r?e:t,n=r?t:e,h=Math.max(i/o,s/n)*a.zoom;return{width:o*h,height:n*h,x:(i-o*h)*a.x,y:(s-n*h)*a.y,scale:h,rotated:r}}function d(t,e,i){if(Math.abs(i.crop.rotation/90)%2==1&&([t,e]=[e,t]),"original"===i.aspectRatio)return[t,e];const[s,a]=i.aspectRatio.split(":").map(Number);return t/e>s/a?[Math.round(e*s/a),e]:[t,Math.round(t*a/s)]}function u(t,e){const i={...t,...e};for(const s of["crop","backdrop","color","dither","mask","effects","motion","hover"])e[s]&&Object.assign(i,{[s]:{...t[s],...e[s]}});return l(i)}function g(t,e,i,s=12e3,a=1){const r=Math.max(2,Number.isFinite(t)?t:960),o=Math.max(2,Number.isFinite(e)?e:540),n=Math.max(1,Math.floor(Number.isFinite(s)?s:12e3)),h=Math.max(.01,Number.isFinite(a)?a:1),l=["dither","pixel","mosaic","lego","voxel","disco","dots","hex","led","cmyk"].includes(i.style)?1:1.65;let c=Math.max(1,Math.ceil(Math.sqrt(r*o/(n*l))/h));for(;Math.ceil(r/(c*h))*Math.ceil(o/(c*h*l))>n;)c++;const f="dither"===i.style?i.dither.scale:i.cellSize,m=Math.max(c,f)*h;return{cell:m,rowHeight:m*l,columns:Math.ceil(r/m),rows:Math.ceil(o/(m*l)),minimum:c,limited:f<c}}var p=[["ascii","Signature ASCII","Brand ink and clean characters.",{}],["print","Newsprint","Fine diffusion on warm paper.",{style:"dither",dither:{algorithm:"floyd-steinberg",palette:"newsprint"}}],["handheld","Pocket camera","Four-tone ordered dither.",{style:"dither",dither:{algorithm:"bayer4",palette:"gameboy",scale:3}}],["riso","Two inks","Limited-color print texture.",{style:"dither",dither:{algorithm:"atkinson",palette:"risograph",scale:2}}],["night","Night signal","Gray characters and optical fringe.",{ink:"#888888",effects:{prism:.7,scanlines:.2,vignette:.3}}],["terminal","Phosphor","Green glyphs with a soft glow.",{ink:"#83efad",effects:{bloom:.4,scanlines:.35,crt:.2}}],["mosaic","Mosaic study","Separated color tiles.",{style:"mosaic",cellSize:14,colorMode:"source"}],["bricks","Brickwork","Colorful studded cells.",{style:"lego",cellSize:18,colorMode:"source"}],["voxel","Little volumes","Three-face isometric tiles.",{style:"voxel",cellSize:22,colorMode:"source"}],["disco","Mirror room","Faceted tiles and warm light.",{style:"disco",cellSize:18,colorMode:"source",lights:[{x:.35,y:.25,radius:.25,intensity:.45,color:"#fff2d4"}]}],["wallpaper","Wallpaper","Living ASCII over a softened source.",{backdrop:{mode:"blurred",blur:18,opacity:.55},ink:"#f2e9c9",motion:{type:"caustics",speed:.5}}],["blueprint","Blueprint","Linework in a cool monochrome.",{style:"lines",ink:"#9bccdf",backdrop:{mode:"solid",color:"#0a1e30"}}]].map(([t,e,i,s])=>({id:t,name:e,description:i,settings:l(s)}));function M(t){const e=p.find(e=>e.id===t);if(!e)throw new Error("Unknown studio look.");return l(e.settings)}function x(t,e=Math.random){const i=p.filter(e=>e.settings.style!==t.style||e.settings.ink!==t.ink),s=M(i[Math.min(i.length-1,Math.max(0,Math.floor(e()*i.length)))].id);return s.aspectRatio=t.aspectRatio,s.crop={...t.crop},s.mask=l(t).mask,s}var v=[{value:"none",mode:"none",label:"Off",description:"Keep the image still. Hover stays available."},{value:"caustics",mode:"caustics",label:"Caustics",description:"Soft ribbons of light travel across a stationary character grid."},{value:"current",mode:"current",label:"Slow Current",description:"A gentle flow through the image, with steady edges."},{value:"reform",mode:"reform",label:"Reveal & Reform",description:"Disperse, gather, then hold the complete image."}],b=t=>Math.max(0,Math.min(1,t)),w=(t,e,i)=>{const s=b((i-t)/(e-t));return s*s*(3-2*s)},y=class{constructor(){this.last=null,this.mode="none",this.phase=0}update(t,e,i=1){return Number.isFinite(t)?((e!==this.mode||null!==this.last&&t<this.last)&&(this.mode=e,this.phase=0,this.last=t),null!==this.last&&(this.phase+=Math.max(0,t-this.last)*Math.max(.1,Math.min(3,Number.isFinite(i)?i:1))),this.last=t,this.phase):this.phase}};function S(t,e,i,s,a){if(a[0]=a[1]=a[2]=0,a[3]=1,"none"===t)return a;const r=s*Math.PI/6,o=w(0,.12,Math.min(e,1-e,i,1-i));if("caustics"===t){const t=Math.sin(9*e+5*i+r)+Math.sin(8*i-3*e-r),s=Math.pow(Math.max(0,1-.72*Math.abs(t)),3);a[2]=(.22*s-.045)*o}else if("current"===t)a[0]=Math.sin(9*i+r)*Math.cos(7*e-r)*10*o,a[1]=Math.cos(8*e+r)*Math.sin(6*i-r)*7*o;else if("reform"===t){const t=(s%12+12)%12,n=((t,e)=>{const i=(.06711056*t+.00583715*e)%1*52.9829189;return i-Math.floor(i)})(Math.floor(160*e),Math.floor(100*i)),h=.65*e+.2*i+.15*n+.08*Math.sin(8*e-5*i),l=w(1.8+1.2*h,3.8+1.2*h,t)*(1-w(5+1.7*h,7.2+1.7*h,t));a[0]=Math.sin(9*i+r)*l*(1-l)*24*o,a[1]=-l*(1-l)*(8+12*n)*o,a[2]=.45*-l,a[3]=1-.9*l}return a}function k(t,e){const i=Math.max(0,Math.min(2,Number.isFinite(e)?e:1));return t[0]*=i,t[1]*=i,t[2]*=i,t[3]=b(1+(t[3]-1)*i),t}var E=(t,e)=>{const i=43758.5453*Math.sin(127.1*t+311.7*e);return i-Math.floor(i)};function A(t,e,i){let s=0;for(let a=1;a<i;a*=2){const i=(Math.floor(t/a)%2+2)%2;s=4*s+[[0,2],[3,1]][(Math.floor(e/a)%2+2)%2][i]}return(s+.5)/(i*i)-.5}var F={"floyd-steinberg":[[1,0,7/16],[-1,1,3/16],[0,1,5/16],[1,1,1/16]],atkinson:[[1,0,.125],[2,0,.125],[-1,1,.125],[0,1,.125],[1,1,.125],[0,2,.125]],stucki:[[1,0,8/42],[2,0,4/42],[-2,1,2/42],[-1,1,4/42],[0,1,8/42],[1,1,4/42],[2,1,2/42],[-2,2,1/42],[-1,2,2/42],[0,2,4/42],[1,2,2/42],[2,2,1/42]],sierra:[[1,0,5/32],[2,0,3/32],[-2,1,2/32],[-1,1,4/32],[0,1,5/32],[1,1,4/32],[2,1,2/32],[-1,2,2/32],[0,2,3/32],[1,2,2/32]],"sierra-lite":[[1,0,.5],[-1,1,.25],[0,1,.25]],burkes:[[1,0,.25],[2,0,4/32],[-2,1,2/32],[-1,1,4/32],[0,1,.25],[1,1,4/32],[2,1,2/32]],jarvis:[[1,0,7/48],[2,0,5/48],[-2,1,3/48],[-1,1,5/48],[0,1,7/48],[1,1,5/48],[2,1,3/48],[-2,2,1/48],[-1,2,3/48],[0,2,5/48],[1,2,3/48],[2,2,1/48]]},T=t=>[parseInt(t.slice(1,3),16),parseInt(t.slice(3,5),16),parseInt(t.slice(5,7),16)];function I(t,e,i){const s=Math.min(t*Math.max(1,i),(1-t)*Math.max(1,i),e*Math.max(1,1/i),(1-e)*Math.max(1,1/i)),a=Math.max(0,Math.min(1,(s-.035)/.105));return a*a*a*(a*(6*a-15)+10)}var P=class{constructor(t,e){this.edgeSafe=!1,this.previous=null,this.peak=0,this.mode="dissolve",this.width=t,this.height=e;const i=t*e;this.pixels=new Uint8Array(4*i),this.ink=new Float32Array(i),this.targetX=new Float32Array(i),this.targetY=new Float32Array(i),this.offsetX=new Float32Array(i),this.offsetY=new Float32Array(i),this.edge=new Float32Array(i);for(let i=0;i<e;i++)for(let s=0;s<t;s++)this.edge[i*t+s]=I(s/(t-1),i/(e-1),t/e);this.clear()}get active(){return this.peak>2e-4}setMode(t){t!==this.mode&&(this.mode=t,this.clear())}clear(){for(const t of[this.ink,this.targetX,this.targetY,this.offsetX,this.offsetY,this.pixels])t.fill(0);if(this.previous=null,this.peak=0,"dissolve"!==this.mode)for(let t=0;t<this.pixels.length;t+=4)this.pixels[t]=this.pixels[t+2]=128}leave(){this.previous=null}move(t,e,i){if(!Number.isFinite(t+e+i))return;t=Math.max(0,Math.min(1,t)),e=Math.max(0,Math.min(1,e));const s=this.previous;this.previous={x:t,y:e};const a=this.width,r=this.height,o=Math.max(1,a/r),n=Math.max(1,r/a),h=s?(t-s.x)*o:0,l=s?(e-s.y)*n:0,c=Math.hypot(h,l);if(!s&&"dissolve"!==this.mode)return;if(s&&c<1e-4)return;const f=.035+.11*Math.max(.1,Math.min(1,i)),m=Math.min(128,Math.max(1,Math.ceil(c/(.45*f)))),d=c?h/c:1,u=c?l/c:0,g=Math.min(1,c/(f*m)*2.2);for(let i=0;i<m;i++){const h=(i+.5)/m,l=s?s.x+(t-s.x)*h:t,c=s?s.y+(e-s.y)*h:e,p=Math.max(0,Math.floor((l-2.5*f/o)*(a-1))),M=Math.min(a-1,Math.ceil((l+2.5*f/o)*(a-1))),x=Math.max(0,Math.floor((c-2.5*f/n)*(r-1))),v=Math.min(r-1,Math.ceil((c+2.5*f/n)*(r-1)));for(let t=x;t<=v;t++)for(let e=p;e<=M;e++){const i=(e/(a-1)-l)*o/f,s=(t/(r-1)-c)*n/f,h=Math.exp(1.5*-(i*i+s*s)),m=t*a+e;if("dissolve"===this.mode)this.ink[m]=Math.max(this.ink[m],h);else{const t=(-i*u+s*d)*h*2.8,e="silk"===this.mode?d*t:-s*h*2.5,a="silk"===this.mode?u*t:i*h*2.5;this.targetX[m]=Math.max(-1,Math.min(1,this.targetX[m]+e*g)),this.targetY[m]=Math.max(-1,Math.min(1,this.targetY[m]+a*g))}}}this.peak=1}step(t){if(!this.active||!Number.isFinite(t))return;const e=Math.max(0,Math.min(.05,t)),i=Math.exp(-("dissolve"===this.mode?2.15:3.2)*e),s=1-Math.exp(-22*e);let a=0;for(let t=0;t<this.ink.length;t++)if("dissolve"===this.mode){this.ink[t]*=i,a=Math.max(a,this.ink[t]);const e=Math.round(65535*this.ink[t]);this.pixels[4*t]=e>>>8,this.pixels[4*t+1]=255&e}else{this.targetX[t]*=i,this.targetY[t]*=i,this.offsetX[t]+=(this.targetX[t]-this.offsetX[t])*s,this.offsetY[t]+=(this.targetY[t]-this.offsetY[t])*s,a=Math.max(a,Math.abs(this.offsetX[t]),Math.abs(this.offsetY[t]),Math.abs(this.targetX[t]),Math.abs(this.targetY[t]));const e=Math.round(this.offsetX[t]*(this.edgeSafe?this.edge[t]:1)*32767+32768),r=Math.round(this.offsetY[t]*(this.edgeSafe?this.edge[t]:1)*32767+32768);this.pixels[4*t]=e>>>8,this.pixels[4*t+1]=255&e,this.pixels[4*t+2]=r>>>8,this.pixels[4*t+3]=255&r}this.peak=a,this.active||this.clear()}sample(t,e,i){const s=Math.max(0,Math.min(this.width-1.001,t*(this.width-1))),a=Math.max(0,Math.min(this.height-1.001,e*(this.height-1))),r=Math.floor(s),o=Math.floor(a),n=s-r,h=a-o,l=o*this.width+r,c=l+this.width,f=t=>(t[l]*(1-n)+t[l+1]*n)*(1-h)+(t[c]*(1-n)+t[c+1]*n)*h;i[0]=f(this.offsetX)*(this.edgeSafe?I(t,e,this.width/this.height):1)*.08,i[1]=f(this.offsetY)*(this.edgeSafe?I(t,e,this.width/this.height):1)*.08,i[2]="dissolve"===this.mode?6*-f(this.ink):0}},R=class{constructor(t,e){this.rings=[],this.previous=null,this.elapsed=1,this.echoPeak=0,this.width=t,this.height=e,this.pixels=new Uint8Array(t*e*4),this.echo=new Float32Array(t*e)}get active(){return this.rings.length>0||this.echoPeak>2e-4}clear(){this.rings=[],this.previous=null,this.elapsed=1,this.pixels.fill(0),this.echo.fill(0),this.echoPeak=0}leave(){this.previous=null}move(t,e,i){const s=Math.max(1,this.width/this.height),a=Math.max(1,this.height/this.width);this.previous&&(Math.hypot((t-this.previous.x)*s,(e-this.previous.y)*a)<.065||this.elapsed<.3)||4!==this.rings.length&&(this.previous={x:t,y:e},this.elapsed=0,this.rings.push({x:t,y:e,age:0,radius:i}))}ringSample(t,e){const i=Math.max(1,this.width/this.height),s=Math.max(1,this.height/this.width);let a=0;for(const r of this.rings){const o=.015+r.age*(.15+.22*r.radius),n=.009+.014*r.radius,h=(Math.hypot((t-r.x)*i,(e-r.y)*s)-o)/n,l=Math.sin(Math.min(1,r.age/.07)*Math.PI/2)*Math.max(0,1-r.age/1.35)**2;a=Math.max(a,Math.exp(-h*h)*l)}return a}sample(t,e){const i=Math.max(0,Math.min(this.width-1,Math.round(t*(this.width-1)))),s=Math.max(0,Math.min(this.height-1,Math.round(e*(this.height-1))));return Math.max(this.ringSample(t,e),this.echo[s*this.width+i])}step(t){if(!Number.isFinite(t))return;const e=Math.max(0,Math.min(.05,t));this.elapsed+=e;for(const t of this.rings)t.age+=e;if(this.rings=this.rings.filter(t=>t.age<1.35),!this.active)return void this.pixels.fill(0);const i=Math.exp(-5.5*e);let s=0;for(let t=0;t<this.height;t++)for(let e=0;e<this.width;e++){const a=t*this.width+e;this.echo[a]=Math.max(this.ringSample(e/(this.width-1),t/(this.height-1)),this.echo[a]*i),s=Math.max(s,this.echo[a]);const r=Math.round(65535*this.echo[a]),o=4*a;this.pixels[o]=r>>>8,this.pixels[o+1]=255&r}this.echoPeak=s,this.active||(this.echo.fill(0),this.pixels.fill(0))}},C=class{constructor(t,e){this.previous=null,this.peak=0,this.width=t,this.height=e;const i=t*e;this.pixels=new Uint8Array(4*i),this.signal=new Float32Array(i),this.offsetX=new Float32Array(i),this.offsetY=new Float32Array(i),this.driftX=new Float32Array(i),this.driftY=new Float32Array(i),this.u=new Float32Array(i),this.v=new Float32Array(i),this.ink=new Float32Array(i),this.a=new Float32Array(i),this.b=new Float32Array(i),this.c=new Float32Array(i),this.pressure=new Float32Array(i),this.pressureNext=new Float32Array(i),this.divergence=new Float32Array(i),this.curl=new Float32Array(i)}get active(){return this.peak>2e-4}clear(){for(const t of[this.u,this.v,this.ink,this.a,this.b,this.c,this.pressure,this.pressureNext,this.divergence,this.curl,this.signal,this.pixels,this.offsetX,this.offsetY,this.driftX,this.driftY])t.fill(0);this.previous=null,this.peak=0}leave(){this.previous=null}move(t,e,i,s=performance.now()){if(!Number.isFinite(t+e+i+s))return;t=Math.max(0,Math.min(1,t)),e=Math.max(0,Math.min(1,e)),i=Math.max(.1,Math.min(1,i));const a=this.previous;if(this.previous={x:t,y:e,time:s},!a)return;const r=(t-a.x)*(this.width-1),o=(e-a.y)*(this.height-1),n=Math.hypot(r,o);if(n<.001)return;const h=Math.min(this.width,this.height),l=s>a.time?Math.max(1/240,(s-a.time)/1e3):1/60,c=Math.min(12,n/h/l),f=1-Math.exp(-c/2.2),m=h*(.022+.075*i)*(.65+.95*f),d=Math.min(128,Math.max(1,Math.ceil(n/(.4*m)))),u=n/m*(.32+.22*f)/d,g=r/n,p=o/n,M=-p,x=g,v=n*(2+18*f)/d;for(let i=0;i<d;i++){const s=(i+.5)/d,r=(a.x+(t-a.x)*s)*(this.width-1),o=(a.y+(e-a.y)*s)*(this.height-1),n=Math.max(1,Math.floor(r-3*m)),h=Math.min(this.width-2,Math.ceil(r+3*m)),l=Math.max(1,Math.floor(o-3*m)),c=Math.min(this.height-2,Math.ceil(o+3*m));for(let t=l;t<=c;t++)for(let e=n;e<=h;e++){const i=((e-r)*g+(t-o)*p)/m,s=((e-r)*M+(t-o)*x)/m,a=Math.exp(-i*i*.65-s*s*1.7),n=t*this.width+e;this.ink[n]=1-(1-this.ink[n])*Math.exp(-a*u);const h=1-s*s*.55,l=i*s*.7;this.u[n]=Math.max(-80,Math.min(80,this.u[n]+(g*h+M*l)*a*v)),this.v[n]=Math.max(-80,Math.min(80,this.v[n]+(p*h+x*l)*a*v))}}this.peak=1}read(t,e,i){const s=0|(e=Math.max(.5,Math.min(this.width-1.5,e))),a=0|(i=Math.max(.5,Math.min(this.height-1.5,i))),r=e-s,o=i-a,n=a*this.width+s;return(t[n]*(1-r)+t[n+1]*r)*(1-o)+(t[n+this.width]*(1-r)+t[n+this.width+1]*r)*o}sample(t,e){return this.read(this.signal,t*(this.width-1),e*(this.height-1))}displacement(t,e,i){i[0]=this.read(this.offsetX,t*(this.width-1),e*(this.height-1)),i[1]=this.read(this.offsetY,t*(this.width-1),e*(this.height-1))}step(t){if(!this.active||!Number.isFinite(t))return;let e=Math.max(0,Math.min(.05,t));const i=this.width,s=this.height;for(;e>1e-7;){const t=Math.min(1/60,e);e-=t;const a=Math.exp(-1.9*t),r=Math.exp(-3.2*t);for(let e=1;e<s-1;e++)for(let o=1;o<i-1;o++){const n=e*i+o,h=Math.max(.5,Math.min(i-1.5,o-this.u[n]*t)),l=Math.max(.5,Math.min(s-1.5,e-this.v[n]*t)),c=0|h,f=0|l,m=h-c,d=l-f,u=f*i+c,g=(1-m)*(1-d),p=m*(1-d),M=(1-m)*d,x=m*d;this.a[n]=(this.u[u]*g+this.u[u+1]*p+this.u[u+i]*M+this.u[u+i+1]*x)*a,this.b[n]=(this.v[u]*g+this.v[u+1]*p+this.v[u+i]*M+this.v[u+i+1]*x)*a,this.c[n]=(this.ink[u]*g+this.ink[u+1]*p+this.ink[u+i]*M+this.ink[u+i+1]*x)*r}[this.u,this.a]=[this.a,this.u],[this.v,this.b]=[this.b,this.v],[this.ink,this.c]=[this.c,this.ink];for(let t=1;t<s-1;t++)for(let e=1;e<i-1;e++){const s=t*i+e;this.curl[s]=.5*(this.v[s+1]-this.v[s-1]-this.u[s+i]+this.u[s-i])}for(let e=1;e<s-1;e++)for(let s=1;s<i-1;s++){const a=e*i+s,r=Math.abs(this.curl[a+1])-Math.abs(this.curl[a-1]),o=Math.abs(this.curl[a+i])-Math.abs(this.curl[a-i]),n=Math.hypot(r,o)+1e-4,h=this.curl[a]*t*10,l=Math.hypot(this.u[a],this.v[a]);this.u[a]+=o/n*h,this.v[a]-=r/n*h;const c=Math.min(1,l/(Math.hypot(this.u[a],this.v[a])+1e-6));this.u[a]*=c,this.v[a]*=c,this.divergence[a]=-.5*(this.u[a+1]-this.u[a-1]+this.v[a+i]-this.v[a-i])}this.pressure.fill(0);for(let t=0;t<4;t++){for(let t=1;t<s-1;t++)for(let e=1;e<i-1;e++){const s=t*i+e;this.pressureNext[s]=.25*(this.divergence[s]+this.pressure[s-1]+this.pressure[s+1]+this.pressure[s-i]+this.pressure[s+i])}[this.pressure,this.pressureNext]=[this.pressureNext,this.pressure]}let o=0;for(let e=1;e<s-1;e++)for(let s=1;s<i-1;s++){const a=e*i+s;this.u[a]=Math.max(-80,Math.min(80,this.u[a]-.5*(this.pressure[a+1]-this.pressure[a-1]))),this.v[a]=Math.max(-80,Math.min(80,this.v[a]-.5*(this.pressure[a+i]-this.pressure[a-i]))),this.driftX[a]+=(3.6*this.u[a]-58*this.offsetX[a]-12*this.driftX[a])*t,this.driftY[a]+=(3.6*this.v[a]-58*this.offsetY[a]-12*this.driftY[a])*t,this.offsetX[a]=Math.max(-2,Math.min(2,this.offsetX[a]+this.driftX[a]*t)),this.offsetY[a]=Math.max(-2,Math.min(2,this.offsetY[a]+this.driftY[a]*t)),this.signal[a]=1-Math.exp(.06*-Math.hypot(this.u[a],this.v[a])-.16*this.ink[a]),o=Math.max(o,this.signal[a])}this.peak=o}if(this.active)for(let t=0;t<this.ink.length;t++){const e=Math.round(65535*Math.min(1,this.signal[t]));this.pixels[4*t]=e>>>8,this.pixels[4*t+1]=255&e,this.pixels[4*t+2]=Math.round(128+63.5*this.offsetX[t]),this.pixels[4*t+3]=Math.round(128+63.5*this.offsetY[t])}else this.clear()}};function L(t,e){const i=Math.max(0,Math.min(1,e/.38));return t+(1-2*t)*(i*i*(3-2*i))}var N=class{constructor(t=1){this.mode="water",this.amount=.55,this.radius=.2,this.lensX=.5,this.lensY=.5,this.lensStrength=0,this.previous=null,this.energy=0,this.pending=!1,this.remainder=0,t=Math.max(.25,Math.min(4,t)),this.columns=Math.round(t>=1?128:128*t),this.rows=Math.round(t>=1?128/t:128),this.xScale=Math.max(1,t),this.yScale=Math.max(1,1/t),this.heights=new Float32Array(this.columns*this.rows),this.velocity=new Float32Array(this.heights.length),this.next=new Float32Array(this.heights.length),this.normals=new Float32Array(2*this.heights.length),this.edgeMask=new Float32Array(this.heights.length);for(let e=0;e<this.rows;e++)for(let i=0;i<this.columns;i++)this.edgeMask[e*this.columns+i]=I(i/(this.columns-1),e/(this.rows-1),t);this.refraction={width:this.columns,height:this.rows,pixels:new Uint8Array(4*this.heights.length),strength:30,mode:"water",focus:[.5,.5,0,.2]},this.waterPixels=this.refraction.pixels,this.trail=new C(this.columns,this.rows),this.contour=new R(this.columns,this.rows),this.afterimage=new P(this.columns,this.rows),this.clear()}get invertsDensity(){return"trail"===this.mode}get densityTrail(){return["trail","contour","dissolve"].includes(this.mode)}get hasRefraction(){return this.active||this.lensStrength>15e-5}get active(){return["dissolve","silk","vortex"].includes(this.mode)?this.afterimage.active:"contour"===this.mode?this.contour.active:"trail"===this.mode?this.trail.active:this.pending||this.energy>15e-5}setMode(t){t!==this.mode&&(this.clear(),this.mode=t,this.refraction.mode=t,"dissolve"!==t&&"silk"!==t&&"vortex"!==t||this.afterimage.setMode(t),this.refraction.pixels="trail"===t?this.trail.pixels:"contour"===t?this.contour.pixels:["dissolve","silk","vortex"].includes(t)?this.afterimage.pixels:this.waterPixels,this.refraction.strength="water"===t?30*this.amount/.55:"silk"===t?28*this.amount:"vortex"===t?38*this.amount:0)}configure(t,e=.55,i=.2,s=!1){this.setMode(t),this.refraction.edgeSafe=s,this.afterimage.edgeSafe=s,this.amount=Number.isFinite(e)?Math.max(0,Math.min(1,e)):.55,this.radius=Number.isFinite(i)?Math.max(.1,Math.min(1,i)):.2,this.refraction.strength="water"===t?30*this.amount/.55:"silk"===t?28*this.amount:"vortex"===t?38*this.amount:0,this.refraction.focus[2]=this.densityTrail?this.amount:this.lensStrength*this.amount,this.refraction.focus[3]=this.radius}move(t,e,i){if("none"===this.mode||0===this.amount)return;if(!Number.isFinite(t+e))return;if(t=Math.max(0,Math.min(1,t)),e=Math.max(0,Math.min(1,e)),["dissolve","silk","vortex"].includes(this.mode))return void this.afterimage.move(t,e,this.radius);if("contour"===this.mode)return void this.contour.move(t,e,this.radius);if("trail"===this.mode)return void this.trail.move(t,e,this.radius,i);if("water"!==this.mode)return!this.previous&&this.lensStrength<.001&&(this.lensX=t,this.lensY=e),this.previous={x:t,y:e},void(this.pending=!0);if(!this.previous)return void(this.previous={x:t,y:e});const s=this.previous;this.previous={x:t,y:e};const a=(t-s.x)*this.xScale,r=(e-s.y)*this.yScale,o=Math.hypot(a,r);if(o<1e-5)return;const n=.035+.1*this.radius,h=3*n,l=Math.min(192,Math.max(1,Math.ceil(o/(.5*n)))),c=95*Math.min(o,1)/l;for(let i=0;i<l;i++){const a=(i+.5)/l,r=s.x+(t-s.x)*a,o=s.y+(e-s.y)*a,f=Math.max(1,Math.floor((r-h/this.xScale)*(this.columns-1))),m=Math.min(this.columns-2,Math.ceil((r+h/this.xScale)*(this.columns-1))),d=Math.max(1,Math.floor((o-h/this.yScale)*(this.rows-1))),u=Math.min(this.rows-2,Math.ceil((o+h/this.yScale)*(this.rows-1)));for(let t=d;t<=u;t++)for(let e=f;e<=m;e++){const i=(e/(this.columns-1)-r)*this.xScale,s=(t/(this.rows-1)-o)*this.yScale,a=Math.exp(-(i*i+s*s)/(n*n))*c,h=t*this.columns+e;this.velocity[h]=Math.max(-12,this.velocity[h]-a)}}this.pending=!0}leave(){this.afterimage.leave(),this.contour.leave(),this.trail.leave(),this.previous=null,"water"!==this.mode&&this.lensStrength&&(this.pending=!0)}clear(){this.trail.clear(),this.contour.clear(),this.afterimage.clear(),this.heights.fill(0),this.velocity.fill(0),this.next.fill(0),this.normals.fill(0),this.refraction.focus[2]=0,this.previous=null,this.lensStrength=0,this.energy=0,this.pending=!1,this.remainder=0;for(let t=0;t<this.waterPixels.length;t+=4)this.waterPixels[t]=this.waterPixels[t+2]=128,this.waterPixels[t+1]=this.waterPixels[t+3]=0}step(t){if(!this.active||!Number.isFinite(t))return;if(["dissolve","silk","vortex"].includes(this.mode))return void this.afterimage.step(t);if("contour"===this.mode)return void this.contour.step(t);if("trail"===this.mode)return void this.trail.step(t);if("water"!==this.mode)return void this.stepLight(Math.max(0,Math.min(.05,t)));this.remainder+=Math.max(0,Math.min(.05,t));const e=1/120,i=Math.exp(-3.8*e),s=.3*Math.min(this.columns,this.rows);for(;this.remainder+1e-8>=e;){this.remainder-=e;let t=0;for(let a=1;a<this.rows-1;a++)for(let r=1;r<this.columns-1;r++){const o=a*this.columns+r,n=this.heights[o],h=this.heights[o-1]+this.heights[o+1]+this.heights[o-this.columns]+this.heights[o+this.columns]-4*n,l=Math.min(r,a,this.columns-1-r,this.rows-1-a),c=l<5?.88+.024*l:1,f=(this.velocity[o]+(h*s*s-8*n)*e)*i*c;this.velocity[o]=f,this.next[o]=(n+f*e)*c,t=Math.max(t,Math.abs(this.next[o]),.1*Math.abs(f))}this.heights.set(this.next),this.energy=t,this.pending=!1}if(!this.active)return void this.clear();const a=.18*Math.min(this.columns,this.rows);for(let t=0;t<this.rows;t++)for(let e=0;e<this.columns;e++){const i=t*this.columns+e,s=(this.heights[t*this.columns+Math.max(0,e-1)]-this.heights[t*this.columns+Math.min(this.columns-1,e+1)])*a,r=(this.heights[Math.max(0,t-1)*this.columns+e]-this.heights[Math.min(this.rows-1,t+1)*this.columns+e])*a,o=Math.tanh(s)*(this.refraction.edgeSafe?this.edgeMask[i]:1),n=Math.tanh(r)*(this.refraction.edgeSafe?this.edgeMask[i]:1);this.normals[2*i]=o,this.normals[2*i+1]=n;const h=Math.round(32767*o+32768),l=Math.round(32767*n+32768);this.refraction.pixels[4*i]=h>>>8,this.refraction.pixels[4*i+1]=255&h,this.refraction.pixels[4*i+2]=l>>>8,this.refraction.pixels[4*i+3]=255&l}}stepLight(t){const e=this.previous,i=1-Math.exp(-30*t),s=1-Math.exp(-12*t);e&&(this.lensX+=(e.x-this.lensX)*i,this.lensY+=(e.y-this.lensY)*i),this.lensStrength+=((e?1:0)-this.lensStrength)*s,this.energy=Math.max(e?Math.abs(e.x-this.lensX)+Math.abs(e.y-this.lensY):0,Math.abs((e?1:0)-this.lensStrength)),this.pending=!1,e||this.active?this.refraction.focus=[this.lensX,this.lensY,this.lensStrength*this.amount,this.radius]:this.clear()}sample(t,e,i){if(["dissolve","silk","vortex"].includes(this.mode))return this.afterimage.sample(t,e,i),i[0]*=this.amount,i[1]*=this.amount,void(i[2]*=this.amount);if("contour"===this.mode)return i[0]=i[1]=0,void(i[2]=this.contour.sample(t,e)*this.amount*3);if("trail"===this.mode)return i[0]=i[1]=0,void(i[2]=this.trail.sample(t,e)*this.amount*3);const s=Math.max(0,Math.min(this.columns-1.001,t*(this.columns-1))),a=Math.max(0,Math.min(this.rows-1.001,e*(this.rows-1))),r=Math.floor(s),o=Math.floor(a),n=s-r,h=a-o,l=2*(o*this.columns+r),c=l+2*this.columns;for(let t=0;t<2;t++)i[t]=.08*((this.normals[l+t]*(1-n)+this.normals[l+2+t]*n)*(1-h)+(this.normals[c+t]*(1-n)+this.normals[c+2+t]*n)*h);i[0]*=this.amount/.55,i[1]*=this.amount/.55,i[2]="light"===this.mode||"scan"===this.mode?function(t,e,i,s){const[a,r,o,n]=i.focus,h=(t-a)*Math.max(1,s)/n,l=(e-r)*Math.max(1,1/s)/n;return"light"===i.mode?Math.exp(-3*(h*h+l*l))*o:"scan"===i.mode?(1.3*Math.exp(-h*h*110)-.3*Math.exp(-h*h*12))*Math.exp(-l*l*1.8)*o:0}(t,e,this.refraction,this.xScale/this.yScale):0}};function D(t){return"videoWidth"in t?[t.videoWidth,t.videoHeight]:"naturalWidth"in t?[t.naturalWidth,t.naturalHeight]:[t.width,t.height]}var U=(t=!1)=>{const e=document.createElement("canvas"),i=e.getContext("2d",{willReadFrequently:t});if(!i)throw new Error("Canvas 2D is unavailable.");return{canvas:e,ctx:i}},X=(t,e,i)=>{t.width===e&&t.height===i||(t.width=e,t.height=i)},B={blocks:" ░▒▓█",braille:" ⠁⠃⠇⡇⣇⣧⣷⣿",lines:" -═╪╬",cross:" ·+xX#",diagonal:" /╱╳",diamond:" ·◇◈◆",mixed:" .:+/◇#@"};function O(t,e={},i={}){const a=t.getContext("2d");if(!a)throw new Error("Canvas is already owned by another renderer.");const r=U(),o=U(!0),n=U(),h=U(),c=U(),f=U(),d=U(),u=U(),p=U(),M=U();let x,v=0,b=l(e),w=0,y="",I="",P=new Uint8ClampedArray(0),R=new Uint8ClampedArray(0),C=0,O=0,Y=0,z=null,_="",W=new N,q=0;const G=[0,0,0],j=[0,0,0,1],V=Math.max(64,Math.min(4096,Number.isFinite(i.maxDimension)?i.maxDimension:960)),H=Math.max(256,Math.min(1048576,Number.isFinite(i.maxCells)?i.maxCells:12e3));let $=H,Q=Math.max(.1,Math.min(8,i.pixelRatio??1));return{canvas:t,render:function(e,i=0,l=960,U=540,H=i*b.motion.speed){if(Number.isFinite(i)||(i=0),!Number.isFinite(l)||!Number.isFinite(U)||l<1||U<1)throw new Error("Render dimensions must be positive finite numbers.");const[J,K]=D(e);if(!J||!K)return;const Z=Math.min(1,V/Math.max(l,U)),tt=Math.max(2,Math.round(l*Z)),et=Math.max(2,Math.round(U*Z));X(t,tt,et),X(r.canvas,tt,et),X(n.canvas,tt,et),X(h.canvas,tt,et),X(c.canvas,tt,et),q!==tt/et&&(q=tt/et,W=new N(q)),W.configure(b.hover.effect,b.hover.strength,b.hover.radius,b.hover.edgeSafe),W.step(Math.max(0,Math.min(.05,i-Y))),Y=i;const it="currentTime"in e?e.getVideoPlaybackQuality?.().totalVideoFrames??e.currentTime:0,st=[w,tt,et,it].join(":"),at="dither"===b.style,rt=g(tt,et,b,$,Q),ot=rt.cell,nt=rt.rowHeight,ht=rt.columns,lt=rt.rows;if(y!==st||z!==e||C!==ht||O!==lt){z=e,y=st,I="",C=ht,O=lt,r.ctx.clearRect(0,0,tt,et),r.ctx.save();const t=m(J,K,tt,et,b.crop);r.ctx.translate(t.x+t.width/2,t.y+t.height/2),r.ctx.rotate(b.crop.rotation*Math.PI/180),r.ctx.drawImage(e,-J*t.scale/2,-K*t.scale/2,J*t.scale,K*t.scale),r.ctx.restore(),X(o.canvas,C,O),o.ctx.clearRect(0,0,C,O),o.ctx.drawImage(r.canvas,0,0,C,O),P=o.ctx.getImageData(0,0,C,O).data;const i=b.color;for(let t=0;t<P.length;t+=4){const e=.299*P[t]+.587*P[t+1]+.114*P[t+2];for(let s=0;s<3;s++){const a=e+(P[t+s]-e)*i.saturation;P[t+s]=((a*(1-i.grayscale)+e*i.grayscale)/255-.5)*i.contrast*255+127.5+255*i.brightness}}}n.ctx.clearRect(0,0,tt,et),n.ctx.globalAlpha=1,n.ctx.globalCompositeOperation="source-over";const ct=H;if(at){const t=!W.active&&"none"===b.motion.type&&"none"===b.dither.motion;if(!t||I!==st){R.length!==P.length&&(R=new Uint8ClampedArray(P.length));const e=R;e.set(P);const a=b.motion.type;if(W.active||"none"!==a)for(let t=0;t<O;t++)for(let i=0;i<C;i++){const s=i/C,r=t/O;let o=i,n=t,h=0,l=1,c=1;W.active&&(W.sample(s,r,G),o-=G[0]*C,n-=G[1]*O,h=G[2]/3),S(a,s,r,ct,j),k(j,b.motion.amount??1),o-=j[0]/960*C,n-=j[1]/960*O,l=1+j[2],c=j[3],o=Math.max(0,Math.min(C-1,o)),n=Math.max(0,Math.min(O-1,n));const f=Math.floor(o),m=Math.floor(n),d=o-f,u=n-m,g=4*(t*C+i),p=4*(m*C+f),M=4*(m*C+Math.min(C-1,f+1)),x=4*(Math.min(O-1,m+1)*C+f),v=4*(Math.min(O-1,m+1)*C+Math.min(C-1,f+1));for(let t=0;t<3;t++){const i=((P[p+t]*(1-d)+P[M+t]*d)*(1-u)+(P[x+t]*(1-d)+P[v+t]*d)*u)/255;let s=(["trail","contour"].includes(b.hover.effect)?L(i,h):"dissolve"===b.hover.effect?i*Math.max(0,1+h):i)*l;e[g+t]=255*s}e[g+3]=P[p+3]*c}!function(t,e,i,a,r=0){const{algorithm:o,amount:n,threshold:h}=a,l=("custom"===a.palette?a.colors:s[a.palette]??s.mono).map(T),c=F[o],f=c?new Float32Array(3*e*3):null,m="drift"===a.motion?r*a.speed*3:0,d=(a.direction??45)*Math.PI/180,u=Math.round(Math.cos(d)*m),g=Math.round(Math.sin(d)*m),p=(t,e)=>(t%e+e)%e,M=l.map(t=>.299*t[0]+.587*t[1]+.114*t[2]),x="shimmer"===a.motion?.15*Math.sin(r*a.speed*2):0;for(let s=0;s<i;s++)for(let r=0;r<e;r++){const d=4*(s*e+r),v=3*(s%3*e+r);if(0===t[d+3]){f&&(f[v]=f[v+1]=f[v+2]=0);continue}let b=0;o.startsWith("bayer")?b=A(r-u&15,s-g&15,Number(o.slice(5))):"noise"===o?b=E(r-u,s-g)-.5:"lines"===o?b=p(s-g,4)/3-.5:"vertical-lines"===o?b=p(r-u,4)/3-.5:"diagonal-lines"===o?b=p(r-u+s-g,4)/3-.5:"radial"===o?b=p(Math.hypot(r-e/2,s-i/2)-m,6)/6-.5:"halftone"===o&&(b=Math.hypot(p(r-u,6)-2.5,p(s-g,6)-2.5)/3.54-.5);const w=128*(b*n+x+(.5-h)),y=t[d]+w+(f?.[v]??0),S=t[d+1]+w+(f?.[v+1]??0),k=t[d+2]+w+(f?.[v+2]??0);let F=0,T=0,I=0;if(l.length){let t=1/0;const e=.299*y+.587*S+.114*k;for(let i=0;i<l.length;i++){const s=l[i],r="luminance"===a.colorSpace?(e-M[i])**2:(y-s[0])**2*.299+(S-s[1])**2*.587+(k-s[2])**2*.114;r<t&&(t=r,[F,T,I]=s)}}else F=51*Math.round(y/51),T=51*Math.round(S/51),I=51*Math.round(k/51);if(t[d]=F,t[d+1]=T,t[d+2]=I,f&&c){f[v]=f[v+1]=f[v+2]=0;for(const[t,a,o]of c){const h=r+t;if(h<0||h>=e||s+a>=i)continue;const l=3*((s+a)%3*e+h);f[l]+=(y-F)*o*n,f[l+1]+=(S-T)*o*n,f[l+2]+=(k-I)*o*n}}}}(e,C,O,b.dither,i),o.ctx.putImageData(new ImageData(e,C,O),0,0),I=t?st:""}n.ctx.imageSmoothingEnabled=!1,n.ctx.drawImage(o.canvas,0,0,tt,et)}else{const t=Array.from(B[b.style]??b.charset),e=n.ctx,i="ascii"===b.style||!!B[b.style],s=Math.max(3,Math.round(.92*nt)),a=Math.ceil(ot+4),r=Math.ceil(nt+4),o=[t.join(""),s,a,r,b.ink,b.colorMode].join(":");if(i&&o!==_&&(_=o,X(d.canvas,a*t.length,r),d.ctx.clearRect(0,0,d.canvas.width,r),d.ctx.font=`${s}px monospace`,d.ctx.textBaseline="middle",d.ctx.textAlign="center",d.ctx.fillStyle="accent"===b.colorMode?b.ink:"#ffffff",t.forEach((t,e)=>d.ctx.fillText(t,e*a+a/2,r/2))),"lego"===b.style&&v!==ot){v=ot,X(M.canvas,Math.ceil(ot),Math.ceil(nt));const t=M.ctx;t.clearRect(0,0,M.canvas.width,M.canvas.height),t.fillStyle="rgba(255,255,255,.2)",t.strokeStyle="rgba(0,0,0,.25)",t.lineWidth=Math.max(.5,.6*Q),t.beginPath(),t.arc(ot/2,nt/2,.28*ot,0,2*Math.PI),t.fill(),t.stroke()}e.font=`${s}px monospace`,e.textBaseline="middle",e.textAlign="center";for(let s=0;s<O;s++)for(let o=0;o<C;o++){let n=o,h=s,l=0;W.active&&(W.sample(o/C,s/O,G),n=Math.max(0,Math.min(C-1,o-G[0]*C)),h=Math.max(0,Math.min(O-1,s-G[1]*O)),l=G[2]/3);const c=4*(Math.floor(h)*C+Math.floor(n));if(!P[c+3])continue;const f=P[c],m=P[c+1],u=P[c+2],g=(.299*f+.587*m+.114*u)/255;let p=g;["trail","contour"].includes(b.hover.effect)&&l?p=L(p,l):"dissolve"===b.hover.effect&&(p*=Math.max(0,1+l));const x=b.motion.type;let v=o*ot,w=s*nt,y=1;S(x,o/C,s/O,ct,j),k(j,b.motion.amount??1),v+=j[0]*tt/960,w+=j[1]*et/960,p=Math.max(0,Math.min(1,p+j[2])),y=j[3],i||"accent"!==b.colorMode||"cmyk"===b.style||(y*=p),e.globalAlpha=y;const A=255*(p-g);let F="source"===b.colorMode?`rgb(${f+A},${m+A},${u+A})`:"gray"===b.colorMode?`rgb(${Math.round(255*p)},${Math.round(255*p)},${Math.round(255*p)})`:b.ink;if(e.fillStyle=F,i){const i=Math.max(0,Math.min(t.length-1,Math.round(p*(t.length-1))));"accent"===b.colorMode?e.drawImage(d.canvas,i*a,0,a,r,"none"===x||"caustics"===x?Math.round(v+(ot-a)/2):v+(ot-a)/2,"none"===x||"caustics"===x?Math.round(w+(nt-r)/2):w+(nt-r)/2,a,r):e.fillText(t[i],v+ot/2,w+nt/2)}else if("dots"===b.style)e.beginPath(),e.arc(v+ot/2,w+nt/2,.48*ot*Math.sqrt(p),0,2*Math.PI),e.fill();else if("led"===b.style)e.beginPath(),e.arc(v+ot/2,w+nt/2,.39*ot,0,2*Math.PI),e.fill(),e.globalAlpha=.35*y,e.fillStyle="#ffffff",e.beginPath(),e.arc(v+.43*ot,w+.4*nt,.11*ot,0,2*Math.PI),e.fill();else if("hex"===b.style){const t=v+ot/2,i=w+nt/2;e.beginPath();for(let s=0;s<6;s++){const a=Math.PI/3*s,r=t+Math.cos(a)*ot*.49,o=i+Math.sin(a)*nt*.49;0===s?e.moveTo(r,o):e.lineTo(r,o)}e.closePath(),e.fill()}else if("cmyk"===b.style){e.fillStyle="#ffffff",e.fillRect(v,w,ot,nt);const t=1-Math.max(f,m,u)/255,i=Math.max(.001,1-t),s=[["#00ffff",(1-f/255-t)/i,.36,.36],["#ff00ff",(1-m/255-t)/i,.64,.36],["#ffff00",(1-u/255-t)/i,.5,.66],["#000000",t,.5,.5]];e.globalCompositeOperation="multiply";for(const[t,i,a,r]of s)e.fillStyle=t,e.beginPath(),e.arc(v+ot*a,w+nt*r,.48*ot*Math.sqrt(Math.max(0,i)),0,2*Math.PI),e.fill();e.globalCompositeOperation="source-over"}else if("voxel"===b.style){const t=v+ot/2,i=w+nt/2;e.beginPath(),e.moveTo(t,w),e.lineTo(v+ot,w+.25*nt),e.lineTo(t,i),e.lineTo(v,w+.25*nt),e.closePath(),e.fill(),e.globalAlpha=.72*y,e.beginPath(),e.moveTo(v,w+.25*nt),e.lineTo(t,i),e.lineTo(t,w+nt),e.lineTo(v,w+.75*nt),e.closePath(),e.fill(),e.globalAlpha=.42*y,e.beginPath(),e.moveTo(t,i),e.lineTo(v+ot,w+.25*nt),e.lineTo(v+ot,w+.75*nt),e.lineTo(t,w+nt),e.closePath(),e.fill()}else{const t="pixel"===b.style?0:Math.max(.5,.06*ot);e.fillRect(v,w,ot-t,nt-t),"lego"===b.style&&e.drawImage(M.canvas,v,w),"disco"===b.style&&(e.fillStyle=`rgba(255,255,255,${.1+.25*E(o,s)})`,e.fillRect(v,w,ot-t,.35*nt),e.fillStyle="rgba(0,0,0,.25)",e.fillRect(v,w+.65*nt,ot-t,.35*nt-t))}}}n.ctx.globalAlpha=1,(b.color.amount||b.lights.length)&&(X(u.canvas,tt,et),u.ctx.clearRect(0,0,tt,et),u.ctx.drawImage(n.canvas,0,0)),b.color.amount&&(n.ctx.save(),n.ctx.globalCompositeOperation=b.color.blend,n.ctx.globalAlpha=b.color.amount,n.ctx.fillStyle=b.color.tint,n.ctx.fillRect(0,0,tt,et),n.ctx.restore());for(const t of b.lights){const e=t.radius*Math.max(tt,et),i=n.ctx.createRadialGradient(t.x*tt,t.y*et,0,t.x*tt,t.y*et,e);i.addColorStop(0,t.color),i.addColorStop(1,"transparent"),n.ctx.save(),n.ctx.globalCompositeOperation="screen",n.ctx.globalAlpha=t.intensity,n.ctx.fillStyle=i,n.ctx.fillRect(0,0,tt,et),n.ctx.restore()}if((b.color.amount||b.lights.length)&&(n.ctx.globalCompositeOperation="destination-in",n.ctx.drawImage(u.canvas,0,0),n.ctx.globalCompositeOperation="source-over"),b.mask.enabled&&b.mask.shapes.length){const t=c.ctx;t.clearRect(0,0,tt,et),t.fillStyle="#fff",t.strokeStyle="#fff",t.lineCap="round",t.lineJoin="round";for(const e of b.mask.shapes){if(t.beginPath(),"ellipse"===e.kind)t.ellipse((e.x+e.width/2)*tt,(e.y+e.height/2)*et,e.width*tt/2,e.height*et/2,0,0,2*Math.PI);else{if("rectangle"!==e.kind){if(t.lineWidth=(e.size??.05)*tt,1===e.points?.length){t.arc(e.points[0][0]*tt,e.points[0][1]*et,t.lineWidth/2,0,2*Math.PI),t.fill();continue}e.points?.forEach(([e,i],s)=>s?t.lineTo(e*tt,i*et):t.moveTo(e*tt,i*et)),t.stroke();continue}t.rect(e.x*tt,e.y*et,e.width*tt,e.height*et)}t.fill()}n.ctx.globalCompositeOperation=b.mask.invert?"destination-out":"destination-in",n.ctx.drawImage(c.canvas,0,0),n.ctx.globalCompositeOperation="source-over"}const ft=h.ctx;ft.clearRect(0,0,tt,et),ft.globalAlpha=b.backdrop.opacity;const mt=b.backdrop;if("solid"===mt.mode&&(ft.fillStyle=mt.color,ft.fillRect(0,0,tt,et)),"gradient"===mt.mode){const t=ft.createLinearGradient(0,0,tt,et);t.addColorStop(0,mt.color),t.addColorStop(1,mt.color2),ft.fillStyle=t,ft.fillRect(0,0,tt,et)}if("source"===mt.mode&&ft.drawImage(r.canvas,0,0),"blurred"===mt.mode){const t=Math.max(1,mt.blur);X(f.canvas,Math.max(2,Math.round(tt/t)),Math.max(2,Math.round(et/t))),f.ctx.drawImage(r.canvas,0,0,f.canvas.width,f.canvas.height),ft.imageSmoothingEnabled=!0,ft.drawImage(f.canvas,0,0,tt,et)}ft.globalAlpha=1,b.effects.characterBloom>0&&(X(p.canvas,Math.max(2,Math.round(tt/3)),Math.max(2,Math.round(et/3))),p.ctx.clearRect(0,0,p.canvas.width,p.canvas.height),p.ctx.drawImage(n.canvas,0,0,p.canvas.width,p.canvas.height),ft.save(),ft.globalAlpha=.8*b.effects.characterBloom,ft.globalCompositeOperation="screen",ft.filter=`blur(${1+4*b.effects.characterBloom}px)`,ft.drawImage(p.canvas,0,0,tt,et),ft.restore()),ft.drawImage(n.canvas,0,0);const dt=Object.entries(b.effects).some(([t,e])=>!["angle","focus","blurType","characterBloom"].includes(t)&&"number"==typeof e&&e>0);a.clearRect(0,0,tt,et),dt?(void 0===x&&(x=function(){const t=document.createElement("canvas"),e=t.getContext("webgl",{alpha:!0,premultipliedAlpha:!1,antialias:!1,preserveDrawingBuffer:!0});if(!e)return null;const i=[],s=(t,s)=>{const a=e.createShader(t);if(i.push(a),e.shaderSource(a,s),e.compileShader(a),!e.getShaderParameter(a,e.COMPILE_STATUS))throw new Error(e.getShaderInfoLog(a)||"Finish shader failed");return a},a=e.createProgram();if(e.attachShader(a,s(e.VERTEX_SHADER,"attribute vec2 p;varying vec2 uv;void main(){uv=(p+1.)*.5;gl_Position=vec4(p,0.,1.);}")),e.attachShader(a,s(e.FRAGMENT_SHADER,"precision mediump float;varying vec2 uv;uniform sampler2D src;uniform vec2 size;uniform float t,bloom,grain,dust,scanlines,crt,prism,vignette,glitch,pixelate,blur,blurMode,angle,focus,halftone,rgbSplit,sharpen;\n float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);}\n vec4 sampleAt(vec2 p){if(min(min(p.x,p.y),min(1.-p.x,1.-p.y))<0.)return vec4(0.);return texture2D(src,vec2(p.x,1.-p.y));}\n void main(){vec2 q=uv,c=q-.5;q=c*(1.+dot(c,c)*crt*.25)+.5;\n if(glitch>0.)q.x+=(hash(vec2(floor(q.y*35.),floor(t*5.)))-.5)*.07*glitch*step(.82,hash(vec2(floor(q.y*35.),floor(t*5.)+3.)));\n if(pixelate>0.){vec2 grid=size/(1.+pixelate*20.);q=(floor(q*grid)+.5)/grid;}\n vec4 base=sampleAt(q);float edge=smoothstep(.12,.65,length(c));\n vec2 shift=vec2((prism*3.*edge+rgbSplit*8.)/size.x,prism*edge/size.y);\n if(prism>0.||rgbSplit>0.)base.rgb=vec3(sampleAt(q+shift).r,base.g,sampleAt(q-shift).b);\n vec2 dir=vec2(cos(angle),sin(angle))/size;float amount=blur;\n if(blurMode>1.5&&blurMode<2.5){dir=normalize(c+vec2(.0001))/size;amount*=length(c)*2.;}\n if(blurMode>2.5)amount*=smoothstep(.05,.5,abs(q.y-focus));\n vec4 blurred=base;\n if(amount>0.){blurred=base*.2;for(int i=1;i<=4;i++){float f=float(i)*amount*.35;vec2 off=dir*f;if(blurMode<.5)off=vec2(cos(float(i)*1.57),sin(float(i)*1.57))*amount/size;blurred+=sampleAt(q+off)*.1+sampleAt(q-off)*.1;}}\n vec3 light=vec3(0.);if(bloom>0.)for(int i=0;i<4;i++){float a=float(i)*1.5708;vec3 s=sampleAt(q+vec2(cos(a),sin(a))*6./size).rgb;light+=max(vec3(0.),s-.35)*.25;}\n vec3 col=blurred.rgb+light*bloom;\n if(sharpen>0.){vec2 px=1./size;vec3 near=sampleAt(q+vec2(px.x,0.)).rgb+sampleAt(q-vec2(px.x,0.)).rgb+sampleAt(q+vec2(0.,px.y)).rgb+sampleAt(q-vec2(0.,px.y)).rgb;col+=(base.rgb*4.-near)*sharpen*.5;}\ncol*=1.-scanlines*.4*(.5+.5*cos(q.y*size.y*3.14159));\n col*=1.-vignette*smoothstep(.15,.72,length(c));\n col+=(hash(floor(q*size)+floor(t*12.))-.5)*grain*.2;\n if(dust>0.)col+=step(1.-dust*.002,hash(floor(q*size*.25)+floor(t*2.)))*.4;\n if(halftone>0.)col*=mix(1.,smoothstep(.1,.65,length(fract(q*size/6.)-.5)),halftone);\n gl_FragColor=vec4(clamp(col,0.,1.),blurred.a);}")),e.linkProgram(a),!e.getProgramParameter(a,e.LINK_STATUS))throw new Error("Finish link failed");e.useProgram(a);const r=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,r),e.bufferData(e.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,-1,1,1,1]),e.STATIC_DRAW);const o=e.getAttribLocation(a,"p");e.enableVertexAttribArray(o),e.vertexAttribPointer(o,2,e.FLOAT,!1,0,0);const n=e.createTexture();e.bindTexture(e.TEXTURE_2D,n),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE);const h=["t","bloom","grain","dust","scanlines","crt","prism","rgbSplit","sharpen","vignette","glitch","pixelate","blur","blurMode","angle","focus","halftone"],l=Object.fromEntries(h.map(t=>[t,e.getUniformLocation(a,t)])),c=e.getUniformLocation(a,"size");return{canvas:t,render(i,s,r,o=1){t.width===i.width&&t.height===i.height||(t.width=i.width,t.height=i.height,e.viewport(0,0,t.width,t.height)),e.useProgram(a),e.bindTexture(e.TEXTURE_2D,n),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,i),e.uniform2f(c,t.width/o,t.height/o);for(const t of h)e.uniform1f(l[t],"t"===t?r:"blurMode"===t?["gaussian","directional","radial","progressive"].indexOf(s.blurType):"angle"===t?s.angle*Math.PI/180:s[t]??0);return e.drawArrays(e.TRIANGLE_STRIP,0,4),t},destroy(){e.deleteTexture(n),e.deleteBuffer(r),e.deleteProgram(a),i.forEach(t=>e.deleteShader(t)),t.width=t.height=1,e.getExtension("WEBGL_lose_context")?.loseContext()}}}()),x?a.drawImage(x.render(h.canvas,b.effects,i,Q),0,0):a.drawImage(h.canvas,0,0),t.dataset.studioFinish=x?"gpu":"unavailable"):(a.drawImage(h.canvas,0,0),t.dataset.studioFinish="none")},setPixelRatio(t){Q=Math.max(.1,Math.min(8,Number.isFinite(t)?t:1))},get pixelRatio(){return Q},setBudget(t){$=Math.max(1500,Math.min(H,Math.round(t)))},get maxCells(){return $},configure(t){b=l(t),w++},pointer:(t,e,i)=>{W.configure(b.hover.effect,b.hover.strength,b.hover.radius,b.hover.edgeSafe),W.move(t,e,i)},leave(){W.leave()},get active(){return W.active},get settings(){return l(b)},get capabilities(){return{gpuFinish:null!==x}},invalidate(){y=""},destroy(){x?.destroy();for(const t of[r,o,n,h,c,f,d,u,p,M])t.canvas.width=t.canvas.height=1;z=null,P=new Uint8ClampedArray(0)}}}function Y(t,e,i){return new Promise((s,a)=>{const r=()=>{l(),s()},o=()=>{l(),a(new Error("Unable to load this media. Check its format and cross-origin permissions."))},n=()=>{l(),a(new DOMException("Cancelled","AbortError"))},h=setTimeout(o,2e4),l=()=>{clearTimeout(h),t.removeEventListener(e,r),t.removeEventListener("error",o),i?.removeEventListener("abort",n)};t.addEventListener(e,r,{once:!0}),t.addEventListener("error",o,{once:!0}),i?.addEventListener("abort",n,{once:!0}),i?.aborted&&n()})}async function z(t,e){if("string"==typeof t&&t.startsWith("blob:")){const i=await fetch(t,{signal:e}),s=await i.blob();return z(new File([s],"Imported media",{type:s.type}),e)}const i="string"!=typeof t,s=i?t.name:t;if(i?"image/gif"===t.type:/\.gif(?:[?#]|$)/i.test(s)){const s=await import("gifuct-js"),{parseGIF:a,decompressFrames:r}="function"==typeof s.parseGIF?s:s.default,o=i?await t.arrayBuffer():await fetch(t,{signal:e}).then(t=>{if(!t.ok)throw new Error("GIF download failed.");return t.arrayBuffer()});if(e?.aborted)throw new DOMException("Cancelled","AbortError");const n=a(o),h=n.lsd.width,l=n.lsd.height;if(h*l>4e6)throw new Error("GIF is too large. Use a smaller GIF or an MP4.");const c=n.frames.filter(t=>"image"in t).length;if(!c||c*h*l*4>128e6)throw new Error("GIF exceeds the decoded memory budget. Use MP4 for long animations.");const f=r(n,!0);if(f.length*h*l*4>128e6)throw new Error("GIF exceeds the 128 MB decoded budget. Use MP4 for long animations.");const m=document.createElement("canvas");m.width=h,m.height=l;const d=m.getContext("2d"),u=document.createElement("canvas"),g=u.getContext("2d"),p=f.reduce((t,e)=>t+Math.max(20,e.delay),0)/1e3;let M=-1,x=null;const v=t=>{const e=(t%p+p)%p*1e3;let i=0,s=0;for(;s<f.length-1&&(i+=Math.max(20,f[s].delay),!(e<i));s++);s<M&&(d.clearRect(0,0,h,l),M=-1,x=null);for(let t=M+1;t<=s;t++){const e=f[t-1];2===e?.disposalType&&d.clearRect(e.dims.left,e.dims.top,e.dims.width,e.dims.height),3===e?.disposalType&&x&&d.putImageData(x,0,0);const i=f[t];x=3===i.disposalType?d.getImageData(0,0,h,l):null,u.width=i.dims.width,u.height=i.dims.height,g.putImageData(new ImageData(new Uint8ClampedArray(i.patch),u.width,u.height),0,0),d.drawImage(u,i.dims.left,i.dims.top)}return M=s,m};return v(0),{source:m,width:h,height:l,duration:p,animated:!0,seek:async()=>{},frame:v,destroy(){m.width=u.width=1,f.length=0,x=null}}}const a=i?t.type.startsWith("video/"):/\.(mp4|webm|mov)(?:[?#]|$)/i.test(s),r=i?URL.createObjectURL(t):t,o=a?document.createElement("video"):new Image;o.crossOrigin="anonymous",o instanceof HTMLVideoElement&&(o.muted=!0,o.playsInline=!0,o.preload="auto");const n=()=>{o instanceof HTMLVideoElement?(o.pause(),o.removeAttribute("src"),o.load()):o.src="",i&&URL.revokeObjectURL(r)};try{const t=Y(o,a?"loadeddata":"load",e);o.src=r,await t;const i=o instanceof HTMLVideoElement?o.videoWidth:o.naturalWidth,s=o instanceof HTMLVideoElement?o.videoHeight:o.naturalHeight;return{source:o,width:i,height:s,duration:o instanceof HTMLVideoElement?o.duration:0,animated:a,async seek(t,e){if(!(o instanceof HTMLVideoElement))return;if(!Number.isFinite(o.duration)||o.duration<=0)throw new Error("Video duration is unavailable.");const i=Math.max(0,Math.min(o.duration-.001,t%o.duration));if(Math.abs(o.currentTime-i)<.001&&o.readyState>=2)return;const s=Y(o,"seeked",e);o.currentTime=i,await s},frame:()=>o,destroy:n}}catch(t){throw n(),t}}var _=t=>{if(t?.aborted)throw new DOMException("Export cancelled","AbortError")};async function W(t,e,i){const{format:s,signal:a}=i,r=Math.round(i.width),o=Math.round(i.height);if(!Number.isFinite(r)||!Number.isFinite(o)||r<2||o<2||r>4096||o>4096||r*o>16777216)throw new Error("Choose export dimensions between 2 and 4096 pixels.");if(!["png","jpeg","mp4","webm","gif"].includes(s))throw new Error("Unknown export format.");if(void 0!==i.fps&&!Number.isFinite(i.fps))throw new Error("Frames per second must be finite.");const n=Math.max(1,Math.min(60,Math.round(i.fps??24))),h=i.duration??5;if(!Number.isFinite(h)||h<=0||h>60)throw new Error("Choose a duration from 0 to 60 seconds.");const c="png"===s||"jpeg"===s,f=i.time??0;if(!Number.isFinite(f)||f<0)throw new Error("Image time must be a finite non-negative number.");if(!c&&r*o>8294400)throw new Error("Video exports support up to 3840 × 2160 pixels.");if("gif"===s&&(r*o>921600||h*n>600))throw new Error("GIF export supports up to 1280 × 720 and 600 frames. Use MP4 for larger exports.");if(void 0!==i.referenceWidth&&(!Number.isFinite(i.referenceWidth)||i.referenceWidth<1))throw new Error("Reference width must be a positive number.");if("gif"===s&&n>30)throw new Error("GIF exports support up to 30 fps. Choose MP4 or WebM for higher frame rates.");const m=document.createElement("canvas"),d=O(m,l(e),{maxDimension:4096,maxCells:i.maxCells??12e3,pixelRatio:r/(i.referenceWidth??Math.min(r,960))});let u;try{if(_(a),i.onProgress?.(0),c){if(d.render(await t.frame(f,a),f,r,o),"unavailable"===m.dataset.studioFinish)throw new Error("Optical effects need WebGL. Disable these effects or export in a supported browser.");_(a);const e=await new Promise((t,e)=>m.toBlob(i=>i?t(i):e(new Error("Image export failed.")),"png"===s?"image/png":"image/jpeg",i.quality??.92));return i.onProgress?.(1),e}const e=Math.ceil(h*n);if("gif"===s){const s=await import("gifenc"),{GIFEncoder:l,quantize:c,applyPalette:f}="function"==typeof s.GIFEncoder?s:s.default,u=l(),g=m.getContext("2d");for(let s=0;s<e;s++){_(a);const l=s/n;if(d.invalidate(),d.render(await t.frame(l,a),l,r,o),"unavailable"===m.dataset.studioFinish)throw new Error("Optical effects need WebGL. Disable these effects or export in a supported browser.");const p=g.getImageData(0,0,r,o).data,M=c(p,256),x=f(p,M);u.writeFrame(x,r,o,{palette:M,delay:10*(Math.round(100*Math.min((s+1)/n,h))-Math.round(100*s/n)),repeat:0}),i.onProgress?.((s+1)/e*.98),await new Promise(t=>setTimeout(t,0))}return u.finish(),i.onProgress?.(1),new Blob([new Uint8Array(u.bytes())],{type:"image/gif"})}const{Output:l,Mp4OutputFormat:g,WebMOutputFormat:p,BufferTarget:M,CanvasSource:x,canEncodeVideo:v}=await import("mediabunny"),b="mp4"===s?"avc":"vp9";if(!await v(b,{width:r,height:o}))throw new Error(`${s.toUpperCase()} encoding is unavailable in this browser. Try another format or a current browser with WebCodecs.`);const w=new l({format:"mp4"===s?new g({fastStart:"in-memory"}):new p,target:new M});m.width=r,m.height=o,u=()=>w.cancel();const y=new x(m,{codec:b,bitrate:Math.max(5e5,Math.round(r*o*n*.15))});w.addVideoTrack(y,{frameRate:n}),m.width=r,m.height=o,await w.start();for(let s=0;s<e;s++){_(a);const l=s/n;if(d.invalidate(),d.render(await t.frame(l,a),l,r,o),"unavailable"===m.dataset.studioFinish)throw new Error("Optical effects need WebGL. Disable these effects or export in a supported browser.");await y.add(l,Math.min(1/n,h-l)),i.onProgress?.((s+1)/e*.98),s%4==0&&await new Promise(t=>setTimeout(t,0))}return y.close(),_(a),await w.finalize(),u=void 0,i.onProgress?.(1),new Blob([w.target.buffer],{type:"mp4"===s?"video/mp4":"video/webm"})}catch(t){throw await(u?.().catch(()=>{})),t}finally{d.destroy(),m.width=m.height=1}}async function q(t,e,i={}){const s=await z(e,i.signal);try{return G(t,s,i)}catch(t){throw s.destroy(),t}}function G(t,e,i={}){let s=l(i.settings),a=i.width??e.width,r=i.height??e.height;const o=O(t,s,i),n=new y;let h=0,c=!1,f=!0,m=!1,g=!0,p=0,M=0,x=0,v=-1,b=!1!==i.adaptive,w=0,S=0,k=0;const E=matchMedia("(prefers-reduced-motion: reduce)"),A=e.source instanceof HTMLVideoElement?e.source:null,F=()=>{c||h||!g||document.hidden||(h=requestAnimationFrame(P))},T=()=>!m&&!E.matches&&g&&!document.hidden,I=()=>{A&&(A.loop=!0,T()?A.play().catch(()=>{m=!0,f=!0,F()}):A.pause()),M=0,f=!0,F()};function P(t){if(h=0,c||!g||document.hidden)return;const l=T();l&&(p+=M?Math.min(.1,(t-M)/1e3):0),M=t;const u=l&&(e.animated||"none"!==s.motion.type||"none"!==s.dither.motion||s.effects.grain>0||s.effects.dust>0||s.effects.glitch>0),y=A?.getVideoPlaybackQuality?.().totalVideoFrames??-1,E="none"!==s.motion.type||"none"!==s.dither.motion||s.effects.grain>0||s.effects.dust>0||s.effects.glitch>0,I=!A||y<0||y!==v;if(f||o.active||u&&(I||E)&&t-x>=1e3/Math.max(1,Math.min(60,i.fps??60))-.5){const h=performance.now();try{e.animated&&!A&&o.invalidate();const[t,l]=d(a,r,s);o.render(e.frame(A?.currentTime??p),p,t,l,n.update(p,s.motion.type,s.motion.speed));const c=performance.now()-h;i.onFrame?.(A?.currentTime??p,c),S=S?.9*S+.1*c:c,++w>20&&b&&(u||o.active)&&(k=S>13?k+1:0,k>=12&&o.maxCells>3e3&&(o.setBudget(Math.max(3e3,.8*o.maxCells)),i.onQualityChange?.(o.maxCells),k=0,S=0))}catch(t){m=!0,i.onError?.(t instanceof Error?t:new Error(String(t)))}f=!1,x=t,v=y}l&&(u||o.active)&&F()}const R=e=>{if(!T())return;const i=t.getBoundingClientRect();o.pointer((e.clientX-i.left)/i.width,(e.clientY-i.top)/i.height,e.timeStamp),F()},C=()=>{o.leave(),F()},L=new IntersectionObserver(([t])=>{g=t.isIntersecting,I()});L.observe(t),t.addEventListener("pointermove",R),t.addEventListener("pointerleave",C),t.addEventListener("pointercancel",C),document.addEventListener("visibilitychange",I),E.addEventListener("change",I);const N=()=>{c||(c=!0,cancelAnimationFrame(h),L.disconnect(),t.removeEventListener("pointermove",R),t.removeEventListener("pointerleave",C),t.removeEventListener("pointercancel",C),document.removeEventListener("visibilitychange",I),E.removeEventListener("change",I),i.signal?.removeEventListener("abort",N),o.destroy(),e.destroy())};if(i.signal?.addEventListener("abort",N,{once:!0}),i.signal?.aborted)throw N(),new DOMException("Cancelled","AbortError");return I(),{canvas:t,media:e,update(t){s=u(s,t),o.configure(s),f=!0,F()},resize(t,e,i){void 0!==i&&o.setPixelRatio(i),a=Math.max(2,t),r=Math.max(2,e),f=!0,F()},pause(t=!0){m=t,I()},async seek(t){p=Math.max(0,t),await e.seek(p),o.invalidate(),f=!0,F()},redraw(){o.invalidate(),f=!0,F()},get time(){return A?.currentTime??p},get paused(){return m||E.matches},setAdaptive(t){b=t,w=k=S=0},setBudget(t){o.setBudget(t),i.onQualityChange?.(o.maxCells),f=!0,F()},get pixelRatio(){return o.pixelRatio},get maxCells(){return o.maxCells},get capabilities(){return o.capabilities},destroy:N}}var j={Standard:()=>import("figlet/fonts/Standard"),Slant:()=>import("figlet/fonts/Slant"),Small:()=>import("figlet/fonts/Small"),Big:()=>import("figlet/fonts/Big"),Banner:()=>import("figlet/fonts/Banner"),Block:()=>import("figlet/fonts/Block"),Bubble:()=>import("figlet/fonts/Bubble"),Digital:()=>import("figlet/fonts/Digital"),Doom:()=>import("figlet/fonts/Doom"),Lean:()=>import("figlet/fonts/Lean"),Mini:()=>import("figlet/fonts/Mini"),Script:()=>import("figlet/fonts/Script"),Shadow:()=>import("figlet/fonts/Shadow"),Speed:()=>import("figlet/fonts/Speed"),Starwars:()=>import("figlet/fonts/Star Wars"),Stop:()=>import("figlet/fonts/Stop"),Straight:()=>import("figlet/fonts/Straight"),Thin:()=>import("figlet/fonts/Thin"),ThreeD:()=>import("figlet/fonts/3-D"),Univers:()=>import("figlet/fonts/Univers"),Wavy:()=>import("figlet/fonts/Wavy")},V=Object.keys(j);async function H(t,e="Standard",i="#ffffff"){if(!Object.prototype.hasOwnProperty.call(j,e))throw new Error("Unknown text font.");const{default:s}=await import("figlet/browser"),a=await j[e]();s.parseFont(e,a.default),s.defaults({fetchFontIfMissing:!1});const r=s.textSync(t.slice(0,120),{font:e}),o=r.split("\n"),n=Math.max(1,...o.map(t=>t.length)),h=Math.max(1,o.length),l=Math.min(1,2048/(9*n)),c=document.createElement("canvas");c.width=Math.ceil(9*n*l+32),c.height=Math.ceil(15*h*l+32);const f=c.getContext("2d");return f.fillStyle="#080808",f.fillRect(0,0,c.width,c.height),f.fillStyle=i,f.font=15*l+"px monospace",f.textBaseline="top",o.forEach((t,e)=>f.fillText(t,16,16+15*e*l)),{canvas:c,ascii:r}}var $={standard:{label:"Classic ASCII",chars:" .:-=+*#%@"},asciify:{label:"Asciify",chars:" .:-=+ASCIIFY#@"},minimal:{label:"Minimal",chars:" .:+"},detailed:{label:"Detailed",chars:" .,:;i1tfLCG08@"},letters:{label:"Letters",chars:" .ilLCFTYASMW"},technical:{label:"Technical",chars:" .:;>_/[{}]=+*#@$"},blocks:{label:"Tonal blocks",chars:" ░▒▓█"},braille:{label:"Braille",chars:" ⠁⠃⠇⡇⣇⣧⣷⣿"}},Q=$;export{i as BLEND_MODES,$ as CHARACTER_SETS,a as DEFAULT_STUDIO_SETTINGS,e as DITHER_ALGORITHMS,Q as STUDIO_CHARACTER_SETS,p as STUDIO_LOOKS,v as STUDIO_MOTIONS,s as STUDIO_PALETTES,t as STUDIO_STYLES,V as STUDIO_TEXT_FONTS,O as createStudioRenderer,H as createStudioText,W as exportStudio,z as loadStudioMedia,q as mountStudio,G as mountStudioMedia,l as normalizeStudioSettings,f as parseStudioSettings,x as restyleStudio,c as serializeStudioSettings,m as studioCrop,d as studioDimensions,g as studioGrid,M as studioLook,D as studioSourceSize,u as updateStudioSettings};//# sourceMappingURL=studio.js.map
|
|
1
|
+
var t=["ascii","blocks","braille","dots","lines","cross","diagonal","diamond","mixed","pixel","mosaic","lego","voxel","disco","dither","hex","led","cmyk"],e=["none","bayer2","bayer4","bayer8","bayer16","floyd-steinberg","atkinson","stucki","sierra","sierra-lite","burkes","jarvis","halftone","lines","noise","vertical-lines","diagonal-lines","radial"],i=["source-over","multiply","screen","overlay","soft-light","hard-light","color-dodge","color-burn","hue","saturation","color","luminosity"],a={original:[],gray4:["#000000","#555555","#aaaaaa","#ffffff"],gray8:["#000000","#242424","#494949","#6d6d6d","#929292","#b6b6b6","#dbdbdb","#ffffff"],rgb8:["#000000","#ff0000","#00ff00","#0000ff","#ffff00","#ff00ff","#00ffff","#ffffff"],cyberpunk:["#08081a","#3c1670","#ed299a","#29dfef","#fff7bf"],pastel:["#393448","#a5b4d4","#9ed9c6","#e7aac1","#f5e8be"],mono:["#080808","#f2f2e8"],asciify:["#080808","#625b38","#a19558","#e8b900"],gameboy:["#0f380f","#306230","#8bac0f","#9bbc0f"],cga:["#000000","#55ffff","#ff55ff","#ffffff"],pico8:["#000000","#1d2b53","#7e2553","#008751","#ab5236","#5f574f","#c2c3c7","#fff1e8","#ff004d","#ffa300","#ffec27","#00e436","#29adff","#83769c","#ff77a8","#ffccaa"],c64:["#000000","#ffffff","#880000","#aaffee","#cc44cc","#00cc55","#0000aa","#eeee77","#dd8855","#664400","#ff7777","#333333","#777777","#aaff66","#0088ff","#bbbbbb"],amber:["#100b00","#5f3b00","#c98014","#ffd17c"],ice:["#081b29","#25586e","#69a6b3","#d9ece7"],risograph:["#f4ebd0","#f2594b","#2853a5","#29232e"],sepia:["#201b17","#6b5039","#b49868","#f6e6c5"],nord:["#2e3440","#4c566a","#88c0d0","#eceff4"],dusk:["#211b35","#654271","#c3788c","#f5c9a3"],forest:["#101f1b","#355747","#87a16f","#e4e3ba"],ocean:["#071b33","#17577f","#3fa7a4","#d9efde"],newsprint:["#191919","#666666","#aaaaaa","#eee9df"],custom:["#080808","#e8b900"]},s={version:1,aspectRatio:"original",style:"ascii",cellSize:6,charset:" .:-=+*#%@",colorMode:"accent",ink:"#e8b900",crop:{x:.5,y:.5,zoom:1,rotation:0},backdrop:{mode:"solid",color:"#080808",color2:"#393323",blur:12,opacity:1},color:{brightness:0,contrast:1,saturation:1,grayscale:0,tint:"#e8b900",amount:0,blend:"source-over"},dither:{algorithm:"none",palette:"mono",colors:["#080808","#e8b900"],amount:1,scale:2,threshold:.5,motion:"none",speed:1,direction:45,colorSpace:"rgb"},mask:{enabled:!1,invert:!1,shapes:[]},lights:[],effects:{bloom:0,characterBloom:0,grain:0,dust:0,scanlines:0,crt:0,prism:0,rgbSplit:0,sharpen:0,vignette:0,glitch:0,pixelate:0,blur:0,blurType:"gaussian",angle:0,focus:.5,halftone:0},motion:{type:"none",speed:1,amount:1},hover:{effect:"trail",strength:.55,radius:.2,edgeSafe:!1}},r=t=>t&&"object"==typeof t&&!Array.isArray(t)?t:{},o=(t,e,i,a)=>"number"==typeof t&&Number.isFinite(t)?Math.min(a,Math.max(i,t)):e,n=(t,e)=>"string"==typeof t&&/^#[\da-f]{6}$/i.test(t)?t:e,h=(t,e,i)=>e.includes(t)?t:i;function l(l={}){const c=r(l),f=s;if(void 0!==c.version&&1!==c.version)throw new Error("Unsupported studio settings version. Update asciify-engine.");const m=r(c.crop),d=r(c.backdrop),u=r(c.color),g=r(c.dither),p=r(c.mask),M=r(c.effects),x=r(c.motion),v=r(c.hover),b={...f.effects};for(const t of["bloom","characterBloom","grain","dust","scanlines","crt","prism","rgbSplit","sharpen","vignette","glitch","pixelate","halftone"])b[t]=o(M[t],0,0,1);b.blur=o(M.blur,0,0,24),b.blurType=h(M.blurType,["gaussian","directional","radial","progressive"],f.effects.blurType),b.angle=o(M.angle,0,-180,180),b.focus=o(M.focus,.5,0,1);let w=2048;return{version:1,aspectRatio:h(c.aspectRatio,["original","16:9","9:16","1:1","4:3","3:4","21:9"],"original"),style:h(c.style,t,f.style),cellSize:o(c.cellSize,f.cellSize,["pixel","mosaic","lego","voxel","disco","dots","hex","led","cmyk"].includes(String(c.style))?1:3,60),charset:"string"==typeof c.charset&&c.charset.length?Array.from(c.charset).slice(0,128).join(""):f.charset,colorMode:h(c.colorMode,["accent","source","gray"],f.colorMode),ink:n(c.ink,f.ink),crop:{x:o(m.x,.5,0,1),y:o(m.y,.5,0,1),zoom:o(m.zoom,1,1,5),rotation:90*Math.round(o(m.rotation,0,-360,360)/90)},backdrop:{mode:h(d.mode,["solid","transparent","source","blurred","gradient"],f.backdrop.mode),color:n(d.color,f.backdrop.color),color2:n(d.color2,f.backdrop.color2),blur:o(d.blur,12,0,32),opacity:o(d.opacity,1,0,1)},color:{brightness:o(u.brightness,0,-1,1),contrast:o(u.contrast,1,0,3),saturation:o(u.saturation,1,0,3),grayscale:o(u.grayscale,0,0,1),tint:n(u.tint,f.color.tint),amount:o(u.amount,0,0,1),blend:h(u.blend,i,f.color.blend)},dither:{algorithm:h(g.algorithm,e,"none"),palette:"string"==typeof g.palette&&Object.prototype.hasOwnProperty.call(a,g.palette)?g.palette:"mono",colors:Array.isArray(g.colors)&&g.colors.length>=2?g.colors.slice(0,32).map(t=>n(t,"#000000")):[...f.dither.colors],amount:o(g.amount,1,0,2),scale:Math.round(o(g.scale,2,1,12)),threshold:o(g.threshold,.5,0,1),motion:h(g.motion,["none","drift","shimmer"],"none"),speed:o(g.speed,1,.1,3),direction:o(g.direction,45,-180,180),colorSpace:h(g.colorSpace,["rgb","luminance"],"rgb")},mask:{enabled:!0===p.enabled,invert:!0===p.invert,shapes:Array.isArray(p.shapes)?p.shapes.slice(0,64).map(t=>{const e=r(t),i=h(e.kind,["rectangle","ellipse","brush"],"rectangle"),a="brush"===i&&Array.isArray(e.points)?e.points.slice(0,w).map(t=>Array.isArray(t)?[Math.round(1e4*o(t[0],0,0,1))/1e4,Math.round(1e4*o(t[1],0,0,1))/1e4]:[0,0]):[];return w-=a.length,{kind:i,x:o(e.x,0,0,1),y:o(e.y,0,0,1),width:o(e.width,.5,0,1),height:o(e.height,.5,0,1),size:o(e.size,.05,.005,.5),points:a}}):[]},lights:Array.isArray(c.lights)?c.lights.slice(0,4).map(t=>{const e=r(t);return{x:o(e.x,.5,0,1),y:o(e.y,.5,0,1),radius:o(e.radius,.3,.02,1),intensity:o(e.intensity,.5,0,1),color:n(e.color,"#ffffff")}}):[],effects:b,motion:{type:h(x.type,["none","caustics","current","reform","sheen","tidal","grain"],"none"),speed:o(x.speed,1,.1,3),amount:o(x.amount,1,0,2)},hover:{effect:h(v.effect,["none","trail","water","contour","dissolve","silk","vortex","magnetic","scatter"],"trail"),strength:o(v.strength,.55,0,1),radius:o(v.radius,.2,.1,1),edgeSafe:!0===v.edgeSafe}}}function c(t){return JSON.stringify(l(t))}function f(t){if(t.length>1e5)throw new Error("Settings exceed 100 KB.");return l(JSON.parse(t))}function m(t,e,i,a,s){const r=Math.abs(s.rotation/90)%2==1,o=r?e:t,n=r?t:e,h=Math.max(i/o,a/n)*s.zoom;return{width:o*h,height:n*h,x:(i-o*h)*s.x,y:(a-n*h)*s.y,scale:h,rotated:r}}function d(t,e,i){if(Math.abs(i.crop.rotation/90)%2==1&&([t,e]=[e,t]),"original"===i.aspectRatio)return[t,e];const[a,s]=i.aspectRatio.split(":").map(Number);return t/e>a/s?[Math.round(e*a/s),e]:[t,Math.round(t*s/a)]}function u(t,e){const i={...t,...e};for(const a of["crop","backdrop","color","dither","mask","effects","motion","hover"])e[a]&&Object.assign(i,{[a]:{...t[a],...e[a]}});return l(i)}function g(t,e,i,a=12e3,s=1){const r=Math.max(2,Number.isFinite(t)?t:960),o=Math.max(2,Number.isFinite(e)?e:540),n=Math.max(1,Math.floor(Number.isFinite(a)?a:12e3)),h=Math.max(.01,Number.isFinite(s)?s:1),l=["dither","pixel","mosaic","lego","voxel","disco","dots","hex","led","cmyk"].includes(i.style)?1:1.65;let c=Math.max(1,Math.ceil(Math.sqrt(r*o/(n*l))/h));for(;Math.ceil(r/(c*h))*Math.ceil(o/(c*h*l))>n;)c++;const f="dither"===i.style?i.dither.scale:i.cellSize,m=Math.max(c,f)*h;return{cell:m,rowHeight:m*l,columns:Math.ceil(r/m),rows:Math.ceil(o/(m*l)),minimum:c,limited:f<c}}var p=[["ascii","Signature ASCII","Brand ink and clean characters.",{}],["print","Newsprint","Fine diffusion on warm paper.",{style:"dither",dither:{algorithm:"floyd-steinberg",palette:"newsprint"}}],["handheld","Pocket camera","Four-tone ordered dither.",{style:"dither",dither:{algorithm:"bayer4",palette:"gameboy",scale:3}}],["riso","Two inks","Limited-color print texture.",{style:"dither",dither:{algorithm:"atkinson",palette:"risograph",scale:2}}],["night","Night signal","Gray characters and optical fringe.",{ink:"#888888",effects:{prism:.7,scanlines:.2,vignette:.3}}],["terminal","Phosphor","Green glyphs with a soft glow.",{ink:"#83efad",effects:{bloom:.4,scanlines:.35,crt:.2}}],["mosaic","Mosaic study","Separated color tiles.",{style:"mosaic",cellSize:14,colorMode:"source"}],["bricks","Brickwork","Colorful studded cells.",{style:"lego",cellSize:18,colorMode:"source"}],["voxel","Little volumes","Three-face isometric tiles.",{style:"voxel",cellSize:22,colorMode:"source"}],["disco","Mirror room","Faceted tiles and warm light.",{style:"disco",cellSize:18,colorMode:"source",lights:[{x:.35,y:.25,radius:.25,intensity:.45,color:"#fff2d4"}]}],["wallpaper","Wallpaper","Living ASCII over a softened source.",{backdrop:{mode:"blurred",blur:18,opacity:.55},ink:"#f2e9c9",motion:{type:"caustics",speed:.5}}],["blueprint","Blueprint","Linework in a cool monochrome.",{style:"lines",ink:"#9bccdf",backdrop:{mode:"solid",color:"#0a1e30"}}]].map(([t,e,i,a])=>({id:t,name:e,description:i,settings:l(a)}));function M(t){const e=p.find(e=>e.id===t);if(!e)throw new Error("Unknown studio look.");return l(e.settings)}function x(t,e=Math.random){const i=p.filter(e=>e.settings.style!==t.style||e.settings.ink!==t.ink),a=M(i[Math.min(i.length-1,Math.max(0,Math.floor(e()*i.length)))].id);return a.aspectRatio=t.aspectRatio,a.crop={...t.crop},a.mask=l(t).mask,a}var v=[{value:"none",mode:"none",label:"Off",description:"Keep the image still. Hover stays available."},{value:"caustics",mode:"caustics",label:"Caustics",description:"Soft ribbons of light travel across a stationary character grid."},{value:"current",mode:"current",label:"Slow Current",description:"A gentle flow through the image, with steady edges."},{value:"reform",mode:"reform",label:"Reveal & Reform",description:"Disperse, gather, then hold the complete image."},{value:"sheen",mode:"sheen",label:"Sheen",description:"A broad diagonal light sweep; characters stay anchored."},{value:"tidal",mode:"tidal",label:"Tidal Rings",description:"Concentric currents travel outward, with protected edges."},{value:"grain",mode:"grain",label:"Living Grain",description:"Slow, individually phased tonal changes on a stationary grid."}],b=t=>Math.max(0,Math.min(1,t)),w=(t,e,i)=>{const a=b((i-t)/(e-t));return a*a*(3-2*a)},y=(t,e)=>{const i=(.06711056*t+.00583715*e)%1*52.9829189;return i-Math.floor(i)},S=class{constructor(){this.last=null,this.mode="none",this.phase=0}update(t,e,i=1){return Number.isFinite(t)?((e!==this.mode||null!==this.last&&t<this.last)&&(this.mode=e,this.phase=0,this.last=t),null!==this.last&&(this.phase+=Math.max(0,t-this.last)*Math.max(.1,Math.min(3,Number.isFinite(i)?i:1))),this.last=t,this.phase):this.phase}};function k(t,e,i,a,s){if(s[0]=s[1]=s[2]=0,s[3]=1,"none"===t)return s;const r=a*Math.PI/6,o=w(0,.12,Math.min(e,1-e,i,1-i));if("caustics"===t){const t=Math.sin(9*e+5*i+r)+Math.sin(8*i-3*e-r),a=Math.pow(Math.max(0,1-.72*Math.abs(t)),3);s[2]=(.22*a-.045)*o}else if("current"===t)s[0]=Math.sin(9*i+r)*Math.cos(7*e-r)*10*o,s[1]=Math.cos(8*e+r)*Math.sin(6*i-r)*7*o;else if("sheen"===t)s[2]=.2*Math.pow(.5+.5*Math.cos(5*e+3*i-r),8)-.025;else if("tidal"===t){const t=e-.5,a=i-.5,n=Math.hypot(t,a),h=Math.sin(22*n-r)*o;s[0]=t*h*9,s[1]=a*h*9,s[2]=.035*h}else if("grain"===t){const t=y(Math.floor(160*e),Math.floor(100*i))*Math.PI*2;s[2]=.07*Math.sin(r+t)}else if("reform"===t){const t=(a%12+12)%12,n=y(Math.floor(160*e),Math.floor(100*i)),h=.65*e+.2*i+.15*n+.08*Math.sin(8*e-5*i),l=w(1.8+1.2*h,3.8+1.2*h,t)*(1-w(5+1.7*h,7.2+1.7*h,t));s[0]=Math.sin(9*i+r)*l*(1-l)*24*o,s[1]=-l*(1-l)*(8+12*n)*o,s[2]=.45*-l,s[3]=1-.9*l}return s}function E(t,e){const i=Math.max(0,Math.min(2,Number.isFinite(e)?e:1));return t[0]*=i,t[1]*=i,t[2]*=i,t[3]=b(1+(t[3]-1)*i),t}var A=(t,e)=>{const i=43758.5453*Math.sin(127.1*t+311.7*e);return i-Math.floor(i)};function F(t,e,i){let a=0;for(let s=1;s<i;s*=2){const i=(Math.floor(t/s)%2+2)%2;a=4*a+[[0,2],[3,1]][(Math.floor(e/s)%2+2)%2][i]}return(a+.5)/(i*i)-.5}var T={"floyd-steinberg":[[1,0,7/16],[-1,1,3/16],[0,1,5/16],[1,1,1/16]],atkinson:[[1,0,.125],[2,0,.125],[-1,1,.125],[0,1,.125],[1,1,.125],[0,2,.125]],stucki:[[1,0,8/42],[2,0,4/42],[-2,1,2/42],[-1,1,4/42],[0,1,8/42],[1,1,4/42],[2,1,2/42],[-2,2,1/42],[-1,2,2/42],[0,2,4/42],[1,2,2/42],[2,2,1/42]],sierra:[[1,0,5/32],[2,0,3/32],[-2,1,2/32],[-1,1,4/32],[0,1,5/32],[1,1,4/32],[2,1,2/32],[-1,2,2/32],[0,2,3/32],[1,2,2/32]],"sierra-lite":[[1,0,.5],[-1,1,.25],[0,1,.25]],burkes:[[1,0,.25],[2,0,4/32],[-2,1,2/32],[-1,1,4/32],[0,1,.25],[1,1,4/32],[2,1,2/32]],jarvis:[[1,0,7/48],[2,0,5/48],[-2,1,3/48],[-1,1,5/48],[0,1,7/48],[1,1,5/48],[2,1,3/48],[-2,2,1/48],[-1,2,3/48],[0,2,5/48],[1,2,3/48],[2,2,1/48]]},I=t=>[parseInt(t.slice(1,3),16),parseInt(t.slice(3,5),16),parseInt(t.slice(5,7),16)];function P(t,e,i){const a=Math.min(t*Math.max(1,i),(1-t)*Math.max(1,i),e*Math.max(1,1/i),(1-e)*Math.max(1,1/i)),s=Math.max(0,Math.min(1,(a-.035)/.105));return s*s*s*(s*(6*s-15)+10)}var R=class{constructor(t,e){this.edgeSafe=!1,this.previous=null,this.peak=0,this.mode="dissolve",this.width=t,this.height=e;const i=t*e;this.pixels=new Uint8Array(4*i),this.ink=new Float32Array(i),this.targetX=new Float32Array(i),this.targetY=new Float32Array(i),this.offsetX=new Float32Array(i),this.offsetY=new Float32Array(i),this.edge=new Float32Array(i);for(let i=0;i<e;i++)for(let a=0;a<t;a++)this.edge[i*t+a]=P(a/(t-1),i/(e-1),t/e);this.clear()}get active(){return this.peak>2e-4}setMode(t){t!==this.mode&&(this.mode=t,this.clear())}clear(){for(const t of[this.ink,this.targetX,this.targetY,this.offsetX,this.offsetY,this.pixels])t.fill(0);if(this.previous=null,this.peak=0,"dissolve"!==this.mode)for(let t=0;t<this.pixels.length;t+=4)this.pixels[t]=this.pixels[t+2]=128}leave(){this.previous=null}move(t,e,i){if(!Number.isFinite(t+e+i))return;t=Math.max(0,Math.min(1,t)),e=Math.max(0,Math.min(1,e));const a=this.previous;this.previous={x:t,y:e};const s=this.width,r=this.height,o=Math.max(1,s/r),n=Math.max(1,r/s),h=a?(t-a.x)*o:0,l=a?(e-a.y)*n:0,c=Math.hypot(h,l);if(!a&&"dissolve"!==this.mode)return;if(a&&c<1e-4)return;const f=.035+.11*Math.max(.1,Math.min(1,i)),m=Math.min(128,Math.max(1,Math.ceil(c/(.45*f)))),d=c?h/c:1,u=c?l/c:0,g=Math.min(1,c/(f*m)*2.2);for(let i=0;i<m;i++){const h=(i+.5)/m,l=a?a.x+(t-a.x)*h:t,c=a?a.y+(e-a.y)*h:e,p=Math.max(0,Math.floor((l-2.5*f/o)*(s-1))),M=Math.min(s-1,Math.ceil((l+2.5*f/o)*(s-1))),x=Math.max(0,Math.floor((c-2.5*f/n)*(r-1))),v=Math.min(r-1,Math.ceil((c+2.5*f/n)*(r-1)));for(let t=x;t<=v;t++)for(let e=p;e<=M;e++){const i=(e/(s-1)-l)*o/f,a=(t/(r-1)-c)*n/f,h=Math.exp(1.5*-(i*i+a*a)),m=t*s+e;if("dissolve"===this.mode)this.ink[m]=Math.max(this.ink[m],h);else{const s=(-i*u+a*d)*h*2.8,r=43758.5453*Math.sin(127.1*e+311.7*t),o=(r-Math.floor(r))*Math.PI*2,n="magnetic"===this.mode?-i*h*2.5:"scatter"===this.mode?(i+.7*Math.cos(o))*h*2:"silk"===this.mode?d*s:-a*h*2.5,l="magnetic"===this.mode?-a*h*2.5:"scatter"===this.mode?(a+.7*Math.sin(o))*h*2:"silk"===this.mode?u*s:i*h*2.5;this.targetX[m]=Math.max(-1,Math.min(1,this.targetX[m]+n*g)),this.targetY[m]=Math.max(-1,Math.min(1,this.targetY[m]+l*g))}}}this.peak=1}step(t){if(!this.active||!Number.isFinite(t))return;const e=Math.max(0,Math.min(.05,t)),i=Math.exp(-("dissolve"===this.mode?2.15:3.2)*e),a=1-Math.exp(-22*e);let s=0;for(let t=0;t<this.ink.length;t++)if("dissolve"===this.mode){this.ink[t]*=i,s=Math.max(s,this.ink[t]);const e=Math.round(65535*this.ink[t]);this.pixels[4*t]=e>>>8,this.pixels[4*t+1]=255&e}else{this.targetX[t]*=i,this.targetY[t]*=i,this.offsetX[t]+=(this.targetX[t]-this.offsetX[t])*a,this.offsetY[t]+=(this.targetY[t]-this.offsetY[t])*a,s=Math.max(s,Math.abs(this.offsetX[t]),Math.abs(this.offsetY[t]),Math.abs(this.targetX[t]),Math.abs(this.targetY[t]));const e=Math.round(this.offsetX[t]*(this.edgeSafe?this.edge[t]:1)*32767+32768),r=Math.round(this.offsetY[t]*(this.edgeSafe?this.edge[t]:1)*32767+32768);this.pixels[4*t]=e>>>8,this.pixels[4*t+1]=255&e,this.pixels[4*t+2]=r>>>8,this.pixels[4*t+3]=255&r}this.peak=s,this.active||this.clear()}sample(t,e,i){const a=Math.max(0,Math.min(this.width-1.001,t*(this.width-1))),s=Math.max(0,Math.min(this.height-1.001,e*(this.height-1))),r=Math.floor(a),o=Math.floor(s),n=a-r,h=s-o,l=o*this.width+r,c=l+this.width,f=t=>(t[l]*(1-n)+t[l+1]*n)*(1-h)+(t[c]*(1-n)+t[c+1]*n)*h;i[0]=f(this.offsetX)*(this.edgeSafe?P(t,e,this.width/this.height):1)*.08,i[1]=f(this.offsetY)*(this.edgeSafe?P(t,e,this.width/this.height):1)*.08,i[2]="dissolve"===this.mode?6*-f(this.ink):0}},C=class{constructor(t,e){this.rings=[],this.previous=null,this.elapsed=1,this.echoPeak=0,this.width=t,this.height=e,this.pixels=new Uint8Array(t*e*4),this.echo=new Float32Array(t*e)}get active(){return this.rings.length>0||this.echoPeak>2e-4}clear(){this.rings=[],this.previous=null,this.elapsed=1,this.pixels.fill(0),this.echo.fill(0),this.echoPeak=0}leave(){this.previous=null}move(t,e,i){const a=Math.max(1,this.width/this.height),s=Math.max(1,this.height/this.width);this.previous&&(Math.hypot((t-this.previous.x)*a,(e-this.previous.y)*s)<.065||this.elapsed<.3)||4!==this.rings.length&&(this.previous={x:t,y:e},this.elapsed=0,this.rings.push({x:t,y:e,age:0,radius:i}))}ringSample(t,e){const i=Math.max(1,this.width/this.height),a=Math.max(1,this.height/this.width);let s=0;for(const r of this.rings){const o=.015+r.age*(.15+.22*r.radius),n=.009+.014*r.radius,h=(Math.hypot((t-r.x)*i,(e-r.y)*a)-o)/n,l=Math.sin(Math.min(1,r.age/.07)*Math.PI/2)*Math.max(0,1-r.age/1.35)**2;s=Math.max(s,Math.exp(-h*h)*l)}return s}sample(t,e){const i=Math.max(0,Math.min(this.width-1,Math.round(t*(this.width-1)))),a=Math.max(0,Math.min(this.height-1,Math.round(e*(this.height-1))));return Math.max(this.ringSample(t,e),this.echo[a*this.width+i])}step(t){if(!Number.isFinite(t))return;const e=Math.max(0,Math.min(.05,t));this.elapsed+=e;for(const t of this.rings)t.age+=e;if(this.rings=this.rings.filter(t=>t.age<1.35),!this.active)return void this.pixels.fill(0);const i=Math.exp(-5.5*e);let a=0;for(let t=0;t<this.height;t++)for(let e=0;e<this.width;e++){const s=t*this.width+e;this.echo[s]=Math.max(this.ringSample(e/(this.width-1),t/(this.height-1)),this.echo[s]*i),a=Math.max(a,this.echo[s]);const r=Math.round(65535*this.echo[s]),o=4*s;this.pixels[o]=r>>>8,this.pixels[o+1]=255&r}this.echoPeak=a,this.active||(this.echo.fill(0),this.pixels.fill(0))}},L=class{constructor(t,e){this.previous=null,this.peak=0,this.width=t,this.height=e;const i=t*e;this.pixels=new Uint8Array(4*i),this.signal=new Float32Array(i),this.offsetX=new Float32Array(i),this.offsetY=new Float32Array(i),this.driftX=new Float32Array(i),this.driftY=new Float32Array(i),this.u=new Float32Array(i),this.v=new Float32Array(i),this.ink=new Float32Array(i),this.a=new Float32Array(i),this.b=new Float32Array(i),this.c=new Float32Array(i),this.pressure=new Float32Array(i),this.pressureNext=new Float32Array(i),this.divergence=new Float32Array(i),this.curl=new Float32Array(i)}get active(){return this.peak>2e-4}clear(){for(const t of[this.u,this.v,this.ink,this.a,this.b,this.c,this.pressure,this.pressureNext,this.divergence,this.curl,this.signal,this.pixels,this.offsetX,this.offsetY,this.driftX,this.driftY])t.fill(0);this.previous=null,this.peak=0}leave(){this.previous=null}move(t,e,i,a=performance.now()){if(!Number.isFinite(t+e+i+a))return;t=Math.max(0,Math.min(1,t)),e=Math.max(0,Math.min(1,e)),i=Math.max(.1,Math.min(1,i));const s=this.previous;if(this.previous={x:t,y:e,time:a},!s)return;const r=(t-s.x)*(this.width-1),o=(e-s.y)*(this.height-1),n=Math.hypot(r,o);if(n<.001)return;const h=Math.min(this.width,this.height),l=a>s.time?Math.max(1/240,(a-s.time)/1e3):1/60,c=Math.min(12,n/h/l),f=1-Math.exp(-c/2.2),m=h*(.022+.075*i)*(.65+.95*f),d=Math.min(128,Math.max(1,Math.ceil(n/(.4*m)))),u=n/m*(.32+.22*f)/d,g=r/n,p=o/n,M=-p,x=g,v=n*(2+18*f)/d;for(let i=0;i<d;i++){const a=(i+.5)/d,r=(s.x+(t-s.x)*a)*(this.width-1),o=(s.y+(e-s.y)*a)*(this.height-1),n=Math.max(1,Math.floor(r-3*m)),h=Math.min(this.width-2,Math.ceil(r+3*m)),l=Math.max(1,Math.floor(o-3*m)),c=Math.min(this.height-2,Math.ceil(o+3*m));for(let t=l;t<=c;t++)for(let e=n;e<=h;e++){const i=((e-r)*g+(t-o)*p)/m,a=((e-r)*M+(t-o)*x)/m,s=Math.exp(-i*i*.65-a*a*1.7),n=t*this.width+e;this.ink[n]=1-(1-this.ink[n])*Math.exp(-s*u);const h=1-a*a*.55,l=i*a*.7;this.u[n]=Math.max(-80,Math.min(80,this.u[n]+(g*h+M*l)*s*v)),this.v[n]=Math.max(-80,Math.min(80,this.v[n]+(p*h+x*l)*s*v))}}this.peak=1}read(t,e,i){const a=0|(e=Math.max(.5,Math.min(this.width-1.5,e))),s=0|(i=Math.max(.5,Math.min(this.height-1.5,i))),r=e-a,o=i-s,n=s*this.width+a;return(t[n]*(1-r)+t[n+1]*r)*(1-o)+(t[n+this.width]*(1-r)+t[n+this.width+1]*r)*o}sample(t,e){return this.read(this.signal,t*(this.width-1),e*(this.height-1))}displacement(t,e,i){i[0]=this.read(this.offsetX,t*(this.width-1),e*(this.height-1)),i[1]=this.read(this.offsetY,t*(this.width-1),e*(this.height-1))}step(t){if(!this.active||!Number.isFinite(t))return;let e=Math.max(0,Math.min(.05,t));const i=this.width,a=this.height;for(;e>1e-7;){const t=Math.min(1/60,e);e-=t;const s=Math.exp(-1.9*t),r=Math.exp(-3.2*t);for(let e=1;e<a-1;e++)for(let o=1;o<i-1;o++){const n=e*i+o,h=Math.max(.5,Math.min(i-1.5,o-this.u[n]*t)),l=Math.max(.5,Math.min(a-1.5,e-this.v[n]*t)),c=0|h,f=0|l,m=h-c,d=l-f,u=f*i+c,g=(1-m)*(1-d),p=m*(1-d),M=(1-m)*d,x=m*d;this.a[n]=(this.u[u]*g+this.u[u+1]*p+this.u[u+i]*M+this.u[u+i+1]*x)*s,this.b[n]=(this.v[u]*g+this.v[u+1]*p+this.v[u+i]*M+this.v[u+i+1]*x)*s,this.c[n]=(this.ink[u]*g+this.ink[u+1]*p+this.ink[u+i]*M+this.ink[u+i+1]*x)*r}[this.u,this.a]=[this.a,this.u],[this.v,this.b]=[this.b,this.v],[this.ink,this.c]=[this.c,this.ink];for(let t=1;t<a-1;t++)for(let e=1;e<i-1;e++){const a=t*i+e;this.curl[a]=.5*(this.v[a+1]-this.v[a-1]-this.u[a+i]+this.u[a-i])}for(let e=1;e<a-1;e++)for(let a=1;a<i-1;a++){const s=e*i+a,r=Math.abs(this.curl[s+1])-Math.abs(this.curl[s-1]),o=Math.abs(this.curl[s+i])-Math.abs(this.curl[s-i]),n=Math.hypot(r,o)+1e-4,h=this.curl[s]*t*10,l=Math.hypot(this.u[s],this.v[s]);this.u[s]+=o/n*h,this.v[s]-=r/n*h;const c=Math.min(1,l/(Math.hypot(this.u[s],this.v[s])+1e-6));this.u[s]*=c,this.v[s]*=c,this.divergence[s]=-.5*(this.u[s+1]-this.u[s-1]+this.v[s+i]-this.v[s-i])}this.pressure.fill(0);for(let t=0;t<4;t++){for(let t=1;t<a-1;t++)for(let e=1;e<i-1;e++){const a=t*i+e;this.pressureNext[a]=.25*(this.divergence[a]+this.pressure[a-1]+this.pressure[a+1]+this.pressure[a-i]+this.pressure[a+i])}[this.pressure,this.pressureNext]=[this.pressureNext,this.pressure]}let o=0;for(let e=1;e<a-1;e++)for(let a=1;a<i-1;a++){const s=e*i+a;this.u[s]=Math.max(-80,Math.min(80,this.u[s]-.5*(this.pressure[s+1]-this.pressure[s-1]))),this.v[s]=Math.max(-80,Math.min(80,this.v[s]-.5*(this.pressure[s+i]-this.pressure[s-i]))),this.driftX[s]+=(3.6*this.u[s]-58*this.offsetX[s]-12*this.driftX[s])*t,this.driftY[s]+=(3.6*this.v[s]-58*this.offsetY[s]-12*this.driftY[s])*t,this.offsetX[s]=Math.max(-2,Math.min(2,this.offsetX[s]+this.driftX[s]*t)),this.offsetY[s]=Math.max(-2,Math.min(2,this.offsetY[s]+this.driftY[s]*t)),this.signal[s]=1-Math.exp(.06*-Math.hypot(this.u[s],this.v[s])-.16*this.ink[s]),o=Math.max(o,this.signal[s])}this.peak=o}if(this.active)for(let t=0;t<this.ink.length;t++){const e=Math.round(65535*Math.min(1,this.signal[t]));this.pixels[4*t]=e>>>8,this.pixels[4*t+1]=255&e,this.pixels[4*t+2]=Math.round(128+63.5*this.offsetX[t]),this.pixels[4*t+3]=Math.round(128+63.5*this.offsetY[t])}else this.clear()}};function N(t,e){const i=Math.max(0,Math.min(1,e/.38));return t+(1-2*t)*(i*i*(3-2*i))}var D=class{constructor(t=1){this.mode="water",this.amount=.55,this.radius=.2,this.lensX=.5,this.lensY=.5,this.lensStrength=0,this.previous=null,this.energy=0,this.pending=!1,this.remainder=0,t=Math.max(.25,Math.min(4,t)),this.columns=Math.round(t>=1?128:128*t),this.rows=Math.round(t>=1?128/t:128),this.xScale=Math.max(1,t),this.yScale=Math.max(1,1/t),this.heights=new Float32Array(this.columns*this.rows),this.velocity=new Float32Array(this.heights.length),this.next=new Float32Array(this.heights.length),this.normals=new Float32Array(2*this.heights.length),this.edgeMask=new Float32Array(this.heights.length);for(let e=0;e<this.rows;e++)for(let i=0;i<this.columns;i++)this.edgeMask[e*this.columns+i]=P(i/(this.columns-1),e/(this.rows-1),t);this.refraction={width:this.columns,height:this.rows,pixels:new Uint8Array(4*this.heights.length),strength:30,mode:"water",focus:[.5,.5,0,.2]},this.waterPixels=this.refraction.pixels,this.trail=new L(this.columns,this.rows),this.contour=new C(this.columns,this.rows),this.afterimage=new R(this.columns,this.rows),this.clear()}get invertsDensity(){return"trail"===this.mode}get densityTrail(){return["trail","contour","dissolve"].includes(this.mode)}get hasRefraction(){return this.active||this.lensStrength>15e-5}get active(){return["dissolve","silk","vortex","magnetic","scatter"].includes(this.mode)?this.afterimage.active:"contour"===this.mode?this.contour.active:"trail"===this.mode?this.trail.active:this.pending||this.energy>15e-5}setMode(t){t!==this.mode&&(this.clear(),this.mode=t,this.refraction.mode=t,"dissolve"!==t&&"silk"!==t&&"vortex"!==t&&"magnetic"!==t&&"scatter"!==t||this.afterimage.setMode(t),this.refraction.pixels="trail"===t?this.trail.pixels:"contour"===t?this.contour.pixels:["dissolve","silk","vortex","magnetic","scatter"].includes(t)?this.afterimage.pixels:this.waterPixels,this.refraction.strength="water"===t?30*this.amount/.55:"silk"===t?28*this.amount:"vortex"===t?38*this.amount:"magnetic"===t||"scatter"===t?32*this.amount:0)}configure(t,e=.55,i=.2,a=!1){this.setMode(t),this.refraction.edgeSafe=a,this.afterimage.edgeSafe=a,this.amount=Number.isFinite(e)?Math.max(0,Math.min(1,e)):.55,this.radius=Number.isFinite(i)?Math.max(.1,Math.min(1,i)):.2,this.refraction.strength="water"===t?30*this.amount/.55:"silk"===t?28*this.amount:"vortex"===t?38*this.amount:"magnetic"===t||"scatter"===t?32*this.amount:0,this.refraction.focus[2]=this.densityTrail?this.amount:this.lensStrength*this.amount,this.refraction.focus[3]=this.radius}move(t,e,i){if("none"===this.mode||0===this.amount)return;if(!Number.isFinite(t+e))return;if(t=Math.max(0,Math.min(1,t)),e=Math.max(0,Math.min(1,e)),["dissolve","silk","vortex","magnetic","scatter"].includes(this.mode))return void this.afterimage.move(t,e,this.radius);if("contour"===this.mode)return void this.contour.move(t,e,this.radius);if("trail"===this.mode)return void this.trail.move(t,e,this.radius,i);if("water"!==this.mode)return!this.previous&&this.lensStrength<.001&&(this.lensX=t,this.lensY=e),this.previous={x:t,y:e},void(this.pending=!0);if(!this.previous)return void(this.previous={x:t,y:e});const a=this.previous;this.previous={x:t,y:e};const s=(t-a.x)*this.xScale,r=(e-a.y)*this.yScale,o=Math.hypot(s,r);if(o<1e-5)return;const n=.035+.1*this.radius,h=3*n,l=Math.min(192,Math.max(1,Math.ceil(o/(.5*n)))),c=95*Math.min(o,1)/l;for(let i=0;i<l;i++){const s=(i+.5)/l,r=a.x+(t-a.x)*s,o=a.y+(e-a.y)*s,f=Math.max(1,Math.floor((r-h/this.xScale)*(this.columns-1))),m=Math.min(this.columns-2,Math.ceil((r+h/this.xScale)*(this.columns-1))),d=Math.max(1,Math.floor((o-h/this.yScale)*(this.rows-1))),u=Math.min(this.rows-2,Math.ceil((o+h/this.yScale)*(this.rows-1)));for(let t=d;t<=u;t++)for(let e=f;e<=m;e++){const i=(e/(this.columns-1)-r)*this.xScale,a=(t/(this.rows-1)-o)*this.yScale,s=Math.exp(-(i*i+a*a)/(n*n))*c,h=t*this.columns+e;this.velocity[h]=Math.max(-12,this.velocity[h]-s)}}this.pending=!0}leave(){this.afterimage.leave(),this.contour.leave(),this.trail.leave(),this.previous=null,"water"!==this.mode&&this.lensStrength&&(this.pending=!0)}clear(){this.trail.clear(),this.contour.clear(),this.afterimage.clear(),this.heights.fill(0),this.velocity.fill(0),this.next.fill(0),this.normals.fill(0),this.refraction.focus[2]=0,this.previous=null,this.lensStrength=0,this.energy=0,this.pending=!1,this.remainder=0;for(let t=0;t<this.waterPixels.length;t+=4)this.waterPixels[t]=this.waterPixels[t+2]=128,this.waterPixels[t+1]=this.waterPixels[t+3]=0}step(t){if(!this.active||!Number.isFinite(t))return;if(["dissolve","silk","vortex","magnetic","scatter"].includes(this.mode))return void this.afterimage.step(t);if("contour"===this.mode)return void this.contour.step(t);if("trail"===this.mode)return void this.trail.step(t);if("water"!==this.mode)return void this.stepLight(Math.max(0,Math.min(.05,t)));this.remainder+=Math.max(0,Math.min(.05,t));const e=1/120,i=Math.exp(-3.8*e),a=.3*Math.min(this.columns,this.rows);for(;this.remainder+1e-8>=e;){this.remainder-=e;let t=0;for(let s=1;s<this.rows-1;s++)for(let r=1;r<this.columns-1;r++){const o=s*this.columns+r,n=this.heights[o],h=this.heights[o-1]+this.heights[o+1]+this.heights[o-this.columns]+this.heights[o+this.columns]-4*n,l=Math.min(r,s,this.columns-1-r,this.rows-1-s),c=l<5?.88+.024*l:1,f=(this.velocity[o]+(h*a*a-8*n)*e)*i*c;this.velocity[o]=f,this.next[o]=(n+f*e)*c,t=Math.max(t,Math.abs(this.next[o]),.1*Math.abs(f))}this.heights.set(this.next),this.energy=t,this.pending=!1}if(!this.active)return void this.clear();const s=.18*Math.min(this.columns,this.rows);for(let t=0;t<this.rows;t++)for(let e=0;e<this.columns;e++){const i=t*this.columns+e,a=(this.heights[t*this.columns+Math.max(0,e-1)]-this.heights[t*this.columns+Math.min(this.columns-1,e+1)])*s,r=(this.heights[Math.max(0,t-1)*this.columns+e]-this.heights[Math.min(this.rows-1,t+1)*this.columns+e])*s,o=Math.tanh(a)*(this.refraction.edgeSafe?this.edgeMask[i]:1),n=Math.tanh(r)*(this.refraction.edgeSafe?this.edgeMask[i]:1);this.normals[2*i]=o,this.normals[2*i+1]=n;const h=Math.round(32767*o+32768),l=Math.round(32767*n+32768);this.refraction.pixels[4*i]=h>>>8,this.refraction.pixels[4*i+1]=255&h,this.refraction.pixels[4*i+2]=l>>>8,this.refraction.pixels[4*i+3]=255&l}}stepLight(t){const e=this.previous,i=1-Math.exp(-30*t),a=1-Math.exp(-12*t);e&&(this.lensX+=(e.x-this.lensX)*i,this.lensY+=(e.y-this.lensY)*i),this.lensStrength+=((e?1:0)-this.lensStrength)*a,this.energy=Math.max(e?Math.abs(e.x-this.lensX)+Math.abs(e.y-this.lensY):0,Math.abs((e?1:0)-this.lensStrength)),this.pending=!1,e||this.active?this.refraction.focus=[this.lensX,this.lensY,this.lensStrength*this.amount,this.radius]:this.clear()}sample(t,e,i){if(["dissolve","silk","vortex","magnetic","scatter"].includes(this.mode))return this.afterimage.sample(t,e,i),i[0]*=this.amount,i[1]*=this.amount,void(i[2]*=this.amount);if("contour"===this.mode)return i[0]=i[1]=0,void(i[2]=this.contour.sample(t,e)*this.amount*3);if("trail"===this.mode)return i[0]=i[1]=0,void(i[2]=this.trail.sample(t,e)*this.amount*3);const a=Math.max(0,Math.min(this.columns-1.001,t*(this.columns-1))),s=Math.max(0,Math.min(this.rows-1.001,e*(this.rows-1))),r=Math.floor(a),o=Math.floor(s),n=a-r,h=s-o,l=2*(o*this.columns+r),c=l+2*this.columns;for(let t=0;t<2;t++)i[t]=.08*((this.normals[l+t]*(1-n)+this.normals[l+2+t]*n)*(1-h)+(this.normals[c+t]*(1-n)+this.normals[c+2+t]*n)*h);i[0]*=this.amount/.55,i[1]*=this.amount/.55,i[2]="light"===this.mode||"scan"===this.mode?function(t,e,i,a){const[s,r,o,n]=i.focus,h=(t-s)*Math.max(1,a)/n,l=(e-r)*Math.max(1,1/a)/n;return"light"===i.mode?Math.exp(-3*(h*h+l*l))*o:"scan"===i.mode?(1.3*Math.exp(-h*h*110)-.3*Math.exp(-h*h*12))*Math.exp(-l*l*1.8)*o:0}(t,e,this.refraction,this.xScale/this.yScale):0}};function U(t){return"videoWidth"in t?[t.videoWidth,t.videoHeight]:"naturalWidth"in t?[t.naturalWidth,t.naturalHeight]:[t.width,t.height]}var X=(t=!1)=>{const e=document.createElement("canvas"),i=e.getContext("2d",{willReadFrequently:t});if(!i)throw new Error("Canvas 2D is unavailable.");return{canvas:e,ctx:i}},B=(t,e,i)=>{t.width===e&&t.height===i||(t.width=e,t.height=i)},O={blocks:" ░▒▓█",braille:" ⠁⠃⠇⡇⣇⣧⣷⣿",lines:" -═╪╬",cross:" ·+xX#",diagonal:" /╱╳",diamond:" ·◇◈◆",mixed:" .:+/◇#@"};function Y(t,e={},i={}){const s=t.getContext("2d");if(!s)throw new Error("Canvas is already owned by another renderer.");const r=X(),o=X(!0),n=X(),h=X(),c=X(),f=X(),d=X(),u=X(),p=X(),M=X();let x,v=0,b=l(e),w=0,y="",S="",P=new Uint8ClampedArray(0),R=new Uint8ClampedArray(0),C=0,L=0,Y=0,z=null,_="",W=new D,q=0;const G=[0,0,0],j=[0,0,0,1],V=Math.max(64,Math.min(4096,Number.isFinite(i.maxDimension)?i.maxDimension:960)),H=Math.max(256,Math.min(1048576,Number.isFinite(i.maxCells)?i.maxCells:12e3));let $=H,Q=Math.max(.1,Math.min(8,i.pixelRatio??1));return{canvas:t,render:function(e,i=0,l=960,X=540,H=i*b.motion.speed){if(Number.isFinite(i)||(i=0),!Number.isFinite(l)||!Number.isFinite(X)||l<1||X<1)throw new Error("Render dimensions must be positive finite numbers.");const[J,K]=U(e);if(!J||!K)return;const Z=Math.min(1,V/Math.max(l,X)),tt=Math.max(2,Math.round(l*Z)),et=Math.max(2,Math.round(X*Z));B(t,tt,et),B(r.canvas,tt,et),B(n.canvas,tt,et),B(h.canvas,tt,et),B(c.canvas,tt,et),q!==tt/et&&(q=tt/et,W=new D(q)),W.configure(b.hover.effect,b.hover.strength,b.hover.radius,b.hover.edgeSafe),W.step(Math.max(0,Math.min(.05,i-Y))),Y=i;const it="currentTime"in e?e.getVideoPlaybackQuality?.().totalVideoFrames??e.currentTime:0,at=[w,tt,et,it].join(":"),st="dither"===b.style,rt=g(tt,et,b,$,Q),ot=rt.cell,nt=rt.rowHeight,ht=rt.columns,lt=rt.rows;if(y!==at||z!==e||C!==ht||L!==lt){z=e,y=at,S="",C=ht,L=lt,r.ctx.clearRect(0,0,tt,et),r.ctx.save();const t=m(J,K,tt,et,b.crop);r.ctx.translate(t.x+t.width/2,t.y+t.height/2),r.ctx.rotate(b.crop.rotation*Math.PI/180),r.ctx.drawImage(e,-J*t.scale/2,-K*t.scale/2,J*t.scale,K*t.scale),r.ctx.restore(),B(o.canvas,C,L),o.ctx.clearRect(0,0,C,L),o.ctx.drawImage(r.canvas,0,0,C,L),P=o.ctx.getImageData(0,0,C,L).data;const i=b.color;for(let t=0;t<P.length;t+=4){const e=.299*P[t]+.587*P[t+1]+.114*P[t+2];for(let a=0;a<3;a++){const s=e+(P[t+a]-e)*i.saturation;P[t+a]=((s*(1-i.grayscale)+e*i.grayscale)/255-.5)*i.contrast*255+127.5+255*i.brightness}}}n.ctx.clearRect(0,0,tt,et),n.ctx.globalAlpha=1,n.ctx.globalCompositeOperation="source-over";const ct=H;if(st){const t=!W.active&&"none"===b.motion.type&&"none"===b.dither.motion;if(!t||S!==at){R.length!==P.length&&(R=new Uint8ClampedArray(P.length));const e=R;e.set(P);const s=b.motion.type;if(W.active||"none"!==s)for(let t=0;t<L;t++)for(let i=0;i<C;i++){const a=i/C,r=t/L;let o=i,n=t,h=0,l=1,c=1;W.active&&(W.sample(a,r,G),o-=G[0]*C,n-=G[1]*L,h=G[2]/3),k(s,a,r,ct,j),E(j,b.motion.amount??1),o-=j[0]/960*C,n-=j[1]/960*L,l=1+j[2],c=j[3],o=Math.max(0,Math.min(C-1,o)),n=Math.max(0,Math.min(L-1,n));const f=Math.floor(o),m=Math.floor(n),d=o-f,u=n-m,g=4*(t*C+i),p=4*(m*C+f),M=4*(m*C+Math.min(C-1,f+1)),x=4*(Math.min(L-1,m+1)*C+f),v=4*(Math.min(L-1,m+1)*C+Math.min(C-1,f+1));for(let t=0;t<3;t++){const i=((P[p+t]*(1-d)+P[M+t]*d)*(1-u)+(P[x+t]*(1-d)+P[v+t]*d)*u)/255;let a=(["trail","contour"].includes(b.hover.effect)?N(i,h):"dissolve"===b.hover.effect?i*Math.max(0,1+h):i)*l;e[g+t]=255*a}e[g+3]=P[p+3]*c}!function(t,e,i,s,r=0){const{algorithm:o,amount:n,threshold:h}=s,l=("custom"===s.palette?s.colors:a[s.palette]??a.mono).map(I),c=T[o],f=c?new Float32Array(3*e*3):null,m="drift"===s.motion?r*s.speed*3:0,d=(s.direction??45)*Math.PI/180,u=Math.round(Math.cos(d)*m),g=Math.round(Math.sin(d)*m),p=(t,e)=>(t%e+e)%e,M=l.map(t=>.299*t[0]+.587*t[1]+.114*t[2]),x="shimmer"===s.motion?.15*Math.sin(r*s.speed*2):0;for(let a=0;a<i;a++)for(let r=0;r<e;r++){const d=4*(a*e+r),v=3*(a%3*e+r);if(0===t[d+3]){f&&(f[v]=f[v+1]=f[v+2]=0);continue}let b=0;o.startsWith("bayer")?b=F(r-u&15,a-g&15,Number(o.slice(5))):"noise"===o?b=A(r-u,a-g)-.5:"lines"===o?b=p(a-g,4)/3-.5:"vertical-lines"===o?b=p(r-u,4)/3-.5:"diagonal-lines"===o?b=p(r-u+a-g,4)/3-.5:"radial"===o?b=p(Math.hypot(r-e/2,a-i/2)-m,6)/6-.5:"halftone"===o&&(b=Math.hypot(p(r-u,6)-2.5,p(a-g,6)-2.5)/3.54-.5);const w=128*(b*n+x+(.5-h)),y=t[d]+w+(f?.[v]??0),S=t[d+1]+w+(f?.[v+1]??0),k=t[d+2]+w+(f?.[v+2]??0);let E=0,T=0,I=0;if(l.length){let t=1/0;const e=.299*y+.587*S+.114*k;for(let i=0;i<l.length;i++){const a=l[i],r="luminance"===s.colorSpace?(e-M[i])**2:(y-a[0])**2*.299+(S-a[1])**2*.587+(k-a[2])**2*.114;r<t&&(t=r,[E,T,I]=a)}}else E=51*Math.round(y/51),T=51*Math.round(S/51),I=51*Math.round(k/51);if(t[d]=E,t[d+1]=T,t[d+2]=I,f&&c){f[v]=f[v+1]=f[v+2]=0;for(const[t,s,o]of c){const h=r+t;if(h<0||h>=e||a+s>=i)continue;const l=3*((a+s)%3*e+h);f[l]+=(y-E)*o*n,f[l+1]+=(S-T)*o*n,f[l+2]+=(k-I)*o*n}}}}(e,C,L,b.dither,i),o.ctx.putImageData(new ImageData(e,C,L),0,0),S=t?at:""}n.ctx.imageSmoothingEnabled=!1,n.ctx.drawImage(o.canvas,0,0,tt,et)}else{const t=Array.from(O[b.style]??b.charset),e=n.ctx,i="ascii"===b.style||!!O[b.style],a=Math.max(3,Math.round(.92*nt)),s=Math.ceil(ot+4),r=Math.ceil(nt+4),o=[t.join(""),a,s,r,b.ink,b.colorMode].join(":");if(i&&o!==_&&(_=o,B(d.canvas,s*t.length,r),d.ctx.clearRect(0,0,d.canvas.width,r),d.ctx.font=`${a}px monospace`,d.ctx.textBaseline="middle",d.ctx.textAlign="center",d.ctx.fillStyle="accent"===b.colorMode?b.ink:"#ffffff",t.forEach((t,e)=>d.ctx.fillText(t,e*s+s/2,r/2))),"lego"===b.style&&v!==ot){v=ot,B(M.canvas,Math.ceil(ot),Math.ceil(nt));const t=M.ctx;t.clearRect(0,0,M.canvas.width,M.canvas.height),t.fillStyle="rgba(255,255,255,.2)",t.strokeStyle="rgba(0,0,0,.25)",t.lineWidth=Math.max(.5,.6*Q),t.beginPath(),t.arc(ot/2,nt/2,.28*ot,0,2*Math.PI),t.fill(),t.stroke()}e.font=`${a}px monospace`,e.textBaseline="middle",e.textAlign="center";for(let a=0;a<L;a++)for(let o=0;o<C;o++){let n=o,h=a,l=0;W.active&&(W.sample(o/C,a/L,G),n=Math.max(0,Math.min(C-1,o-G[0]*C)),h=Math.max(0,Math.min(L-1,a-G[1]*L)),l=G[2]/3);const c=4*(Math.floor(h)*C+Math.floor(n));if(!P[c+3])continue;const f=P[c],m=P[c+1],u=P[c+2],g=(.299*f+.587*m+.114*u)/255;let p=g;["trail","contour"].includes(b.hover.effect)&&l?p=N(p,l):"dissolve"===b.hover.effect&&(p*=Math.max(0,1+l));const x=b.motion.type;let v=o*ot,w=a*nt,y=1;k(x,o/C,a/L,ct,j),E(j,b.motion.amount??1),v+=j[0]*tt/960,w+=j[1]*et/960,p=Math.max(0,Math.min(1,p+j[2])),y=j[3],i||"accent"!==b.colorMode||"cmyk"===b.style||(y*=p),e.globalAlpha=y;const S=255*(p-g);let F="source"===b.colorMode?`rgb(${f+S},${m+S},${u+S})`:"gray"===b.colorMode?`rgb(${Math.round(255*p)},${Math.round(255*p)},${Math.round(255*p)})`:b.ink;if(e.fillStyle=F,i){const i=Math.max(0,Math.min(t.length-1,Math.round(p*(t.length-1))));"accent"===b.colorMode?e.drawImage(d.canvas,i*s,0,s,r,"none"===x||"caustics"===x?Math.round(v+(ot-s)/2):v+(ot-s)/2,"none"===x||"caustics"===x?Math.round(w+(nt-r)/2):w+(nt-r)/2,s,r):e.fillText(t[i],v+ot/2,w+nt/2)}else if("dots"===b.style)e.beginPath(),e.arc(v+ot/2,w+nt/2,.48*ot*Math.sqrt(p),0,2*Math.PI),e.fill();else if("led"===b.style)e.beginPath(),e.arc(v+ot/2,w+nt/2,.39*ot,0,2*Math.PI),e.fill(),e.globalAlpha=.35*y,e.fillStyle="#ffffff",e.beginPath(),e.arc(v+.43*ot,w+.4*nt,.11*ot,0,2*Math.PI),e.fill();else if("hex"===b.style){const t=v+ot/2,i=w+nt/2;e.beginPath();for(let a=0;a<6;a++){const s=Math.PI/3*a,r=t+Math.cos(s)*ot*.49,o=i+Math.sin(s)*nt*.49;0===a?e.moveTo(r,o):e.lineTo(r,o)}e.closePath(),e.fill()}else if("cmyk"===b.style){e.fillStyle="#ffffff",e.fillRect(v,w,ot,nt);const t=1-Math.max(f,m,u)/255,i=Math.max(.001,1-t),a=[["#00ffff",(1-f/255-t)/i,.36,.36],["#ff00ff",(1-m/255-t)/i,.64,.36],["#ffff00",(1-u/255-t)/i,.5,.66],["#000000",t,.5,.5]];e.globalCompositeOperation="multiply";for(const[t,i,s,r]of a)e.fillStyle=t,e.beginPath(),e.arc(v+ot*s,w+nt*r,.48*ot*Math.sqrt(Math.max(0,i)),0,2*Math.PI),e.fill();e.globalCompositeOperation="source-over"}else if("voxel"===b.style){const t=v+ot/2,i=w+nt/2;e.beginPath(),e.moveTo(t,w),e.lineTo(v+ot,w+.25*nt),e.lineTo(t,i),e.lineTo(v,w+.25*nt),e.closePath(),e.fill(),e.globalAlpha=.72*y,e.beginPath(),e.moveTo(v,w+.25*nt),e.lineTo(t,i),e.lineTo(t,w+nt),e.lineTo(v,w+.75*nt),e.closePath(),e.fill(),e.globalAlpha=.42*y,e.beginPath(),e.moveTo(t,i),e.lineTo(v+ot,w+.25*nt),e.lineTo(v+ot,w+.75*nt),e.lineTo(t,w+nt),e.closePath(),e.fill()}else{const t="pixel"===b.style?0:Math.max(.5,.06*ot);e.fillRect(v,w,ot-t,nt-t),"lego"===b.style&&e.drawImage(M.canvas,v,w),"disco"===b.style&&(e.fillStyle=`rgba(255,255,255,${.1+.25*A(o,a)})`,e.fillRect(v,w,ot-t,.35*nt),e.fillStyle="rgba(0,0,0,.25)",e.fillRect(v,w+.65*nt,ot-t,.35*nt-t))}}}n.ctx.globalAlpha=1,(b.color.amount||b.lights.length)&&(B(u.canvas,tt,et),u.ctx.clearRect(0,0,tt,et),u.ctx.drawImage(n.canvas,0,0)),b.color.amount&&(n.ctx.save(),n.ctx.globalCompositeOperation=b.color.blend,n.ctx.globalAlpha=b.color.amount,n.ctx.fillStyle=b.color.tint,n.ctx.fillRect(0,0,tt,et),n.ctx.restore());for(const t of b.lights){const e=t.radius*Math.max(tt,et),i=n.ctx.createRadialGradient(t.x*tt,t.y*et,0,t.x*tt,t.y*et,e);i.addColorStop(0,t.color),i.addColorStop(1,"transparent"),n.ctx.save(),n.ctx.globalCompositeOperation="screen",n.ctx.globalAlpha=t.intensity,n.ctx.fillStyle=i,n.ctx.fillRect(0,0,tt,et),n.ctx.restore()}if((b.color.amount||b.lights.length)&&(n.ctx.globalCompositeOperation="destination-in",n.ctx.drawImage(u.canvas,0,0),n.ctx.globalCompositeOperation="source-over"),b.mask.enabled&&b.mask.shapes.length){const t=c.ctx;t.clearRect(0,0,tt,et),t.fillStyle="#fff",t.strokeStyle="#fff",t.lineCap="round",t.lineJoin="round";for(const e of b.mask.shapes){if(t.beginPath(),"ellipse"===e.kind)t.ellipse((e.x+e.width/2)*tt,(e.y+e.height/2)*et,e.width*tt/2,e.height*et/2,0,0,2*Math.PI);else{if("rectangle"!==e.kind){if(t.lineWidth=(e.size??.05)*tt,1===e.points?.length){t.arc(e.points[0][0]*tt,e.points[0][1]*et,t.lineWidth/2,0,2*Math.PI),t.fill();continue}e.points?.forEach(([e,i],a)=>a?t.lineTo(e*tt,i*et):t.moveTo(e*tt,i*et)),t.stroke();continue}t.rect(e.x*tt,e.y*et,e.width*tt,e.height*et)}t.fill()}n.ctx.globalCompositeOperation=b.mask.invert?"destination-out":"destination-in",n.ctx.drawImage(c.canvas,0,0),n.ctx.globalCompositeOperation="source-over"}const ft=h.ctx;ft.clearRect(0,0,tt,et),ft.globalAlpha=b.backdrop.opacity;const mt=b.backdrop;if("solid"===mt.mode&&(ft.fillStyle=mt.color,ft.fillRect(0,0,tt,et)),"gradient"===mt.mode){const t=ft.createLinearGradient(0,0,tt,et);t.addColorStop(0,mt.color),t.addColorStop(1,mt.color2),ft.fillStyle=t,ft.fillRect(0,0,tt,et)}if("source"===mt.mode&&ft.drawImage(r.canvas,0,0),"blurred"===mt.mode){const t=Math.max(1,mt.blur);B(f.canvas,Math.max(2,Math.round(tt/t)),Math.max(2,Math.round(et/t))),f.ctx.drawImage(r.canvas,0,0,f.canvas.width,f.canvas.height),ft.imageSmoothingEnabled=!0,ft.drawImage(f.canvas,0,0,tt,et)}ft.globalAlpha=1,b.effects.characterBloom>0&&(B(p.canvas,Math.max(2,Math.round(tt/3)),Math.max(2,Math.round(et/3))),p.ctx.clearRect(0,0,p.canvas.width,p.canvas.height),p.ctx.drawImage(n.canvas,0,0,p.canvas.width,p.canvas.height),ft.save(),ft.globalAlpha=.8*b.effects.characterBloom,ft.globalCompositeOperation="screen",ft.filter=`blur(${1+4*b.effects.characterBloom}px)`,ft.drawImage(p.canvas,0,0,tt,et),ft.restore()),ft.drawImage(n.canvas,0,0);const dt=Object.entries(b.effects).some(([t,e])=>!["angle","focus","blurType","characterBloom"].includes(t)&&"number"==typeof e&&e>0);s.clearRect(0,0,tt,et),dt?(void 0===x&&(x=function(){const t=document.createElement("canvas"),e=t.getContext("webgl",{alpha:!0,premultipliedAlpha:!1,antialias:!1,preserveDrawingBuffer:!0});if(!e)return null;const i=[],a=(t,a)=>{const s=e.createShader(t);if(i.push(s),e.shaderSource(s,a),e.compileShader(s),!e.getShaderParameter(s,e.COMPILE_STATUS))throw new Error(e.getShaderInfoLog(s)||"Finish shader failed");return s},s=e.createProgram();if(e.attachShader(s,a(e.VERTEX_SHADER,"attribute vec2 p;varying vec2 uv;void main(){uv=(p+1.)*.5;gl_Position=vec4(p,0.,1.);}")),e.attachShader(s,a(e.FRAGMENT_SHADER,"precision mediump float;varying vec2 uv;uniform sampler2D src;uniform vec2 size;uniform float t,bloom,grain,dust,scanlines,crt,prism,vignette,glitch,pixelate,blur,blurMode,angle,focus,halftone,rgbSplit,sharpen;\n float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);}\n vec4 sampleAt(vec2 p){if(min(min(p.x,p.y),min(1.-p.x,1.-p.y))<0.)return vec4(0.);return texture2D(src,vec2(p.x,1.-p.y));}\n void main(){vec2 q=uv,c=q-.5;q=c*(1.+dot(c,c)*crt*.25)+.5;\n if(glitch>0.)q.x+=(hash(vec2(floor(q.y*35.),floor(t*5.)))-.5)*.07*glitch*step(.82,hash(vec2(floor(q.y*35.),floor(t*5.)+3.)));\n if(pixelate>0.){vec2 grid=size/(1.+pixelate*20.);q=(floor(q*grid)+.5)/grid;}\n vec4 base=sampleAt(q);float edge=smoothstep(.12,.65,length(c));\n vec2 shift=vec2((prism*3.*edge+rgbSplit*8.)/size.x,prism*edge/size.y);\n if(prism>0.||rgbSplit>0.)base.rgb=vec3(sampleAt(q+shift).r,base.g,sampleAt(q-shift).b);\n vec2 dir=vec2(cos(angle),sin(angle))/size;float amount=blur;\n if(blurMode>1.5&&blurMode<2.5){dir=normalize(c+vec2(.0001))/size;amount*=length(c)*2.;}\n if(blurMode>2.5)amount*=smoothstep(.05,.5,abs(q.y-focus));\n vec4 blurred=base;\n if(amount>0.){blurred=base*.2;for(int i=1;i<=4;i++){float f=float(i)*amount*.35;vec2 off=dir*f;if(blurMode<.5)off=vec2(cos(float(i)*1.57),sin(float(i)*1.57))*amount/size;blurred+=sampleAt(q+off)*.1+sampleAt(q-off)*.1;}}\n vec3 light=vec3(0.);if(bloom>0.)for(int i=0;i<4;i++){float a=float(i)*1.5708;vec3 s=sampleAt(q+vec2(cos(a),sin(a))*6./size).rgb;light+=max(vec3(0.),s-.35)*.25;}\n vec3 col=blurred.rgb+light*bloom;\n if(sharpen>0.){vec2 px=1./size;vec3 near=sampleAt(q+vec2(px.x,0.)).rgb+sampleAt(q-vec2(px.x,0.)).rgb+sampleAt(q+vec2(0.,px.y)).rgb+sampleAt(q-vec2(0.,px.y)).rgb;col+=(base.rgb*4.-near)*sharpen*.5;}\ncol*=1.-scanlines*.4*(.5+.5*cos(q.y*size.y*3.14159));\n col*=1.-vignette*smoothstep(.15,.72,length(c));\n col+=(hash(floor(q*size)+floor(t*12.))-.5)*grain*.2;\n if(dust>0.)col+=step(1.-dust*.002,hash(floor(q*size*.25)+floor(t*2.)))*.4;\n if(halftone>0.)col*=mix(1.,smoothstep(.1,.65,length(fract(q*size/6.)-.5)),halftone);\n gl_FragColor=vec4(clamp(col,0.,1.),blurred.a);}")),e.linkProgram(s),!e.getProgramParameter(s,e.LINK_STATUS))throw new Error("Finish link failed");e.useProgram(s);const r=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,r),e.bufferData(e.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,-1,1,1,1]),e.STATIC_DRAW);const o=e.getAttribLocation(s,"p");e.enableVertexAttribArray(o),e.vertexAttribPointer(o,2,e.FLOAT,!1,0,0);const n=e.createTexture();e.bindTexture(e.TEXTURE_2D,n),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE);const h=["t","bloom","grain","dust","scanlines","crt","prism","rgbSplit","sharpen","vignette","glitch","pixelate","blur","blurMode","angle","focus","halftone"],l=Object.fromEntries(h.map(t=>[t,e.getUniformLocation(s,t)])),c=e.getUniformLocation(s,"size");return{canvas:t,render(i,a,r,o=1){t.width===i.width&&t.height===i.height||(t.width=i.width,t.height=i.height,e.viewport(0,0,t.width,t.height)),e.useProgram(s),e.bindTexture(e.TEXTURE_2D,n),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,i),e.uniform2f(c,t.width/o,t.height/o);for(const t of h)e.uniform1f(l[t],"t"===t?r:"blurMode"===t?["gaussian","directional","radial","progressive"].indexOf(a.blurType):"angle"===t?a.angle*Math.PI/180:a[t]??0);return e.drawArrays(e.TRIANGLE_STRIP,0,4),t},destroy(){e.deleteTexture(n),e.deleteBuffer(r),e.deleteProgram(s),i.forEach(t=>e.deleteShader(t)),t.width=t.height=1,e.getExtension("WEBGL_lose_context")?.loseContext()}}}()),x?s.drawImage(x.render(h.canvas,b.effects,i,Q),0,0):s.drawImage(h.canvas,0,0),t.dataset.studioFinish=x?"gpu":"unavailable"):(s.drawImage(h.canvas,0,0),t.dataset.studioFinish="none")},setPixelRatio(t){Q=Math.max(.1,Math.min(8,Number.isFinite(t)?t:1))},get pixelRatio(){return Q},setBudget(t){$=Math.max(1500,Math.min(H,Math.round(t)))},get maxCells(){return $},configure(t){b=l(t),w++},pointer:(t,e,i)=>{W.configure(b.hover.effect,b.hover.strength,b.hover.radius,b.hover.edgeSafe),W.move(t,e,i)},leave(){W.leave()},get active(){return W.active},get settings(){return l(b)},get capabilities(){return{gpuFinish:null!==x}},invalidate(){y=""},destroy(){x?.destroy();for(const t of[r,o,n,h,c,f,d,u,p,M])t.canvas.width=t.canvas.height=1;z=null,P=new Uint8ClampedArray(0)}}}function z(t,e,i){return new Promise((a,s)=>{const r=()=>{l(),a()},o=()=>{l(),s(new Error("Unable to load this media. Check its format and cross-origin permissions."))},n=()=>{l(),s(new DOMException("Cancelled","AbortError"))},h=setTimeout(o,2e4),l=()=>{clearTimeout(h),t.removeEventListener(e,r),t.removeEventListener("error",o),i?.removeEventListener("abort",n)};t.addEventListener(e,r,{once:!0}),t.addEventListener("error",o,{once:!0}),i?.addEventListener("abort",n,{once:!0}),i?.aborted&&n()})}async function _(t,e){if("string"==typeof t&&t.startsWith("blob:")){const i=await fetch(t,{signal:e}),a=await i.blob();return _(new File([a],"Imported media",{type:a.type}),e)}const i="string"!=typeof t,a=i?t.name:t;if(i?"image/gif"===t.type:/\.gif(?:[?#]|$)/i.test(a)){const a=await import("gifuct-js"),{parseGIF:s,decompressFrames:r}="function"==typeof a.parseGIF?a:a.default,o=i?await t.arrayBuffer():await fetch(t,{signal:e}).then(t=>{if(!t.ok)throw new Error("GIF download failed.");return t.arrayBuffer()});if(e?.aborted)throw new DOMException("Cancelled","AbortError");const n=s(o),h=n.lsd.width,l=n.lsd.height;if(h*l>4e6)throw new Error("GIF is too large. Use a smaller GIF or an MP4.");const c=n.frames.filter(t=>"image"in t).length;if(!c||c*h*l*4>128e6)throw new Error("GIF exceeds the decoded memory budget. Use MP4 for long animations.");const f=r(n,!0);if(f.length*h*l*4>128e6)throw new Error("GIF exceeds the 128 MB decoded budget. Use MP4 for long animations.");const m=document.createElement("canvas");m.width=h,m.height=l;const d=m.getContext("2d"),u=document.createElement("canvas"),g=u.getContext("2d"),p=f.reduce((t,e)=>t+Math.max(20,e.delay),0)/1e3;let M=-1,x=null;const v=t=>{const e=(t%p+p)%p*1e3;let i=0,a=0;for(;a<f.length-1&&(i+=Math.max(20,f[a].delay),!(e<i));a++);a<M&&(d.clearRect(0,0,h,l),M=-1,x=null);for(let t=M+1;t<=a;t++){const e=f[t-1];2===e?.disposalType&&d.clearRect(e.dims.left,e.dims.top,e.dims.width,e.dims.height),3===e?.disposalType&&x&&d.putImageData(x,0,0);const i=f[t];x=3===i.disposalType?d.getImageData(0,0,h,l):null,u.width=i.dims.width,u.height=i.dims.height,g.putImageData(new ImageData(new Uint8ClampedArray(i.patch),u.width,u.height),0,0),d.drawImage(u,i.dims.left,i.dims.top)}return M=a,m};return v(0),{source:m,width:h,height:l,duration:p,animated:!0,seek:async()=>{},frame:v,destroy(){m.width=u.width=1,f.length=0,x=null}}}const s=i?t.type.startsWith("video/"):/\.(mp4|webm|mov)(?:[?#]|$)/i.test(a),r=i?URL.createObjectURL(t):t,o=s?document.createElement("video"):new Image;o.crossOrigin="anonymous",o instanceof HTMLVideoElement&&(o.muted=!0,o.playsInline=!0,o.preload="auto");const n=()=>{o instanceof HTMLVideoElement?(o.pause(),o.removeAttribute("src"),o.load()):o.src="",i&&URL.revokeObjectURL(r)};try{const t=z(o,s?"loadeddata":"load",e);o.src=r,await t;const i=o instanceof HTMLVideoElement?o.videoWidth:o.naturalWidth,a=o instanceof HTMLVideoElement?o.videoHeight:o.naturalHeight;return{source:o,width:i,height:a,duration:o instanceof HTMLVideoElement?o.duration:0,animated:s,async seek(t,e){if(!(o instanceof HTMLVideoElement))return;if(!Number.isFinite(o.duration)||o.duration<=0)throw new Error("Video duration is unavailable.");const i=Math.max(0,Math.min(o.duration-.001,t%o.duration));if(Math.abs(o.currentTime-i)<.001&&o.readyState>=2)return;const a=z(o,"seeked",e);o.currentTime=i,await a},frame:()=>o,destroy:n}}catch(t){throw n(),t}}var W=t=>{if(t?.aborted)throw new DOMException("Export cancelled","AbortError")};async function q(t,e,i){const{format:a,signal:s}=i,r=Math.round(i.width),o=Math.round(i.height);if(!Number.isFinite(r)||!Number.isFinite(o)||r<2||o<2||r>4096||o>4096||r*o>16777216)throw new Error("Choose export dimensions between 2 and 4096 pixels.");if(!["png","jpeg","mp4","webm","gif"].includes(a))throw new Error("Unknown export format.");if(void 0!==i.fps&&!Number.isFinite(i.fps))throw new Error("Frames per second must be finite.");const n=Math.max(1,Math.min(60,Math.round(i.fps??24))),h=i.duration??5;if(!Number.isFinite(h)||h<=0||h>60)throw new Error("Choose a duration from 0 to 60 seconds.");const c="png"===a||"jpeg"===a,f=i.time??0;if(!Number.isFinite(f)||f<0)throw new Error("Image time must be a finite non-negative number.");if(!c&&r*o>8294400)throw new Error("Video exports support up to 3840 × 2160 pixels.");if("gif"===a&&(r*o>921600||h*n>600))throw new Error("GIF export supports up to 1280 × 720 and 600 frames. Use MP4 for larger exports.");if(void 0!==i.referenceWidth&&(!Number.isFinite(i.referenceWidth)||i.referenceWidth<1))throw new Error("Reference width must be a positive number.");if("gif"===a&&n>30)throw new Error("GIF exports support up to 30 fps. Choose MP4 or WebM for higher frame rates.");const m=document.createElement("canvas"),d=Y(m,l(e),{maxDimension:4096,maxCells:i.maxCells??12e3,pixelRatio:r/(i.referenceWidth??Math.min(r,960))});let u;try{if(W(s),i.onProgress?.(0),c){if(d.render(await t.frame(f,s),f,r,o),"unavailable"===m.dataset.studioFinish)throw new Error("Optical effects need WebGL. Disable these effects or export in a supported browser.");W(s);const e=await new Promise((t,e)=>m.toBlob(i=>i?t(i):e(new Error("Image export failed.")),"png"===a?"image/png":"image/jpeg",i.quality??.92));return i.onProgress?.(1),e}const e=Math.ceil(h*n);if("gif"===a){const a=await import("gifenc"),{GIFEncoder:l,quantize:c,applyPalette:f}="function"==typeof a.GIFEncoder?a:a.default,u=l(),g=m.getContext("2d");for(let a=0;a<e;a++){W(s);const l=a/n;if(d.invalidate(),d.render(await t.frame(l,s),l,r,o),"unavailable"===m.dataset.studioFinish)throw new Error("Optical effects need WebGL. Disable these effects or export in a supported browser.");const p=g.getImageData(0,0,r,o).data,M=c(p,256),x=f(p,M);u.writeFrame(x,r,o,{palette:M,delay:10*(Math.round(100*Math.min((a+1)/n,h))-Math.round(100*a/n)),repeat:0}),i.onProgress?.((a+1)/e*.98),await new Promise(t=>setTimeout(t,0))}return u.finish(),i.onProgress?.(1),new Blob([new Uint8Array(u.bytes())],{type:"image/gif"})}const{Output:l,Mp4OutputFormat:g,WebMOutputFormat:p,BufferTarget:M,CanvasSource:x,canEncodeVideo:v}=await import("mediabunny"),b="mp4"===a?"avc":"vp9";if(!await v(b,{width:r,height:o}))throw new Error(`${a.toUpperCase()} encoding is unavailable in this browser. Try another format or a current browser with WebCodecs.`);const w=new l({format:"mp4"===a?new g({fastStart:"in-memory"}):new p,target:new M});m.width=r,m.height=o,u=()=>w.cancel();const y=new x(m,{codec:b,bitrate:Math.max(5e5,Math.round(r*o*n*.15))});w.addVideoTrack(y,{frameRate:n}),m.width=r,m.height=o,await w.start();for(let a=0;a<e;a++){W(s);const l=a/n;if(d.invalidate(),d.render(await t.frame(l,s),l,r,o),"unavailable"===m.dataset.studioFinish)throw new Error("Optical effects need WebGL. Disable these effects or export in a supported browser.");await y.add(l,Math.min(1/n,h-l)),i.onProgress?.((a+1)/e*.98),a%4==0&&await new Promise(t=>setTimeout(t,0))}return y.close(),W(s),await w.finalize(),u=void 0,i.onProgress?.(1),new Blob([w.target.buffer],{type:"mp4"===a?"video/mp4":"video/webm"})}catch(t){throw await(u?.().catch(()=>{})),t}finally{d.destroy(),m.width=m.height=1}}async function G(t,e,i={}){const a=await _(e,i.signal);try{return j(t,a,i)}catch(t){throw a.destroy(),t}}function j(t,e,i={}){let a=l(i.settings),s=i.width??e.width,r=i.height??e.height;const o=Y(t,a,i),n=new S;let h=0,c=!1,f=!0,m=!1,g=!0,p=0,M=0,x=0,v=-1,b=!1!==i.adaptive,w=0,y=0,k=0;const E=matchMedia("(prefers-reduced-motion: reduce)"),A=e.source instanceof HTMLVideoElement?e.source:null,F=()=>{c||h||!g||document.hidden||(h=requestAnimationFrame(P))},T=()=>!m&&!E.matches&&g&&!document.hidden,I=()=>{A&&(A.loop=!0,T()?A.play().catch(()=>{m=!0,f=!0,F()}):A.pause()),M=0,f=!0,F()};function P(t){if(h=0,c||!g||document.hidden)return;const l=T();l&&(p+=M?Math.min(.1,(t-M)/1e3):0),M=t;const u=l&&(e.animated||"none"!==a.motion.type||"none"!==a.dither.motion||a.effects.grain>0||a.effects.dust>0||a.effects.glitch>0),S=A?.getVideoPlaybackQuality?.().totalVideoFrames??-1,E="none"!==a.motion.type||"none"!==a.dither.motion||a.effects.grain>0||a.effects.dust>0||a.effects.glitch>0,I=!A||S<0||S!==v;if(f||o.active||u&&(I||E)&&t-x>=1e3/Math.max(1,Math.min(60,i.fps??60))-.5){const h=performance.now();try{e.animated&&!A&&o.invalidate();const[t,l]=d(s,r,a);o.render(e.frame(A?.currentTime??p),p,t,l,n.update(p,a.motion.type,a.motion.speed));const c=performance.now()-h;i.onFrame?.(A?.currentTime??p,c),y=y?.9*y+.1*c:c,++w>20&&b&&(u||o.active)&&(k=y>13?k+1:0,k>=12&&o.maxCells>3e3&&(o.setBudget(Math.max(3e3,.8*o.maxCells)),i.onQualityChange?.(o.maxCells),k=0,y=0))}catch(t){m=!0,i.onError?.(t instanceof Error?t:new Error(String(t)))}f=!1,x=t,v=S}l&&(u||o.active)&&F()}const R=e=>{if(!T())return;const i=t.getBoundingClientRect();o.pointer((e.clientX-i.left)/i.width,(e.clientY-i.top)/i.height,e.timeStamp),F()},C=()=>{o.leave(),F()},L=new IntersectionObserver(([t])=>{g=t.isIntersecting,I()});L.observe(t),t.addEventListener("pointermove",R),t.addEventListener("pointerleave",C),t.addEventListener("pointercancel",C),document.addEventListener("visibilitychange",I),E.addEventListener("change",I);const N=()=>{c||(c=!0,cancelAnimationFrame(h),L.disconnect(),t.removeEventListener("pointermove",R),t.removeEventListener("pointerleave",C),t.removeEventListener("pointercancel",C),document.removeEventListener("visibilitychange",I),E.removeEventListener("change",I),i.signal?.removeEventListener("abort",N),o.destroy(),e.destroy())};if(i.signal?.addEventListener("abort",N,{once:!0}),i.signal?.aborted)throw N(),new DOMException("Cancelled","AbortError");return I(),{canvas:t,media:e,update(t){a=u(a,t),o.configure(a),f=!0,F()},resize(t,e,i){void 0!==i&&o.setPixelRatio(i),s=Math.max(2,t),r=Math.max(2,e),f=!0,F()},pause(t=!0){m=t,I()},async seek(t){p=Math.max(0,t),await e.seek(p),o.invalidate(),f=!0,F()},redraw(){o.invalidate(),f=!0,F()},get time(){return A?.currentTime??p},get paused(){return m||E.matches},setAdaptive(t){b=t,w=k=y=0},setBudget(t){o.setBudget(t),i.onQualityChange?.(o.maxCells),f=!0,F()},get pixelRatio(){return o.pixelRatio},get maxCells(){return o.maxCells},get capabilities(){return o.capabilities},destroy:N}}var V={Standard:()=>import("figlet/fonts/Standard"),Slant:()=>import("figlet/fonts/Slant"),Small:()=>import("figlet/fonts/Small"),Big:()=>import("figlet/fonts/Big"),Banner:()=>import("figlet/fonts/Banner"),Block:()=>import("figlet/fonts/Block"),Bubble:()=>import("figlet/fonts/Bubble"),Digital:()=>import("figlet/fonts/Digital"),Doom:()=>import("figlet/fonts/Doom"),Lean:()=>import("figlet/fonts/Lean"),Mini:()=>import("figlet/fonts/Mini"),Script:()=>import("figlet/fonts/Script"),Shadow:()=>import("figlet/fonts/Shadow"),Speed:()=>import("figlet/fonts/Speed"),Starwars:()=>import("figlet/fonts/Star Wars"),Stop:()=>import("figlet/fonts/Stop"),Straight:()=>import("figlet/fonts/Straight"),Thin:()=>import("figlet/fonts/Thin"),ThreeD:()=>import("figlet/fonts/3-D"),Univers:()=>import("figlet/fonts/Univers"),Wavy:()=>import("figlet/fonts/Wavy")},H=Object.keys(V);async function $(t,e="Standard",i="#ffffff"){if(!Object.prototype.hasOwnProperty.call(V,e))throw new Error("Unknown text font.");const{default:a}=await import("figlet/browser"),s=await V[e]();a.parseFont(e,s.default),a.defaults({fetchFontIfMissing:!1});const r=a.textSync(t.slice(0,120),{font:e}),o=r.split("\n"),n=Math.max(1,...o.map(t=>t.length)),h=Math.max(1,o.length),l=Math.min(1,2048/(9*n)),c=document.createElement("canvas");c.width=Math.ceil(9*n*l+32),c.height=Math.ceil(15*h*l+32);const f=c.getContext("2d");return f.fillStyle="#080808",f.fillRect(0,0,c.width,c.height),f.fillStyle=i,f.font=15*l+"px monospace",f.textBaseline="top",o.forEach((t,e)=>f.fillText(t,16,16+15*e*l)),{canvas:c,ascii:r}}var Q={standard:{label:"Classic ASCII",chars:" .:-=+*#%@"},asciify:{label:"Asciify",chars:" .:-=+ASCIIFY#@"},minimal:{label:"Minimal",chars:" .:+"},detailed:{label:"Detailed",chars:" .,:;i1tfLCG08@"},letters:{label:"Letters",chars:" .ilLCFTYASMW"},technical:{label:"Technical",chars:" .:;>_/[{}]=+*#@$"},blocks:{label:"Tonal blocks",chars:" ░▒▓█"},braille:{label:"Braille",chars:" ⠁⠃⠇⡇⣇⣧⣷⣿"}},J=Q;export{i as BLEND_MODES,Q as CHARACTER_SETS,s as DEFAULT_STUDIO_SETTINGS,e as DITHER_ALGORITHMS,J as STUDIO_CHARACTER_SETS,p as STUDIO_LOOKS,v as STUDIO_MOTIONS,a as STUDIO_PALETTES,t as STUDIO_STYLES,H as STUDIO_TEXT_FONTS,Y as createStudioRenderer,$ as createStudioText,q as exportStudio,_ as loadStudioMedia,G as mountStudio,j as mountStudioMedia,l as normalizeStudioSettings,f as parseStudioSettings,x as restyleStudio,c as serializeStudioSettings,m as studioCrop,d as studioDimensions,g as studioGrid,M as studioLook,U as studioSourceSize,u as updateStudioSettings};//# sourceMappingURL=studio.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
type ColorMode = 'grayscale' | 'fullcolor' | 'matrix' | 'accent';
|
|
2
2
|
type RenderMode = 'ascii' | 'dots';
|
|
3
|
-
type AnimationStyle = 'none' | 'caustics' | 'current' | 'reform';
|
|
3
|
+
type AnimationStyle = 'none' | 'caustics' | 'current' | 'reform' | 'sheen' | 'tidal' | 'grain';
|
|
4
4
|
/** Core media draws ASCII/dots; use StudioStyle for the 15 render styles. */
|
|
5
5
|
type ArtStyle = 'classic';
|
|
6
6
|
type HoverEffect = 'spotlight' | 'magnify' | 'repel' | 'glow' | 'colorShift' | 'attract' | 'shatter' | 'trail' | 'glitchText';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
type ColorMode = 'grayscale' | 'fullcolor' | 'matrix' | 'accent';
|
|
2
2
|
type RenderMode = 'ascii' | 'dots';
|
|
3
|
-
type AnimationStyle = 'none' | 'caustics' | 'current' | 'reform';
|
|
3
|
+
type AnimationStyle = 'none' | 'caustics' | 'current' | 'reform' | 'sheen' | 'tidal' | 'grain';
|
|
4
4
|
/** Core media draws ASCII/dots; use StudioStyle for the 15 render styles. */
|
|
5
5
|
type ArtStyle = 'classic';
|
|
6
6
|
type HoverEffect = 'spotlight' | 'magnify' | 'repel' | 'glow' | 'colorShift' | 'attract' | 'shatter' | 'trail' | 'glitchText';
|
package/package.json
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
name: asciify-engine
|
|
3
3
|
description: Build and tune browser ASCII images, video, GIFs, text, and interactive heroes with asciify-engine. Use for media conversion, character and color choices, hover integration, layered HTML typography, scroll-synced video, and rendering performance in apps using this package.
|
|
4
4
|
metadata:
|
|
5
|
-
tested-engine: "4.
|
|
5
|
+
tested-engine: "4.3.0"
|
|
6
6
|
updated: "2026-10-07"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Asciify Engine
|
|
10
10
|
|
|
11
|
-
Use the published `asciify-engine` npm package for browser canvas rendering. Tested against **4.
|
|
11
|
+
Use the published `asciify-engine` npm package for browser canvas rendering. Tested against **4.3.0**. Check the application's installed version and its public types before using newer options; a local checkout can contain unpublished changes.
|
|
12
12
|
|
|
13
13
|
- Agent entry: https://asciify.org/skill (redirects to this Markdown document).
|
|
14
14
|
- Playground: https://asciify.org/editor
|
|
@@ -157,3 +157,21 @@ studio.setBudget(65536);
|
|
|
157
157
|
```
|
|
158
158
|
|
|
159
159
|
When exporting, pass the same `maxCells` and logical `referenceWidth` as the preview to retain cell density. Increasing output resolution alone should not invent a different composition. Older projects normalize new fields to neutral defaults.
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
## Additional local interactions (4.3)
|
|
163
|
+
|
|
164
|
+
Studio and `asciify-engine/hover` support `magnetic` (gathers toward a stroke)
|
|
165
|
+
and `scatter` (radial, spatially varied scatter that relaxes). Both retain a
|
|
166
|
+
bounded field after cursor exit; radius and strength control the response.
|
|
167
|
+
Use `hover.effect` in Studio and `effect` in mountHover. Defaults remain unchanged.
|
|
168
|
+
|
|
169
|
+
Still-image motion now has six active choices: `caustics`, `current`, `reform`,
|
|
170
|
+
`sheen`, `tidal`, and `grain`, plus `none`. Sheen and Living Grain change tone
|
|
171
|
+
without displacement; Tidal Rings moves the image with protected edges.
|
|
172
|
+
Set Studio `motion: { type: 'sheen', speed: 0.7, amount: 0.6 }`.
|
|
173
|
+
Core uses `animationStyle`; mountHover uses `motion` and `motionSpeed`.
|
|
174
|
+
Base cycles last 12 seconds; speed scales duration. Studio amount scales strength.
|
|
175
|
+
Keep automatic motion off for source video unless requested. Respect reduced motion.
|
|
176
|
+
These are local effects, not AI-generated frames. Frame rate depends on device,
|
|
177
|
+
resolution and other effects; no universal FPS guarantee.
|