From c1d1b8d5f8c2e3eb5b49d4aca1dac03e7312bc92 Mon Sep 17 00:00:00 2001 From: reindernijhoff Date: Wed, 15 May 2024 07:21:45 +0000 Subject: [PATCH] deploy: 994db81b7fe87ccbc51b32807c4cfdd9d8b49b79 --- assets/index-4ZkqVyUE.js | 30 ------------------------------ assets/index-B9REFjg6.js | 30 ++++++++++++++++++++++++++++++ index.html | 2 +- 3 files changed, 31 insertions(+), 31 deletions(-) delete mode 100644 assets/index-4ZkqVyUE.js create mode 100644 assets/index-B9REFjg6.js diff --git a/assets/index-4ZkqVyUE.js b/assets/index-4ZkqVyUE.js deleted file mode 100644 index 97e1b57..0000000 --- a/assets/index-4ZkqVyUE.js +++ /dev/null @@ -1,30 +0,0 @@ -var v=Object.defineProperty;var b=(n,e,t)=>e in n?v(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var o=(n,e,t)=>(b(n,typeof e!="symbol"?e+"":e,t),t);(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))a(i);new MutationObserver(i=>{for(const s of i)if(s.type==="childList")for(const r of s.addedNodes)r.tagName==="LINK"&&r.rel==="modulepreload"&&a(r)}).observe(document,{childList:!0,subtree:!0});function t(i){const s={};return i.integrity&&(s.integrity=i.integrity),i.referrerPolicy&&(s.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?s.credentials="include":i.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function a(i){if(i.ep)return;i.ep=!0;const s=t(i);fetch(i.href,s)}})();const y=`let buffer; - -self.onmessage = async (e) => { - if (e.data.cmd === 'init') { - buffer = e.data.buffer; - } else if (e.data.cmd === 'load') { - loadImage(e.data.offset, e.data.size, e.data.index); - } -}; - -async function loadImage(offset, size, index) { - const view = new Uint8Array(buffer, offset, size); - const blob = new Blob([view], {}); - const imageBitmap = await createImageBitmap(blob); - postMessage({msg: 'done', imageBitmap, index}, [imageBitmap]); -}`;class L{constructor(e,t={}){o(this,"fileInfo",[]);o(this,"buffer");o(this,"options");o(this,"worker");o(this,"resolve",[]);o(this,"defaultOptions",{useWorker:!0});this.buffer=e,this.options={...this.defaultOptions,...t};let a=0;for(;at.name.includes(e))}getImage(e,t){return this.options.useWorker?(this.worker||(this.worker=this.createWorker()),new Promise((a,i)=>{const s=this.getInfo(e);s&&!this.resolve[t]?(this.resolve[t]=a,this.worker.postMessage({cmd:"load",offset:s.header_offset+512,size:s.size,index:t})):i()})):new Promise((a,i)=>{const s=this.getBlob(e,"image");s!==void 0?createImageBitmap(s).then(r=>{a(r)}).catch(()=>{i()}):i()})}readFileName(e){const t=new Uint8Array(this.buffer,e,100),a=t.indexOf(0);return new TextDecoder().decode(t.slice(0,a))}readFileSize(e){const t=new Uint8Array(this.buffer,e+124,12);let a="";for(let i=0;i<11;i++)a+=String.fromCharCode(t[i]);return parseInt(a,8)}getBlob(e,t=""){const a=this.getInfo(e);if(a){const i=new Uint8Array(this.buffer,a.header_offset+512,a.size);return new Blob([i],{type:t})}}createWorker(){const e=new Blob([y],{type:"application/javascript"}),t=new Worker(URL.createObjectURL(e));return t.addEventListener("message",a=>{const i=this.resolve[a.data.index];this.resolve[a.data.index]=void 0,i?i(a.data.imageBitmap):a.data.imageBitmap.close()}),t.postMessage({cmd:"init",buffer:this.buffer},[this.buffer]),t}}const x=`self.onmessage = async (e) => { - if (e.data.cmd === 'load') { - await loadImage(e.data.url, e.data.index); - } -}; - -async function loadImage(url, index) { - const response = await fetch(url); - if (!response.ok) throw "network error"; - const imageBitmap = await createImageBitmap(await response.blob()); - postMessage({msg: 'done', imageBitmap, index}, [imageBitmap]); -}`;class C{constructor(){o(this,"index",-1e10);o(this,"worker");o(this,"resolve");const e=new Blob([x],{type:"application/javascript"}),t=new Worker(URL.createObjectURL(e));t.addEventListener("message",a=>{this.resolve&&a.data.index===this.index?this.resolve(a.data.imageBitmap):a.data.imageBitmap.close()}),this.worker=t}load(e,t){return this.index=e,new Promise((a,i)=>{this.resolve=a,this.worker.postMessage({cmd:"load",url:t,index:e})})}abort(){this.index=-1e10,this.resolve=void 0}}const p=[];function T(){return p.length===0&&p.push(new C),p.shift()}function k(n){n.abort(),p.push(n)}class F{constructor(e,t){o(this,"index");o(this,"priority",0);o(this,"tarImageAvailable",!1);o(this,"loading",!1);o(this,"loadingTarImage",!1);o(this,"context");o(this,"_image");o(this,"_tarImage");this.index=t,this.context=e}get tarImage(){if(this._tarImage!==void 0&&!this.loadingTarImage)return this._tarImage}set tarImage(e){this.releaseTarImage(),this._tarImage=e}get image(){if(this._image!==void 0&&!this.loading)return this._image}set image(e){this.releaseImage(),this._image=e}get tarImageURL(){if(this.context.options.tarImageURLCallback)return this.context.options.tarImageURLCallback(this.index)}get imageURL(){if(this.context.options.imageURLCallback)return new URL(this.context.options.imageURLCallback(this.index),window.location.href).href}reset(){this._image=void 0,this._tarImage=void 0,this.priority=0}async getImage(){return new Promise(async(e,t)=>{this.image!==void 0?e(this.image):this.tarImage!==void 0?e(this.tarImage):this.fetchTarImage().then(a=>e(a)).catch(()=>t())})}async fetchImage(){return new Promise((e,t)=>{if(this.imageURL){this.loading=!0;const a=s=>{this.loading&&(this.image=s,e(s))},i=s=>{this.reset(),t(s)};if(this.context.options.useWorkerForImage){const s=T();s.load(this.index,this.imageURL).then(r=>{a(r),k(s)}).catch(r=>i(r))}else{const s=new Image;this.loadImage(s,this.imageURL).then(()=>{a(s)}).catch(r=>i(r))}}else t()})}async fetchTarImage(){return new Promise((e,t)=>{this.tarImage!==void 0?e(this.tarImage):this.tarImageAvailable&&!this.loadingTarImage?(this.loadingTarImage=!0,this.context.tarball.getImage(this.tarImageURL,this.index).then(a=>{this.loadingTarImage&&(this.tarImage=a,e(a))}).catch(a=>{this.loadingTarImage=!1,this.reset(),t(a)})):(this.reset(),t())})}releaseImage(){this._image&&(this._image instanceof ImageBitmap&&this._image.close(),this._image=void 0),this.loading=!1}releaseTarImage(){this.tarImage&&(this.tarImage instanceof ImageBitmap&&this.tarImage.close(),this._tarImage=void 0),this.loadingTarImage=!1}loadImage(e,t){return new Promise((a,i)=>{e.onerror=s=>i(s),e.decoding="async",e.src=t,e.decode().then(()=>{a(e)}).catch(s=>{console.error(s),i(s),this.reset()})})}}function P(){const n=document.createElement("div");return Object.assign(n.style,{position:"absolute",top:"0",left:"0",backgroundColor:"rgba(0, 0, 0, 0.5)",color:"white",padding:"8px",fontSize:"12px",zIndex:"1000",lineHeight:"20px"}),n}function R(n,e){n.innerHTML=`
${e}
`}function S(n,e){return new Promise((t,a)=>{const i=new XMLHttpRequest;i.open("GET",n,!0),i.responseType="arraybuffer",i.onprogress=function(s){if(s.lengthComputable&&e){const r=s.loaded/s.total;e(r)}},i.onload=function(){i.status===200?t(i.response):a(new Error(`Error ${i.status}: ${i.statusText}`))},i.onerror=function(){a(new Error("Request failed"))},i.send()})}function E(){return typeof navigator<"u"&&/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)}function I(n,e,t){return Math.min(Math.max(n,e),t)}const u=class u{constructor(e,t){o(this,"canvas");o(this,"options");o(this,"width",0);o(this,"height",0);o(this,"frame",0);o(this,"tarball");o(this,"context");o(this,"tickFuncs",[]);o(this,"frames",[]);o(this,"startTime",-1);o(this,"animationRequestId",0);o(this,"container");o(this,"resizeObserver");o(this,"mutationOberver");o(this,"clearCanvas",!0);o(this,"speed",0);o(this,"prevFrame",0);o(this,"direction",1);o(this,"lastFrameDrawn",-1);o(this,"destructed",!1);o(this,"logElement");o(this,"initialized",!1);o(this,"log");o(this,"tarLoadProgress",0);if(this.options={...u.defaultOptions,...t},this.options.frames<=0)throw new Error("FastImageSequence: frames must be greater than 0");this.options.maxCachedImages=Math.floor(this.options.maxCachedImages),this.options.maxCachedImages=I(this.options.frames,1,this.options.maxCachedImages),this.container=e,this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),this.context.fillStyle=this.options.fillStyle,this.context.clearRect(0,0,this.canvas.width,this.canvas.height),Object.assign(this.canvas.style,{inset:"0",width:"100%",height:"100%",margin:"0",display:"block"}),this.container.appendChild(this.canvas),this.resizeObserver=new ResizeObserver(()=>{this.clearCanvas=!0}),this.resizeObserver.observe(this.canvas),this.mutationOberver=new MutationObserver(()=>{this.container.isConnected||(console.error("FastImageSequence: container is not connected to the DOM, fast image sequence will be destroyed"),this.destruct())}),this.mutationOberver.observe(e,{childList:!0});for(let a=0;a{},this.loadResources().then(()=>{this.initialized=!0,this.log("Frames",this.frames),this.log("Options",this.options),this.options.showDebugInfo&&(this.logElement=P(),this.container.appendChild(this.logElement),this.tick(()=>this.logDebugStatus(this.logElement))),this.drawingLoop(-1)})}get playing(){return this.speed!==0}get paused(){return!this.playing}get loadProgress(){const{used:e,numLoaded:t,numLoading:a,maxLoaded:i}=this.getLoadStatus(),{used:s,numLoading:r,numLoaded:d,maxLoaded:l,tarLoadProgress:c}=this.getTarStatus();return((e?Math.max(t-a,0):0)+(s?Math.max(d-r,0)/2+c:0))/((e?i:0)+(s?l/2+1:0))}get progress(){return this.index/(this.options.frames-1)}set progress(e){this.frame=(this.options.frames-1)*e}get ready(){return new Promise(e=>{const t=()=>{this.lastFrameDrawn!==-1?e():setTimeout(t,16)};t()})}get index(){return this.wrapIndex(this.frame)}get spread(){return this.options.loop?Math.floor(this.options.maxCachedImages/2):this.options.maxCachedImages}tick(e){this.tickFuncs.push(e)}play(e=30){this.speed=e}stop(){this.speed=0}async getFrameImage(e){const t=this.frames[this.wrapIndex(e)];try{return await t.fetchImage()}catch{return await t.fetchTarImage()}}async onLoadProgress(e){let t=this.loadProgress;return new Promise(a=>{const i=()=>{this.loadProgress>=1?(e&&e(1),a(!0)):(e&&t!==this.loadProgress&&(e(this.loadProgress),t=this.loadProgress),setTimeout(i,16))};i()})}setMaxCachedImages(e,t){return this.options.maxCachedImages=I(e,1,this.options.frames),this.onLoadProgress(t)}destruct(){this.destructed||(this.destructed=!0,this.animationRequestId&&cancelAnimationFrame(this.animationRequestId),this.resizeObserver.disconnect(),this.mutationOberver.disconnect(),this.container.removeChild(this.canvas),this.logElement&&(this.container.removeChild(this.logElement),this.logElement=void 0),this.canvas.replaceWith(this.canvas.cloneNode(!0)),this.frames.forEach(e=>{e.releaseImage(),e.releaseTarImage()}))}setDisplayOptions(e){this.options={...this.options,...e},this.clearCanvas=!0}async loadResources(){if(this.options.tarURL!==void 0){const e=await S(this.options.tarURL,t=>{this.tarLoadProgress=t});this.tarball=new L(e,{useWorker:this.options.useWorkerForTar}),this.log("Tarball",this.tarball),this.frames.forEach(t=>{var a;return t.tarImageAvailable=t.tarImageURL!==void 0&&((a=this.tarball)==null?void 0:a.getInfo(t.tarImageURL))!==void 0}),this.options.preloadAllTarImages&&await Promise.all(this.frames.map(t=>t.fetchTarImage()))}await this.getFrameImage(0)}wrapIndex(e){const t=e|0;return this.wrapFrame(t)}wrapFrame(e){return this.options.loop?(e%this.options.frames+this.options.frames)%this.options.frames:I(e,0,this.options.frames-1)}async drawingLoop(e=0){if(this.destructed)return;e/=1e3;const t=this.initialized?this.startTime<0?1/60:Math.min(e-this.startTime,1/30):0;this.startTime=e>0?e:-1,this.frame-this.prevFrame<0&&(this.direction=-1),this.frame-this.prevFrame>0&&(this.direction=1),this.frame+=this.speed*t,this.frame=this.wrapFrame(this.frame);const a=this.index,i=this.canvas.getBoundingClientRect();if(i.top0){this.frames.forEach(l=>{l.priority=Math.abs(l.index-a);let c=Math.sign(this.frame-this.prevFrame);if(this.options.loop){const h=this.options.frames-l.priority;hc.priority-l.priority);const r=this.frames.filter(l=>l.image!==void 0).pop();r&&r.image&&this.drawFrame(r);const d=this.frames.filter(l=>l.tarImage!==void 0).pop();d&&d.tarImage&&(r&&r.image&&r.priority<=d.priority||this.drawFrame(d))}this.process(t),this.tickFuncs.forEach(r=>r(t)),this.prevFrame=this.frame,this.animationRequestId=requestAnimationFrame(r=>this.drawingLoop(r))}drawFrame(e){const t=e.image||e.tarImage;if(!t)return;this.lastFrameDrawn=e.index;const a=this.container.offsetWidth/this.container.offsetHeight,i=t.width/t.height;if(this.width=Math.max(this.width,t.width),this.height=Math.max(this.height,t.height),this.options.objectFit==="contain"){const d=a>i?this.height*a:this.width,l=a>i?this.height:this.width/a;(this.canvas.width!==d||this.canvas.height!==this.height)&&(this.canvas.width=d,this.canvas.height=l)}else{const d=a>i?this.width:this.height*a,l=a>i?this.width/a:this.height;(this.canvas.width!==d||this.canvas.height!==this.height)&&(this.canvas.width=d,this.canvas.height=l)}const s=(this.canvas.width-this.width)*this.options.horizontalAlign,r=(this.canvas.height-this.height)*this.options.verticalAlign;(this.clearCanvas||this.options.clearCanvas)&&(this.context.clearRect(0,0,this.canvas.width,this.canvas.height),this.clearCanvas=!1),this.context.drawImage(t,0,0,t.width,t.height,s,r,this.width,this.height)}setLoadingPriority(){const e=this.index;this.frames.forEach(t=>{t.priority=Math.abs(t.index+.25-e),this.options.loop&&(t.priority=Math.min(t.priority,this.options.frames-t.priority))})}process(e){var t,a;if(this.setLoadingPriority(),!this.options.preloadAllTarImages&&this.options.tarURL!==void 0&&this.tarball){let{numLoading:i,numLoaded:s}=this.getTarStatus();const r=this.options.maxConnectionLimit,d=this.frames.filter(h=>h.tarImage===void 0&&h.tarImageAvailable&&!h.loadingTarImage).sort((h,m)=>h.priority-m.priority),c=((t=this.frames.filter(h=>h.tarImage!==void 0&&h.tarImageAvailable&&!h.loadingTarImage).sort((h,m)=>m.priority-h.priority).shift())==null?void 0:t.priority)??1e10;for(;i0;){const h=d.shift();(h.priority{this.releaseTarImageWithLowestPriority()}).catch(m=>{console.error(m)}),i++}}if(this.options.imageURLCallback){let{numLoading:i,numLoaded:s}=this.getLoadStatus();const r=this.options.maxConnectionLimit,d=this.frames.filter(h=>h.image===void 0&&!h.loading&&h.priority).sort((h,m)=>h.priority-m.priority),c=((a=this.frames.filter(h=>h.image!==void 0&&!h.loading).sort((h,m)=>m.priority-h.priority).shift())==null?void 0:a.priority)??1e10;for(;i0;){const h=d.shift();(h.priority{this.releaseImageWithLowestPriority()}).catch(m=>{console.error(m)}),i++}}}getLoadStatus(){const e=this.options.imageURLCallback!==void 0,t=this.frames.filter(r=>r.loading).length,a=this.frames.filter(r=>r.image!==void 0).length,i=this.options.maxCachedImages,s=Math.max(0,a-t)/i;return{used:e,progress:s,numLoading:t,numLoaded:a,maxLoaded:i}}getTarStatus(){const e=this.options.tarURL!==void 0,t=this.tarball!==void 0&&this.initialized,a=this.frames.filter(l=>l.loadingTarImage).length,i=this.frames.filter(l=>l.tarImage!==void 0).length,s=this.options.preloadAllTarImages?this.frames.length:this.options.maxCachedImages,r=this.tarLoadProgress,d=i/s;return{used:e,tarLoaded:t,progress:d,numLoading:a,numLoaded:i,maxLoaded:s,tarLoadProgress:r}}logDebugStatus(e){const t=i=>`${Math.abs(i*100).toFixed(1).padStart(5," ")}%`;let a=`${this.options.name} - frames: ${this.frames.length}, maxCache: ${this.options.maxCachedImages}, wrap: ${this.options.loop}, size: ${this.options.objectFit} -- loadProgress ${t(this.loadProgress)}, last frame drawn ${this.lastFrameDrawn}/${this.index} -`;{const{used:i,progress:s,numLoading:r,numLoaded:d,maxLoaded:l}=this.getLoadStatus();a+=`- images: ${i?`${t(s)}, numLoading: ${r}, numLoaded: ${d}/${l}`:"not used"} -`}{const{used:i,tarLoaded:s,progress:r,numLoading:d,numLoaded:l,maxLoaded:c}=this.getTarStatus();a+=`- tar: ${i?`${t(r)}, numLoading: ${d}, numLoaded: ${l}/${c}`:"not used"}`}R(e,a)}releaseImageWithLowestPriority(){this.setLoadingPriority();const e=this.frames.filter(t=>t.image!==void 0&&!t.loading);if(e.length>this.options.maxCachedImages){const t=e.sort((a,i)=>a.priority-i.priority).pop();t&&t.releaseImage()}}releaseTarImageWithLowestPriority(){if(!this.options.preloadAllTarImages){this.setLoadingPriority();const e=this.frames.filter(t=>t.tarImage!==void 0&&!t.loadingTarImage);if(e.length>this.options.maxCachedImages){const t=e.sort((a,i)=>a.priority-i.priority).pop();t&&t.releaseTarImage()}}}};o(u,"defaultOptions",{frames:1,imageURLCallback:void 0,tarURL:void 0,tarImageURLCallback:void 0,loop:!1,fillStyle:"#00000000",objectFit:"cover",preloadAllTarImages:!1,clearCanvas:!1,useWorkerForTar:!0,useWorkerForImage:!E(),maxCachedImages:32,showDebugInfo:!1,name:"FastImageSequence",maxConnectionLimit:4,horizontalAlign:.5,verticalAlign:.5});let g=u;const M=document.getElementById("prev-button"),U=document.getElementById("next-button"),f=document.getElementById("slider-input");async function B(n){const e=new g(n,{name:"PlayWithControlTest",frames:89,imageURLCallback:t=>`${(""+(t+1)).padStart(4,"0")}.webp`,tarURL:"lowrespreviews.tar",tarImageURLCallback:t=>`${(""+(t+1)).padStart(4,"0")}.jpg`,loop:!0,objectFit:"contain",fillStyle:"#00000000",preloadAllTarImages:!1,useWorkerForTar:!0,maxCachedImages:32,clearCanvas:!1,showDebugInfo:!0});await e.ready,e.progress=0,e.tick(t=>{e.playing&&(f.value=e.progress)}),M.addEventListener("click",()=>{e.play(-30)}),U.addEventListener("click",()=>{e.play(30)}),f.addEventListener("mousedown",t=>{e.stop()}),f.addEventListener("input",()=>{e.paused&&(e.progress=f.value)}),e.play(30)}async function W(n){const e=new g(n,{name:"PlayBackwardsTest at 200fps",frames:89,imageURLCallback:t=>`${(""+(t+1)).padStart(4,"0")}.webp`,loop:!0,objectFit:"cover",fillStyle:"#00000000",preloadAllTarImages:!1,useWorkerForTar:!0,maxCachedImages:32,clearCanvas:!1,showDebugInfo:!0});await e.ready,e.progress=0,e.play(-200)}async function O(n){const e=new g(n,{name:"StillImageTest",frames:89,imageURLCallback:t=>`${(""+(t+1)).padStart(4,"0")}.webp`,loop:!0,objectFit:"cover",fillStyle:"#00000000",preloadAllTarImages:!1,useWorkerForTar:!0,maxCachedImages:1,clearCanvas:!1,showDebugInfo:!0});await e.ready,console.log("fastImageSequence loaded"),setTimeout(()=>{e.setMaxCachedImages(89,t=>console.log("preload progress:",t)).then(()=>{console.log("all frames preloaded")})},2e3)}function A(n){let e=w(n);setInterval(()=>{console.log("destructing"),e.destruct(),console.log("constructing"),e=w(n)},3e3)}function w(n){const e=new g(n,{name:"ConstructDestructTest",frames:89,imageURLCallback:t=>`${(""+(t+1)).padStart(4,"0")}.webp`,tarURL:Math.random()>.5?"lowrespreviews.tar":void 0,tarImageURLCallback:t=>`${(""+(t+1)).padStart(4,"0")}.jpg`,loop:Math.random()>.5,objectFit:Math.random()>.5?"cover":"contain",fillStyle:"#00000000",preloadAllTarImages:Math.random()>.5,useWorkerForTar:Math.random()>.5,maxCachedImages:1+Math.random()*32|0,clearCanvas:Math.random()>.5,showDebugInfo:!0});return e.ready.then(()=>{e.tick(()=>e.progress=Math.random())}),e}B(document.getElementsByClassName("grid-item")[0]);W(document.getElementsByClassName("grid-item")[1]);O(document.getElementsByClassName("grid-item")[2]);A(document.getElementsByClassName("grid-item")[3]); diff --git a/assets/index-B9REFjg6.js b/assets/index-B9REFjg6.js new file mode 100644 index 0000000..86c22d4 --- /dev/null +++ b/assets/index-B9REFjg6.js @@ -0,0 +1,30 @@ +var v=Object.defineProperty;var b=(h,e,t)=>e in h?v(h,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):h[e]=t;var o=(h,e,t)=>(b(h,typeof e!="symbol"?e+"":e,t),t);(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))s(i);new MutationObserver(i=>{for(const a of i)if(a.type==="childList")for(const r of a.addedNodes)r.tagName==="LINK"&&r.rel==="modulepreload"&&s(r)}).observe(document,{childList:!0,subtree:!0});function t(i){const a={};return i.integrity&&(a.integrity=i.integrity),i.referrerPolicy&&(a.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?a.credentials="include":i.crossOrigin==="anonymous"?a.credentials="omit":a.credentials="same-origin",a}function s(i){if(i.ep)return;i.ep=!0;const a=t(i);fetch(i.href,a)}})();const y=`let buffer; + +self.onmessage = async (e) => { + if (e.data.cmd === 'init') { + buffer = e.data.buffer; + } else if (e.data.cmd === 'load') { + loadImage(e.data.offset, e.data.size, e.data.index); + } +}; + +async function loadImage(offset, size, index) { + const view = new Uint8Array(buffer, offset, size); + const blob = new Blob([view], {}); + const imageBitmap = await createImageBitmap(blob); + postMessage({msg: 'done', imageBitmap, index}, [imageBitmap]); +}`;class L{constructor(e,t={}){o(this,"fileInfo",[]);o(this,"buffer");o(this,"options");o(this,"worker");o(this,"resolve",[]);o(this,"defaultOptions",{useWorker:!0});this.buffer=e,this.options={...this.defaultOptions,...t};let s=0;for(;st.name.includes(e))}getImage(e,t){return this.options.useWorker?(this.worker||(this.worker=this.createWorker()),new Promise((s,i)=>{const a=this.getInfo(e);a&&!this.resolve[t]?(this.resolve[t]=s,this.worker.postMessage({cmd:"load",offset:a.header_offset+512,size:a.size,index:t})):i()})):new Promise((s,i)=>{const a=this.getBlob(e,"image");a!==void 0?createImageBitmap(a).then(r=>{s(r)}).catch(()=>{i()}):i()})}readFileName(e){const t=new Uint8Array(this.buffer,e,100),s=t.indexOf(0);return new TextDecoder().decode(t.slice(0,s))}readFileSize(e){const t=new Uint8Array(this.buffer,e+124,12);let s="";for(let i=0;i<11;i++)s+=String.fromCharCode(t[i]);return parseInt(s,8)}getBlob(e,t=""){const s=this.getInfo(e);if(s){const i=new Uint8Array(this.buffer,s.header_offset+512,s.size);return new Blob([i],{type:t})}}createWorker(){const e=new Blob([y],{type:"application/javascript"}),t=new Worker(URL.createObjectURL(e));return t.addEventListener("message",s=>{const i=this.resolve[s.data.index];this.resolve[s.data.index]=void 0,i?i(s.data.imageBitmap):s.data.imageBitmap.close()}),t.postMessage({cmd:"init",buffer:this.buffer},[this.buffer]),t}}const x=`self.onmessage = async (e) => { + if (e.data.cmd === 'load') { + await loadImage(e.data.url, e.data.index); + } +}; + +async function loadImage(url, index) { + const response = await fetch(url); + if (!response.ok) throw "network error"; + const imageBitmap = await createImageBitmap(await response.blob()); + postMessage({msg: 'done', imageBitmap, index}, [imageBitmap]); +}`;class C{constructor(){o(this,"index",-1e10);o(this,"worker");o(this,"resolve");const e=new Blob([x],{type:"application/javascript"}),t=new Worker(URL.createObjectURL(e));t.addEventListener("message",s=>{this.resolve&&s.data.index===this.index?this.resolve(s.data.imageBitmap):s.data.imageBitmap.close()}),this.worker=t}load(e,t){return this.index=e,new Promise((s,i)=>{this.resolve=s,this.worker.postMessage({cmd:"load",url:t,index:e})})}abort(){this.index=-1e10,this.resolve=void 0}}const p=[];function T(){return p.length===0&&p.push(new C),p.shift()}function k(h){h.abort(),p.push(h)}class F{constructor(e,t){o(this,"index");o(this,"priority",0);o(this,"tarImageAvailable",!1);o(this,"loading",!1);o(this,"loadingTarImage",!1);o(this,"context");o(this,"_image");o(this,"_tarImage");this.index=t,this.context=e}get tarImage(){if(this._tarImage!==void 0&&!this.loadingTarImage)return this._tarImage}set tarImage(e){this.releaseTarImage(),this._tarImage=e}get image(){if(this._image!==void 0&&!this.loading)return this._image}set image(e){this.releaseImage(),this._image=e}get tarImageURL(){if(this.context.options.tarImageURLCallback)return this.context.options.tarImageURLCallback(this.index)}get imageURL(){if(this.context.options.imageURLCallback)return new URL(this.context.options.imageURLCallback(this.index),window.location.href).href}reset(){this._image=void 0,this._tarImage=void 0,this.priority=0}async getImage(){return new Promise(async(e,t)=>{this.image!==void 0?e(this.image):this.tarImage!==void 0?e(this.tarImage):this.fetchTarImage().then(s=>e(s)).catch(()=>t())})}async fetchImage(){return new Promise((e,t)=>{if(this.imageURL){this.loading=!0;const s=a=>{this.loading&&(this.image=a,e(a))},i=a=>{this.reset(),t(a)};if(this.context.options.useWorkerForImage){const a=T();a.load(this.index,this.imageURL).then(r=>{s(r),k(a)}).catch(r=>i(r))}else{const a=new Image;this.loadImage(a,this.imageURL).then(()=>{s(a)}).catch(r=>i(r))}}else t()})}async fetchTarImage(){return new Promise((e,t)=>{this.tarImage!==void 0?e(this.tarImage):this.tarImageAvailable&&!this.loadingTarImage?(this.loadingTarImage=!0,this.context.tarball.getImage(this.tarImageURL,this.index).then(s=>{this.loadingTarImage&&(this.tarImage=s,e(s))}).catch(s=>{this.loadingTarImage=!1,this.reset(),t(s)})):(this.reset(),t())})}releaseImage(){this._image&&(this._image instanceof ImageBitmap&&this._image.close(),this._image=void 0),this.loading=!1}releaseTarImage(){this.tarImage&&(this.tarImage instanceof ImageBitmap&&this.tarImage.close(),this._tarImage=void 0),this.loadingTarImage=!1}loadImage(e,t){return new Promise((s,i)=>{e.onerror=a=>i(a),e.decoding="async",e.src=t,e.decode().then(()=>{s(e)}).catch(a=>{console.error(a),i(a),this.reset()})})}}function P(){const h=document.createElement("div");return Object.assign(h.style,{position:"absolute",top:"0",left:"0",backgroundColor:"rgba(0, 0, 0, 0.5)",color:"white",padding:"8px",fontSize:"12px",zIndex:"1000",lineHeight:"20px"}),h}function R(h,e){h.innerHTML=`
${e}
`}function S(h,e){return new Promise((t,s)=>{const i=new XMLHttpRequest;i.open("GET",h,!0),i.responseType="arraybuffer",i.onprogress=function(a){if(a.lengthComputable&&e){const r=a.loaded/a.total;e(r)}},i.onload=function(){i.status===200?t(i.response):s(new Error(`Error ${i.status}: ${i.statusText}`))},i.onerror=function(){s(new Error("Request failed"))},i.send()})}function E(){return typeof navigator<"u"&&/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)}function I(h,e,t){return Math.min(Math.max(h,e),t)}const u=class u{constructor(e,t){o(this,"canvas");o(this,"options");o(this,"width",0);o(this,"height",0);o(this,"frame",0);o(this,"tarball");o(this,"context");o(this,"tickFuncs",[]);o(this,"frames",[]);o(this,"startTime",-1);o(this,"animationRequestId",0);o(this,"container");o(this,"resizeObserver");o(this,"mutationOberver");o(this,"clearCanvas",!0);o(this,"speed",0);o(this,"prevFrame",0);o(this,"direction",1);o(this,"lastFrameDrawn",-1);o(this,"destructed",!1);o(this,"logElement");o(this,"initialized",!1);o(this,"log");o(this,"tarLoadProgress",0);if(this.options={...u.defaultOptions,...t},this.options.frames<=0)throw new Error("FastImageSequence: frames must be greater than 0");this.options.maxCachedImages=Math.floor(this.options.maxCachedImages),this.options.maxCachedImages=I(this.options.frames,1,this.options.maxCachedImages),this.container=e,this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),this.context.fillStyle=this.options.fillStyle,this.context.clearRect(0,0,this.canvas.width,this.canvas.height),Object.assign(this.canvas.style,{inset:"0",width:"100%",height:"100%",margin:"0",display:"block"}),this.container.appendChild(this.canvas),this.resizeObserver=new ResizeObserver(()=>{this.clearCanvas=!0}),this.resizeObserver.observe(this.canvas),this.mutationOberver=new MutationObserver(()=>{this.container.isConnected||(console.error("FastImageSequence: container is not connected to the DOM, fast image sequence will be destroyed"),this.destruct())}),this.mutationOberver.observe(e,{childList:!0});for(let s=0;s{},this.loadResources().then(()=>{this.initialized=!0,this.log("Frames",this.frames),this.log("Options",this.options),this.options.showDebugInfo&&(this.logElement=P(),this.container.appendChild(this.logElement),this.tick(()=>this.logDebugStatus(this.logElement))),this.drawingLoop(-1)})}get playing(){return this.speed!==0}get paused(){return!this.playing}get loadProgress(){const{used:e,numLoaded:t,numLoading:s,maxLoaded:i}=this.getLoadStatus(),{used:a,numLoading:r,numLoaded:d,maxLoaded:l,tarLoadProgress:m}=this.getTarStatus(),n=e?Math.max(t-s,0)/i:0,c=a?Math.max(d-r,0)/l/2+m/2:0;return(n+c)/((e?1:0)+(a?1:0))}get progress(){return this.index/(this.options.frames-1)}set progress(e){this.frame=(this.options.frames-1)*e}get ready(){return new Promise(e=>{const t=()=>{this.lastFrameDrawn!==-1?e():setTimeout(t,16)};t()})}get index(){return this.wrapIndex(this.frame)}get spread(){return this.options.loop?Math.floor(this.options.maxCachedImages/2):this.options.maxCachedImages}tick(e){this.tickFuncs.push(e)}play(e=30){this.speed=e}stop(){this.speed=0}async getFrameImage(e){const t=this.frames[this.wrapIndex(e)];try{return await t.fetchImage()}catch{return await t.fetchTarImage()}}async onLoadProgress(e){let t=this.loadProgress;return new Promise(s=>{const i=()=>{this.loadProgress>=1?(e&&e(1),s(!0)):(e&&t!==this.loadProgress&&(e(this.loadProgress),t=this.loadProgress),setTimeout(i,16))};i()})}setMaxCachedImages(e,t){return this.options.maxCachedImages=I(e,1,this.options.frames),this.onLoadProgress(t)}destruct(){this.destructed||(this.destructed=!0,this.animationRequestId&&cancelAnimationFrame(this.animationRequestId),this.resizeObserver.disconnect(),this.mutationOberver.disconnect(),this.container.removeChild(this.canvas),this.logElement&&(this.container.removeChild(this.logElement),this.logElement=void 0),this.canvas.replaceWith(this.canvas.cloneNode(!0)),this.frames.forEach(e=>{e.releaseImage(),e.releaseTarImage()}))}setDisplayOptions(e){this.options={...this.options,...e},this.clearCanvas=!0}async loadResources(){if(this.options.tarURL!==void 0){const e=await S(this.options.tarURL,t=>{this.tarLoadProgress=t});this.tarball=new L(e,{useWorker:this.options.useWorkerForTar}),this.log("Tarball",this.tarball),this.frames.forEach(t=>{var s;return t.tarImageAvailable=t.tarImageURL!==void 0&&((s=this.tarball)==null?void 0:s.getInfo(t.tarImageURL))!==void 0}),this.options.preloadAllTarImages&&await Promise.all(this.frames.map(t=>t.fetchTarImage()))}await this.getFrameImage(0)}wrapIndex(e){const t=e|0;return this.wrapFrame(t)}wrapFrame(e){return this.options.loop?(e%this.options.frames+this.options.frames)%this.options.frames:I(e,0,this.options.frames-1)}async drawingLoop(e=0){if(this.destructed)return;e/=1e3;const t=this.initialized?this.startTime<0?1/60:Math.min(e-this.startTime,1/30):0;this.startTime=e>0?e:-1,this.frame-this.prevFrame<0&&(this.direction=-1),this.frame-this.prevFrame>0&&(this.direction=1),this.frame+=this.speed*t,this.frame=this.wrapFrame(this.frame);const s=this.index,i=this.canvas.getBoundingClientRect();if(i.top0){this.frames.forEach(l=>{l.priority=Math.abs(l.index-s);let m=Math.sign(this.frame-this.prevFrame);if(this.options.loop){const n=this.options.frames-l.priority;nm.priority-l.priority);const r=this.frames.filter(l=>l.image!==void 0).pop();r&&r.image&&this.drawFrame(r);const d=this.frames.filter(l=>l.tarImage!==void 0).pop();d&&d.tarImage&&(r&&r.image&&r.priority<=d.priority||this.drawFrame(d))}this.process(t),this.tickFuncs.forEach(r=>r(t)),this.prevFrame=this.frame,this.animationRequestId=requestAnimationFrame(r=>this.drawingLoop(r))}drawFrame(e){const t=e.image||e.tarImage;if(!t)return;this.lastFrameDrawn=e.index;const s=this.container.offsetWidth/this.container.offsetHeight,i=t.width/t.height;if(this.width=Math.max(this.width,t.width),this.height=Math.max(this.height,t.height),this.options.objectFit==="contain"){const d=s>i?this.height*s:this.width,l=s>i?this.height:this.width/s;(this.canvas.width!==d||this.canvas.height!==this.height)&&(this.canvas.width=d,this.canvas.height=l)}else{const d=s>i?this.width:this.height*s,l=s>i?this.width/s:this.height;(this.canvas.width!==d||this.canvas.height!==this.height)&&(this.canvas.width=d,this.canvas.height=l)}const a=(this.canvas.width-this.width)*this.options.horizontalAlign,r=(this.canvas.height-this.height)*this.options.verticalAlign;(this.clearCanvas||this.options.clearCanvas)&&(this.context.clearRect(0,0,this.canvas.width,this.canvas.height),this.clearCanvas=!1),this.context.drawImage(t,0,0,t.width,t.height,a,r,this.width,this.height)}setLoadingPriority(){const e=this.index;this.frames.forEach(t=>{t.priority=Math.abs(t.index+.25-e),this.options.loop&&(t.priority=Math.min(t.priority,this.options.frames-t.priority))})}process(e){var t,s;if(this.setLoadingPriority(),!this.options.preloadAllTarImages&&this.options.tarURL!==void 0&&this.tarball){let{numLoading:i,numLoaded:a}=this.getTarStatus();const r=this.options.maxConnectionLimit,d=this.frames.filter(n=>n.tarImage===void 0&&n.tarImageAvailable&&!n.loadingTarImage).sort((n,c)=>n.priority-c.priority),m=((t=this.frames.filter(n=>n.tarImage!==void 0&&n.tarImageAvailable&&!n.loadingTarImage).sort((n,c)=>c.priority-n.priority).shift())==null?void 0:t.priority)??1e10;for(;i0;){const n=d.shift();(n.priority{this.releaseTarImageWithLowestPriority()}).catch(c=>{console.error(c)}),i++}}if(this.options.imageURLCallback){let{numLoading:i,numLoaded:a}=this.getLoadStatus();const r=this.options.maxConnectionLimit,d=this.frames.filter(n=>n.image===void 0&&!n.loading&&n.priority).sort((n,c)=>n.priority-c.priority),m=((s=this.frames.filter(n=>n.image!==void 0&&!n.loading).sort((n,c)=>c.priority-n.priority).shift())==null?void 0:s.priority)??1e10;for(;i0;){const n=d.shift();(n.priority{this.releaseImageWithLowestPriority()}).catch(c=>{console.error(c)}),i++}}}getLoadStatus(){const e=this.options.imageURLCallback!==void 0,t=this.frames.filter(r=>r.loading).length,s=this.frames.filter(r=>r.image!==void 0).length,i=this.options.maxCachedImages,a=Math.max(0,s-t)/i;return{used:e,progress:a,numLoading:t,numLoaded:s,maxLoaded:i}}getTarStatus(){const e=this.options.tarURL!==void 0,t=this.tarball!==void 0&&this.initialized,s=this.frames.filter(l=>l.loadingTarImage).length,i=this.frames.filter(l=>l.tarImage!==void 0).length,a=this.options.preloadAllTarImages?this.frames.length:this.options.maxCachedImages,r=this.tarLoadProgress,d=i/a;return{used:e,tarLoaded:t,progress:d,numLoading:s,numLoaded:i,maxLoaded:a,tarLoadProgress:r}}logDebugStatus(e){const t=i=>`${Math.abs(i*100).toFixed(1).padStart(5," ")}%`;let s=`${this.options.name} - frames: ${this.frames.length}, maxCache: ${this.options.maxCachedImages}, wrap: ${this.options.loop}, size: ${this.options.objectFit} +- loadProgress ${t(this.loadProgress)}, last frame drawn ${this.lastFrameDrawn}/${this.index} +`;{const{used:i,progress:a,numLoading:r,numLoaded:d,maxLoaded:l}=this.getLoadStatus();s+=`- images: ${i?`${t(a)}, numLoading: ${r}, numLoaded: ${d}/${l}`:"not used"} +`}{const{used:i,tarLoaded:a,progress:r,numLoading:d,numLoaded:l,maxLoaded:m}=this.getTarStatus();s+=`- tar: ${i?`${t(r)}, numLoading: ${d}, numLoaded: ${l}/${m}`:"not used"}`}R(e,s)}releaseImageWithLowestPriority(){this.setLoadingPriority();const e=this.frames.filter(t=>t.image!==void 0&&!t.loading);if(e.length>this.options.maxCachedImages){const t=e.sort((s,i)=>s.priority-i.priority).pop();t&&t.releaseImage()}}releaseTarImageWithLowestPriority(){if(!this.options.preloadAllTarImages){this.setLoadingPriority();const e=this.frames.filter(t=>t.tarImage!==void 0&&!t.loadingTarImage);if(e.length>this.options.maxCachedImages){const t=e.sort((s,i)=>s.priority-i.priority).pop();t&&t.releaseTarImage()}}}};o(u,"defaultOptions",{frames:1,imageURLCallback:void 0,tarURL:void 0,tarImageURLCallback:void 0,loop:!1,fillStyle:"#00000000",objectFit:"cover",preloadAllTarImages:!1,clearCanvas:!1,useWorkerForTar:!0,useWorkerForImage:!E(),maxCachedImages:32,showDebugInfo:!1,name:"FastImageSequence",maxConnectionLimit:4,horizontalAlign:.5,verticalAlign:.5});let g=u;const M=document.getElementById("prev-button"),U=document.getElementById("next-button"),f=document.getElementById("slider-input");async function B(h){const e=new g(h,{name:"PlayWithControlTest",frames:89,imageURLCallback:t=>`${(""+(t+1)).padStart(4,"0")}.webp`,tarURL:"lowrespreviews.tar",tarImageURLCallback:t=>`${(""+(t+1)).padStart(4,"0")}.jpg`,loop:!0,objectFit:"contain",fillStyle:"#00000000",preloadAllTarImages:!1,useWorkerForTar:!0,maxCachedImages:32,clearCanvas:!1,showDebugInfo:!0});await e.ready,e.progress=0,e.tick(t=>{e.playing&&(f.value=e.progress)}),M.addEventListener("click",()=>{e.play(-30)}),U.addEventListener("click",()=>{e.play(30)}),f.addEventListener("mousedown",t=>{e.stop()}),f.addEventListener("input",()=>{e.paused&&(e.progress=f.value)}),e.play(30)}async function W(h){const e=new g(h,{name:"PlayBackwardsTest at 200fps",frames:89,imageURLCallback:t=>`${(""+(t+1)).padStart(4,"0")}.webp`,loop:!0,objectFit:"cover",fillStyle:"#00000000",preloadAllTarImages:!1,useWorkerForTar:!0,maxCachedImages:32,clearCanvas:!1,showDebugInfo:!0});await e.ready,e.progress=0,e.play(-200)}async function O(h){const e=new g(h,{name:"StillImageTest",frames:89,imageURLCallback:t=>`${(""+(t+1)).padStart(4,"0")}.webp`,loop:!0,objectFit:"cover",fillStyle:"#00000000",preloadAllTarImages:!1,useWorkerForTar:!0,maxCachedImages:1,clearCanvas:!1,showDebugInfo:!0});await e.ready,console.log("fastImageSequence loaded"),setTimeout(()=>{e.setMaxCachedImages(89,t=>console.log("preload progress:",t)).then(()=>{console.log("all frames preloaded")})},2e3)}function A(h){let e=w(h);setInterval(()=>{console.log("destructing"),e.destruct(),console.log("constructing"),e=w(h)},3e3)}function w(h){const e=new g(h,{name:"ConstructDestructTest",frames:89,imageURLCallback:t=>`${(""+(t+1)).padStart(4,"0")}.webp`,tarURL:Math.random()>.5?"lowrespreviews.tar":void 0,tarImageURLCallback:t=>`${(""+(t+1)).padStart(4,"0")}.jpg`,loop:Math.random()>.5,objectFit:Math.random()>.5?"cover":"contain",fillStyle:"#00000000",preloadAllTarImages:Math.random()>.5,useWorkerForTar:Math.random()>.5,maxCachedImages:1+Math.random()*32|0,clearCanvas:Math.random()>.5,showDebugInfo:!0});return e.ready.then(()=>{e.tick(()=>e.progress=Math.random())}),e}B(document.getElementsByClassName("grid-item")[0]);W(document.getElementsByClassName("grid-item")[1]);O(document.getElementsByClassName("grid-item")[2]);A(document.getElementsByClassName("grid-item")[3]); diff --git a/index.html b/index.html index 466b196..1639281 100644 --- a/index.html +++ b/index.html @@ -52,7 +52,7 @@ margin: 0; } - +