-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathszi-tile-source-v0.6.1.umd.cjs
More file actions
1 lines (1 loc) · 8.67 KB
/
szi-tile-source-v0.6.1.umd.cjs
File metadata and controls
1 lines (1 loc) · 8.67 KB
1
(function(f,l){typeof exports=="object"&&typeof module<"u"?l(exports):typeof define=="function"&&define.amd?define(["exports"],l):(f=typeof globalThis<"u"?globalThis:f||self,l(f.SziTileSource={}))})(this,function(f){"use strict";class l{static create=async(t,e)=>{const n=await this.fetchFileSize(t,e);return new l(t,n,e)};static fetchFileSize=async(t,e)=>{const n=e.headers?{...e.headers,Range:"bytes=0-255"}:{Range:"bytes=0-255"},i=await fetch(t,{headers:n,mode:e.mode,credentials:e.credentials});if(!i.ok)throw new Error(`Could not fetch size of ${t}, response status for request: ${i.status}`);const r=i.headers.get("Content-Range");if(!r)throw new Error(`Could not fetch size of ${t}, Content-Range header not included in response. Check that your server's CORS settings include it in Access-Control-Expose-Headers.`);const[s,a,c,d]=r.match(/bytes (\d+)\-(\d+)\/(\d+)/);if(!s||!d)throw new Error(`Could not fetch size of ${t}, Content-Range header didn't contain the length of the file`);return parseInt(d,10)};constructor(t,e,n){this.url=t,this.size=e,this.fetchOptions=n}fetchRange=async(t,e,n)=>{if(t<0||t>this.size)throw new Error(`Start of fetch range (${t}) out of bounds (0 - ${this.size})!`);if(e<0||e>this.size)throw new Error(`Start of fetch range (${t}) out of bounds (0 - ${this.size})!`);if(t>e)throw new Error(`Start of fetch range (${t}) greater than end (${e})!`);const i=`bytes=${t}-${e-1}`,r=this.fetchOptions.headers?{...this.fetchOptions.headers,Range:i}:{Range:i},s=await fetch(this.url,{headers:r,signal:n,mode:this.fetchOptions.mode,credentials:this.fetchOptions.credentials});if(!s.ok)throw new Error(`Couldn't fetch range ${t}:${e} of ${this.url} status: ${s.status}`);return await s.arrayBuffer()}}class h{constructor(t){this.buffer=t,this.view=new DataView(t),this.pos=0}checkBounds(t){if(t<0)throw new Error("Trying to move before start of buffer");if(t>this.buffer.byteLength)throw new Error("Trying to move after end of buffer")}readUint16(){const t=this.pos+2;this.checkBounds(t);const e=this.view.getUint16(this.pos,!0);return this.pos=t,e}readUint32(){const t=this.pos+4;this.checkBounds(t);const e=this.view.getUint32(this.pos,!0);return this.pos=t,e}readUint64(){const t=this.pos+8;this.checkBounds(t);const e=this.view.getBigUint64(this.pos,!0);if(this.pos=t,e>Number.MAX_SAFE_INTEGER)throw new Error("Only values upto 2^53 - 1 are supported!");return Number(e)}readUtf8String(t){const e=this.readUint8Array(t);return new TextDecoder().decode(e)}readUint8Array(t){const e=this.pos+t;this.checkBounds(e);const n=new Uint8Array(this.buffer,this.pos,t);return this.pos=e,n}skip(t){const e=this.pos+t;this.checkBounds(e),this.pos=e}}const m=4294967295,w=65535,S=w,g=22,U=20,O=1,b=101010256,D=117853008,R=101075792,C=33639248,L=67324752;function $(o,t,e){if(e.length>o.length)return-1;t=Math.min(t,o.length-e.length);for(let n=t;n>-1;n--){let i=!0;for(let r=0;r<e.length&&i;r++)o.at(n+r)!==e.at(r)&&(i=!1);if(i)return n}return-1}function v(o){const t=new Uint8Array(4);return new DataView(t.buffer).setUint32(0,b,!0),t}function A(o){const t=new Uint8Array(o),e=v();let n=o.byteLength-g;for(;n>=0;){const i=$(t,n,e);if(i===-1)throw new Error("Invalid SZI file, no valid End Of Central Directory Record found");const r=new h(o);if(r.skip(i),r.readUint32()!==b)throw new Error("Programming Error: End Of Central Directory Record has unexpected magic number");r.readUint16(),r.readUint16(),r.readUint16();const a=r.readUint16(),c=r.readUint32(),d=r.readUint32(),u=r.readUint16();if(r.pos+u===o.byteLength)return u>0&&r.readUtf8String(u),{totalEntries:a,centralDirectorySize:c,centralDirectoryOffset:d,startOfEocdInBuffer:i};n=i-1}if(n<0)throw new Error("Invalid SZI file, no End Of Central Directory Record found")}function I(o,t){const e=new h(o);if(e.skip(t),e.readUint32()!==D)throw new Error("Invalid SZI file: Zip64 End Of Central Directory Locator has unexpected magic number");e.readUint32();const i=e.readUint64();return e.readUint32(),{zip64EocdOffset:i}}function k(o,t){const e=new h(o);if(e.skip(t),e.readUint32()!==R)throw new Error("Invalid SZI file: Zip64 End Of Central Directory Record has unexpected magic number");const i=e.readUint64()+12;e.readUint16(),e.readUint16(),e.readUint32(),e.readUint32(),e.readUint64();const r=e.readUint64(),s=e.readUint64(),a=e.readUint64(),c=i-e.pos-t;return e.skip(c),{totalEntries:r,centralDirectorySize:s,centralDirectoryOffset:a}}function x(o,t,e){let{compressedSize:n,uncompressedSize:i,diskNumberStart:r,relativeOffsetOfLocalHeader:s}=e;const a=o.pos;for(;o.pos-a<t;){const c=o.readUint16(),d=o.readUint16();c===O?(i===m&&(i=o.readUint64()),n===m&&(n=o.readUint64()),s===m&&(s=o.readUint64()),r===w&&(r=o.readUint32())):o.skip(d)}return{compressedSize:n,uncompressedSize:i,diskNumberStart:r,relativeOffsetOfLocalHeader:s}}function N(o,t){const e=new h(o),n=[];for(let i=0;i<t;i++){if(e.readUint32()!==C)throw new Error(`Invalid SZI file: Central Directory Header ${i} has unexpected magic number`);e.readUint16(),e.readUint16(),e.readUint16(),e.readUint16(),e.readUint16(),e.readUint16(),e.readUint32();const s=e.readUint32(),a=e.readUint32(),c=e.readUint16(),d=e.readUint16(),u=e.readUint16(),T=e.readUint16();e.readUint16(),e.readUint32();const Z=e.readUint32(),y=e.readUtf8String(c);if(s!==a)throw new Error(`Invalid SZI file: compressedSize: ${s} and uncompressedSize: ${a} don't match for ${y}!`);const E=x(e,d,{compressedSize:s,uncompressedSize:a,diskNumberStart:T,relativeOffsetOfLocalHeader:Z});e.readUtf8String(u),n.push({uncompressedSize:E.uncompressedSize,relativeOffsetOfLocalHeader:E.relativeOffsetOfLocalHeader,filename:y})}return n}async function B(o){const t=Math.max(0,o.size-(U+g+S)),e=await o.fetchRange(t,o.size),{totalEntries:n,centralDirectoryOffset:i,centralDirectorySize:r,startOfEocdInBuffer:s}=A(e);if(n===w||i===m||r===m){const c=s-U,d=I(e,c),u=await o.fetchRange(d.zip64EocdOffset,t+c);return k(u,0)}else return{totalEntries:n,centralDirectoryOffset:i,centralDirectorySize:r}}function F(o,t){const e=new Map,n=o.toSorted((r,s)=>s.relativeOffsetOfLocalHeader-r.relativeOffsetOfLocalHeader);let i=t;for(const r of n){const s=r.relativeOffsetOfLocalHeader;e.set(r.filename,{start:s,maxEnd:i,bodyLength:r.uncompressedSize}),i=s}return e}async function H(o){const{totalEntries:t,centralDirectoryOffset:e,centralDirectorySize:n}=await B(o),i=await o.fetchRange(e,e+n),r=N(i,t);return F(r,e)}class p{static create=async t=>{const e=await H(t);return new p(t,e)};constructor(t,e){this.sziFile=t,this.contents=e}fetchFileBody=async(t,e)=>{const n=this.contents.get(t);if(!n)throw new Error(`${t} is not present inside this .szi file`);const i=await this.sziFile.fetchRange(n.start,n.maxEnd,e),r=new h(i,0);if(r.readUint32()!==L)throw new Error(`Invalid SZI file: Local Header for ${t} has unexpected magic number`);r.readUint16(),r.readUint16(),r.readUint16(),r.readUint16(),r.readUint16(),r.readUint32(),r.readUint32(),r.readUint32();const a=r.readUint16(),c=r.readUint16(),d=r.readUtf8String(a);if(d!==t)throw new Error(`Trying to read ${t} but actually got ${d}`);return r.skip(c),r.readUint8Array(n.bodyLength)};dziFilename=()=>{let t="";for(const e of this.contents.keys())if(e.match(/^(.*)\.dzi$/)){if(t)throw new Error("Multiple .dzi files found in .szi!");t=e}if(!t)throw new Error("No dzi file found in .szi!");return t};tilesDirectory=()=>this.dziFilename().replace(/\.dzi$/,"_files/")}const z=o=>{class t extends o.DziTileSource{static createSziTileSource=async(n,i={})=>{if(i&&i.mode==="no-cors")throw new Error("'no-cors' mode is not supported, as Range headers don't work with it");const r=await l.create(n,i),s=await p.create(r),a=await this.readOptionsFromDziXml(s);return new t(s,a)};static async readOptionsFromDziXml(n){const i=n.dziFilename(),r=await n.fetchFileBody(i),s=new TextDecoder().decode(r),a=o.parseXml(s);return o.DziTileSource.prototype.configure(a,i,"")}constructor(n,i){super(i),this.remoteSziReader=n}downloadTileStart=n=>{const i=new Image;i.onload=function(){r(),n.finish(i,n.userData.request,null)},i.onabort=i.onerror=function(){r(),n.finish(null,n.userData.request,"Image load aborted.")};const r=()=>{i.onload=i.onerror=i.onabort=null};n.userData.image=i,n.userData.abortController=new AbortController,this.remoteSziReader.fetchFileBody(n.src,n.userData.abortController.signal).then(s=>{const a=new Blob([s]);a.size===0?(r(),n.finish(null,null,"Empty image!")):i.src=(window.URL||window.webkitURL).createObjectURL(a)},s=>{r(),n.finish(null,null,"Download failed: "+s.message)})};downloadTileAbort=n=>{const i=n.userData.abortController;i&&i.abort();const r=n.userData.image;r&&(r.onload=r.onerror=r.onabort=null)}}o.SziTileSource=t};(function(o,t){typeof f>"u"||typeof o.OpenSeadragon<"u"&&t(o.OpenSeadragon)})(typeof window<"u"?window:void 0,z),f.enableSziTileSource=z,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"})});