@etu-wiki/sharp-iiif-shims 0.1.9 → 0.1.11

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.
Files changed (2) hide show
  1. package/dist/index.mjs +1 -1
  2. package/package.json +2 -2
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import A from"sharp";var a="[1-9][0-9]*",te="[0-9]*",M="(?=.*[1-9])\\d+(\\.\\d+)?",U="\\d+(\\.\\d+)?",G={jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",webp:"image/webp",tif:"image/tiff",tiff:"image/tiff",gif:"image/gif",jp2:"image/jp2",pdf:"application/pdf"},q={version:["1.0","1.1","2.0","2.1","3.0"],level:["0","1","2"],region:["full","square",`${te},${te},${a},${a}`,`pct:${U},${U},${M},${M}`],rotation:`!?${U}`,quality:["color","gray","bitonal","default","native","grey"],format:["jpg","png","webp","tif","gif","jp2","pdf"],size:[""]},he={1:["full",`${a},`,`,${a}`,`pct:${M}`,`${a},${a}`,`!${a},${a}`],1.1:["full",`${a},`,`,${a}`,`pct:${M}`,`${a},${a}`,`!${a},${a}`],2:["full",`${a},`,`,${a}`,`pct:${M}`,`${a},${a}`,`!${a},${a}`],2.1:["full","max",`${a},`,`,${a}`,`pct:${M}`,`${a},${a}`,`!${a},${a}`],3:["max",`${a},`,`,${a}`,`pct:${M}`,`${a},${a}`,`!${a},${a}`,"\\^max",`\\^${a},`,`\\^,${a}`,`\\^pct:${M}`,`\\^${a},${a}`,`\\^!${a},${a}`]},j=/^pct:([\d,]+)/,ie=class{constructor(s,i,t,e,r,o,n){this.version=s,this.level=i,this.maxArea=t,this.maxWidth=e,this.maxHeight=r,this.tileWidth=o,this.tileHeight=n,this.validate("version",s),this.validate("level",i),q.size=he[Number(s)]}validator(s){let i=q[s];return i instanceof Array&&(i=i.join("|")),new RegExp("^("+i+")$")}validate(s,i){if(!this.validator(s).test(i))throw Error(`invalid IIIF url ${s}: ${i}`);return!0}normalizeRegionParams(s,i){if(this.validate("region",s),s==="full")return null;if(s==="square")return this._regionSquare(i);if(j.test(s))return this._regionPct(s.match(j)[1],i);{let t=s.split(",").map(e=>Number(e));return this._regionXYWH(t,i)}}_regionSquare(s){let i,t,e=s.width,r=s.height;if(e!==r){let o=Math.min(e,r),n=Math.abs(Math.floor((e-r)/2));return e>r?(i=n,t=0):(i=0,t=n),this._regionXYWH([i,t,o,o],s)}return null}_regionPct(s,i){let t=s.split(",").map((e,r)=>{let o=Number(e)/100;return r===0||r===2?Math.ceil(i.width*o):r===1||r===3?Math.ceil(i.height*o):null});return this._regionXYWH(t,i)}_regionXYWH(s,i){let t=i.width,e=i.height,[r,o,n,l]=s;if(r+n>t&&(n=t-r),o+l>e&&(l=e-o),n<=0)throw Error(`invalid IIIF width ${n}`);if(l<=0)throw Error(`invalid IIIF height ${l}`);return{x:r,y:o,w:n,h:l}}normalizeSizeParams(s,i){let t=s,e=i.width,r=i.height;if(!i||!e&&!r)throw Error(`invalid region dimensions: ${JSON.stringify(i,null,2)}`);this.validate("size",t);let o=!1;t.charAt(0)==="^"&&(o=!0,t=t.substring(1));let n=null;if(t==="full"||(t==="max"?n=this._sizeMaxScale(i):j.test(t)?n=this._sizePctScale(t.match(j)[1]):t.charAt(0)==="!"&&(t=t.substring(1),n=this._sizeBangScale(t,o,i)),n===1))return null;if(n){let l=Math.ceil(e*n),h=Math.ceil(r*n);return this._sizeWH(`${l},${h}`,o,i)}else return this._sizeWH(t,o,i)}_sizeBangScale(s,i,t){let e=t.width,r=t.height,[o,n]=s.split(",").map(h=>h===""?null:Number(h)),l=Math.min(o/e,n/r);if(o>e&&n>r&&!i)throw Error("should not upscale without ^");return l}_sizeMaxScale(s){let i=s.width,t=s.height,e=1;return this.maxArea&&this.maxArea<i*t&&(e=Math.sqrt(this.maxArea/(i*t))),this.maxWidth&&this.maxWidth<i&&(e=Math.min(e,this.maxWidth/i)),this.maxHeight&&this.maxHeight<t&&(e=Math.min(e,this.maxHeight/t)),e}_sizePctScale(s){return Number(s)/100}_sizeWH(s,i,t){let e=t.width,r=t.height,[o,n]=s.split(",").map(l=>l===""?null:Number(l));if(o?n||(n=Math.ceil(r*o/e),n=n===0?1:n):(o=Math.ceil(e*n/r),o=o===0?1:o),(o>e||n>r)&&!i)throw Error("should not upscale without ^");return{width:o,height:n}}normalizeRotationParams(s){this.validate("rotation",s);let i=!1;if(s==="0")return null;s[0]==="!"&&(i=!0);let t=Number(s.replace(/^!/,""));return{isMirror:i,degree:t}}normalizeQualityParams(s){return this.validate("quality",s),s==="native"||s==="default"?null:s}normalizeFormatParams(s,i){if((this.version==="1.0"||this.version==="1.1"||this.version==="2.0"||this.version==="2.1")&&!s)return"png";this.validate("format",s);let t=G[s],e=G[i];return t===e?null:s}getContentType(s){return G[s]}generateImageInfoTemp(s,i){let t={},e={};t.info=e;let r=this.version;return r==="1.0"?(e.identifier=s,e.width=i.width,e.height=i.height,e.scale_factors=this.factors(i),e.tile_width=this.tileWidth,e.tile_height=this.tileHeight,e.formats=q.format,e.qualities=q.quality,e.profile=this.uriPattern("compliance"),t.contentType="application/json",t.body=JSON.stringify(e)):(r==="1.1"?(e["@context"]=this.uriPattern("context"),e["@id"]=s,e.width=i.width,e.height=i.height,e.scale_factors=this.factors(i),e.tile_width=this.tileWidth,e.tile_height=this.tileHeight,e.formats=q.format,e.qualities=q.quality,e.profile=this.uriPattern("compliance")):r==="2.0"||r==="2.1"?(e["@context"]=this.uriPattern("context"),e["@id"]=s,e.protocol="http://iiif.io/api/image",e.width=i.width,e.height=i.height,this.level==="0"?e.sizes=this.sizes(i):e.tiles=[{scaleFactors:this.factors(i),width:this.tileWidth,height:this.tileHeight}],e.profile=[this.uriPattern("compliance")]):r==="3.0"&&(e["@context"]=[this.uriPattern("context")],e.id=s,e.type="ImageService3",e.protocol="http://iiif.io/api/image",e.width=i.width,e.height=i.height,this.level==="0"?e.sizes=this.sizes(i):e.tiles=[{scaleFactors:this.factors(i),width:this.tileWidth,height:this.tileHeight}],e.profile=this.uriPattern("compliance")),t.contentType="application/ld+json"),t}factors(s){let i=1,t=[];for(;this.tileWidth*i<=s.width||this.tileHeight*i<=s.height;)t.push(i),i*=2;return t.length===0&&t.push(1),t}uriPattern(s){let i="",t="";return this.version==="1.0"?i=`http://library.stanford.edu/iiif/image-api/compliance.html#level${this.level}`:this.version==="1.1"?(i=`http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level${this.level}`,t="http://library.stanford.edu/iiif/image-api/1.1/context.json"):this.version==="2.0"||this.version==="2.1"?(i=`http://iiif.io/api/image/2/level${this.level}.json`,t="http://iiif.io/api/image/2/context.json"):this.version==="3.0"&&(i=`level${this.level}`,t="http://iiif.io/api/image/3/context.json"),s==="compliance"?i:s==="context"?t:""}sizes(s){return[{width:s.width,height:s.height}]}};import{addDecoder as ce,BaseDecoder as ge,fromCustomClient as re,fromUrl as ue,BaseClient as oe,BaseResponse as ne}from"geotiff";var fe=1e8,pe=1e4,me=1e4,de=512,we=512,ye={2:["baseUriRedirect","canonicalLinkHeader","cors","jsonldMediaType","mirroring","profileLinkHeader","regionByPct","regionByPx","rotationArbitrary","rotationBy90s","sizeAboveFull","sizeByWhListed","sizeByForcedWh","sizeByH","sizeByPct","sizeByW","sizeByWh"],2.1:["baseUriRedirect","canonicalLinkHeader","cors","jsonldMediaType","mirroring","profileLinkHeader","regionByPct","regionByPx","regionSquare","rotationArbitrary","rotationBy90s","sizeAboveFull","sizeByConfinedWh","sizeByDistortedWh","sizeByH","sizeByPct","sizeByW","sizeByWh","sizeByWhListed","sizeByForcedWh"],3:["baseUriRedirect","canonicalLinkHeader","cors","jsonldMediaType","mirroring","profileLinkHeader","regionByPct","regionByPx","regionSquare","rotationArbitrary","rotationBy90s","sizeByConfinedWh","sizeByH","sizeByPct","sizeByW","sizeByWh","sizeUpscaling"]},Y=class extends ge{async decode(i,t){let e=Array.isArray(i.BitsPerSample)?i.BitsPerSample.length:i.SamplesPerPixel||4,r=A(t,{sequentialRead:!0}),n=(await r.metadata()).channels||4;e===4&&n<4&&r.ensureAlpha?r=r.ensureAlpha():e===3&&n>3&&r.removeAlpha&&(r=r.removeAlpha());let{data:l,info:h}=await r.raw().toBuffer({resolveWithObject:!0});if(h.channels!==e){let m=h.width*h.height,c=Buffer.alloc(m*e),g=l;for(let u=0;u<m;u+=1){let w=u*h.channels,z=u*e;for(let f=0;f<e;f+=1)f<h.channels?c[z+f]=g[w+f]:c[z+f]=f===3?255:0}return c.buffer.slice(c.byteOffset,c.byteOffset+c.byteLength)}return l.buffer.slice(l.byteOffset,l.byteOffset+l.byteLength)}};ce(50001,()=>Promise.resolve(Y));var K=class extends ne{constructor(i){super(),this.result=i}get ok(){return this.result.res.status>=200&&this.result.res.status<300}get status(){return this.result.res.status}getHeader(i){return this.result.res.headers[i.toLowerCase()]}getData(){return Buffer.isBuffer(this.result.content)?this.result.content.buffer.slice(this.result.content.byteOffset,this.result.content.byteOffset+this.result.content.byteLength):this.result.content}},Q=class extends oe{constructor(i,t){super(i),this.objectKey=i,this.ossClient=t}async request({headers:i={}}={}){let t=await this.ossClient.get(this.objectKey,{headers:i,timeout:3e4});return new K(t)}};async function $e(s,i){let t=new Q(s,i);return re(t)}var ze=new Map,Pe=new Map,O=new Map,E=new Map,J=class extends ne{constructor(i,t){super(),this.response=i,this.arrayBuffer=t}get ok(){return this.response.ok}get status(){return this.response.status}getHeader(i){return this.response.headers.get(i)||""}getData(){return this.arrayBuffer}},Z=class extends oe{constructor(i,t,e,r){super(i),this.ipfsUrl=i,this.verifiedFetch=t,this.peerCache=e,this.inFlightRequests=r}extractCID(i){let t=i.match(/(?:ipfs:\/\/|\/ipfs\/)([a-zA-Z0-9]+)/);return t?t[1]:null}async request({headers:i={}}={}){let t=this.extractCID(this.ipfsUrl),e=t?this.peerCache?.get(t):null,r=e==="discovering",o=e&&Array.isArray(e)&&e.length>0,n=e&&Array.isArray(e),l=n?3e4:6e4,h=new AbortController,m=setTimeout(()=>{console.log("[IPFSClient] Request timeout, aborting..."),h.abort()},l);try{let c={headers:i,signal:h.signal,session:!1};t&&(n?console.log(`[IPFSClient] Using fast path for previously accessed ${t}`):(console.log(`[IPFSClient] First fetch for ${t}, using HTTP gateways...`),this.peerCache&&this.peerCache.set(t,"discovering")));let g=await this.verifiedFetch(this.ipfsUrl,c);if(!g.ok)throw new Error(`Failed to fetch from IPFS: ${g.status} ${g.statusText}`);let u=await g.arrayBuffer();return clearTimeout(m),t&&this.peerCache&&this.peerCache.get(t)==="discovering"&&(this.peerCache.set(t,[]),console.log(`[IPFSClient] Marked ${t} as discovered`)),new J(g,u)}catch(c){throw clearTimeout(m),t&&this.peerCache&&this.peerCache.get(t)==="discovering"&&this.peerCache.delete(t),console.error("[IPFSClient] Error during request:",c),c instanceof Error&&(console.error("[IPFSClient] Error name:",c.name),console.error("[IPFSClient] Error message:",c.message),console.error("[IPFSClient] Error stack:",c.stack)),c&&typeof c=="object"&&"errors"in c&&console.error("[IPFSClient] AggregateError details:",c.errors),c}}};async function se(s,i,t){let e=`${t}:${i}`,r=E.get(e);if(r)return r instanceof Promise?await r:r;let o=s.getImage(i);E.set(e,o);try{let n=await o;return E.set(e,n),n}catch(n){throw E.delete(e),n}}async function ve(s,i){let t=O.get(s);if(t)return t instanceof Promise?(console.log(`[fromIPFS] Waiting for in-flight GeoTIFF creation for ${s}`),await t):(console.log(`[fromIPFS] Using cached GeoTIFF client for ${s}`),t);console.log(`[fromIPFS] Creating new GeoTIFF client for ${s}`);let e=(async()=>{let r=new Z(s,i,ze,Pe),o=await re(r,{cacheSize:128*1024*1024,blockSize:65536});return O.set(s,o),o})();O.set(s,e);try{return await e}catch(r){throw O.delete(s),r}}var V=class extends ie{constructor(i,t,e=!1,r=fe,o=pe,n=me,l=de,h=we){super(i,t,r,o,n,l,h),this.enableHD=e}regionImpl(i,t){i&&(t=t.extract({left:i.x,top:i.y,width:i.w,height:i.h}))}sizeImpl(i,t){i&&(t=t.resize({...i,fit:"fill"}))}rotationImpl(i,t){i&&(i.isMirror&&(t=t.flop()),t=t.rotate(i.degree))}qualityFormatImpl(i,t,e,r,o){i&&(i==="color"?e=e.toColorspace("srgb"):i==="gray"||i==="grey"?e=e.grayscale():i==="bitonal"&&(e=e.threshold())),t&&(e=e.toFormat(t)),r==="png"&&(o.paletteBitDepth===1||o.space==="b-w")&&(e=e.toColorspace("b-w").png({colors:2}))}async generateImageTile(i,t,e){let r=i.split("/"),o=r.pop(),n=o.split(".")[0],l=o.split(".")[1],h=r.pop(),m=r.pop(),c=r.pop(),g=r.pop(),u={width:t.width,height:t.height},w=super.normalizeRegionParams(c,u),z=super.normalizeSizeParams(m,{width:w?w.w:u.width,height:w?w.h:u.height}),{x:f,y:v,w:I,h:P}=w??{x:0,y:0,w:u.width,h:u.height},{width:b,height:S}=z;console.log(`Attempting to fetch from URL: ${e}`);let x,y;typeof e=="string"?(console.log("Using standard HTTP fetch"),x=await ue(e),y=e):typeof g=="string"&&g.startsWith("bafy")?(console.log("Detected CID id, using fromIPFS"),y=`ipfs://${g}`,x=await ve(y,e)):(x=await $e(g,e),y=`oss://${g}`);let p=await se(x,0,y);console.log(`Source dimensions: ${p.getWidth()} x ${p.getHeight()}`),console.log(`Extracting region: x=${f}, y=${v}, w=${I}, h=${P}`),console.log(`Output size: ${b} x ${S}`);let C=await x.getImageCount();console.log(`Total images (including overviews): ${C}`);let H=p.getSamplesPerPixel(),F;H>=3?(F=[0,1,2],H>=4&&F.push(3)):F=[0],console.log("Using automatic overview selection based on resolution...");let T=Math.max(I/b,P/S),W=p,$=1;for(let R=0;R<C;R++){let _=await se(x,R,y),X=p.getWidth()/_.getWidth();X<=T&&X>$&&($=X,W=_)}console.log(`Selected overview with scale: ${$.toFixed(2)}x`),console.log(`Overview dimensions: ${W.getWidth()} x ${W.getHeight()}`);let B=[Math.floor(f/$),Math.floor(v/$),Math.floor((f+I)/$),Math.floor((v+P)/$)],d;try{d=await W.readRasters({window:B,width:b,height:S,samples:F,interleave:!0,resampleMethod:"bilinear"})}catch(R){console.log(`Failed to read from overview, falling back to main image: ${R}`);let _=[f,v,f+I,v+P];d=await p.readRasters({window:_,width:b,height:S,samples:F,interleave:!0,resampleMethod:"bilinear"})}let k=F.length,L=Buffer.from(d.buffer,d.byteOffset,d.byteLength),D=A(L,{raw:{width:b,height:S,channels:k}}),ae=super.normalizeRotationParams(h);this.rotationImpl(ae,D);let le=super.normalizeQualityParams(n),ee=super.normalizeFormatParams(l,t.format);this.qualityFormatImpl(le,ee,D,l,t);let N={};return N.body=D,N.contentType=super.getContentType(ee),N}iiifTransform(i,t){let e=this.enableHD?A({limitInputPixels:!1,sequentialRead:!0}):A(),r=i.split("/"),o=r.pop(),n=o.split(".")[0],l=o.split(".")[1],h=r.pop(),m=r.pop(),c=r.pop(),g=!1,u=e,w={width:t.width,height:t.height};t&&t.orientation&&(g=!0,u=u.rotate(),t.orientation>=5&&(w={width:t.height,height:t.width}));let z=super.normalizeRegionParams(c,w);this.regionImpl(z,u);let f=super.normalizeSizeParams(m,{width:z?z.w:w.width,height:z?z.h:w.height});this.sizeImpl(f,u);let v=super.normalizeRotationParams(h);this.rotationImpl(v,u);let I=super.normalizeQualityParams(n),P=super.normalizeFormatParams(l,t.format);return this.qualityFormatImpl(I,P,u,l,t),z||f||v||I||P||g?u:(console.log("skip iiif transform"),null)}async generateIiifImage(i,t,e){let r=i.split("/"),o=r.pop(),n=o.split(".")[0],l=o.split(".")[1],h=r.pop(),m=r.pop(),c=r.pop(),g=super.normalizeRegionParams(c,e),u=super.normalizeSizeParams(m,{width:g?g.w:e.width,height:g?g.h:e.height}),w=super.normalizeRotationParams(h),z=super.normalizeQualityParams(n),f=super.normalizeFormatParams(l,e.format),{x:v,y:I,w:P,h:b}=g||{x:0,y:0,w:e.width,h:e.height},{width:S,height:x}=u||{width:e.width,height:e.height},y=0,p;if(e.pages&&e.pages>1){let H=S/P,F=x/b,T=Math.max(H,F);if(T>=.95)console.log("Pyramid optimization: using full resolution page (scale \u2248 1.0)"),y=0;else{y=e.pages-1;let $=Math.pow(2,e.pages-1),B=e.width/$,d=e.height/$;for(;y>0;){let k=P*(B/e.width),L=b*(d/e.height);if(k>=S*1.1&&L>=x*1.1)break;y--,B*=2,d*=2}console.log(`Pyramid optimization: selected page ${y}/${e.pages-1} (scale: ${T.toFixed(2)}x, target: ${S}x${x})`)}let W=this.enableHD?{limitInputPixels:!1,page:y,sequentialRead:!0,failOn:"none"}:{page:y,sequentialRead:!0,failOn:"none"};if(p=A(t,W),g&&y>0){let $=await p.metadata(),B=$.width/e.width,d={x:Math.floor(v*B),y:Math.floor(I*B),w:Math.floor(P*B),h:Math.floor(b*B)};d.w=Math.min(d.w,$.width-d.x),d.h=Math.min(d.h,$.height-d.y),this.regionImpl(d,p)}else this.regionImpl(g,p)}else{let H=this.enableHD?{limitInputPixels:!1,sequentialRead:!0,failOn:"none"}:{sequentialRead:!0,failOn:"none"};p=A(t,H),this.regionImpl(g,p)}this.sizeImpl(u,p),this.rotationImpl(w,p),this.qualityFormatImpl(z,f,p,l,e);let C={};return C.body=p,C.contentType=super.getContentType(f),C}generateImageInfo(i,t,e=""){let r=this.version,o=this.level,n={width:t.width,height:t.height};t&&t.orientation&&t.orientation>=5&&(console.log(t.orientation),n={width:t.height,height:t.width});let l=super.generateImageInfoTemp(i,n),h=l.info;if((r==="2.0"||r==="2.1")&&(h.profile=[super.uriPattern("compliance")],o==="2")){let m={};m.formats=["jpg","png","webp","jp2","pdf","tif"],m.qualities=["color","gray","bitonal","default","native","grey"],m.supports=ye[Number(r)],h.profile.push(m)}return r==="3.0"&&e&&(h.extraFormats=[e],h.preferredFormats=[e]),e&&(h.formats=[e]),l}};export{V as default};
1
+ import W from"sharp";var z="[1-9][0-9]*",te="[0-9]*",_="(?=.*[1-9])\\d+(\\.\\d+)?",U="\\d+(\\.\\d+)?",G={jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",webp:"image/webp",tif:"image/tiff",tiff:"image/tiff",gif:"image/gif",jp2:"image/jp2",pdf:"application/pdf"},A={version:["1.0","1.1","2.0","2.1","3.0"],level:["0","1","2"],region:["full","square",`${te},${te},${z},${z}`,`pct:${U},${U},${_},${_}`],rotation:`!?${U}`,quality:["color","gray","bitonal","default","native","grey"],format:["jpg","png","webp","tif","gif","jp2","pdf"],size:["^full$",`^${z},$`,`^,${z}$`,`^pct:${_}$`,`^${z},${z}$`,`^!${z},${z}$`,"^max$","^\\^max$",`^\\^${z},$`,`^\\^,${z}$`,`^\\^pct:${_}$`,`^\\^${z},${z}$`,`^\\^!${z},${z}$`]},j=/^pct:([\d,]+)/,ie=class{constructor(r,t,e,i,s,o){this.level=r,this.maxArea=t,this.maxWidth=e,this.maxHeight=i,this.tileWidth=s,this.tileHeight=o,this.validate("level",r)}validate(r,t){let e=A[r];if(e instanceof Array&&(e=e.join("|")),!new RegExp("^("+e+")$").test(t))throw Error(`invalid IIIF url ${r}: ${t}`);return!0}normalizeRegionParams(r,t){if(this.validate("region",r),r==="full")return null;if(r==="square")return this._regionSquare(t);if(j.test(r))return this._regionPct(r.match(j)[1],t);{let e=r.split(",").map(i=>Number(i));return this._regionXYWH(e,t)}}_regionSquare(r){let t,e,i=r.width,s=r.height;if(i!==s){let o=Math.min(i,s),n=Math.abs(Math.floor((i-s)/2));return i>s?(t=n,e=0):(t=0,e=n),this._regionXYWH([t,e,o,o],r)}return null}_regionPct(r,t){let e=r.split(",").map((i,s)=>{let o=Number(i)/100;return s===0||s===2?Math.ceil(t.width*o):s===1||s===3?Math.ceil(t.height*o):null});return this._regionXYWH(e,t)}_regionXYWH(r,t){let e=t.width,i=t.height,[s,o,n,a]=r;if(s+n>e&&(n=e-s),o+a>i&&(a=i-o),n<=0)throw Error(`invalid IIIF width ${n}`);if(a<=0)throw Error(`invalid IIIF height ${a}`);return{x:s,y:o,w:n,h:a}}normalizeSizeParams(r,t){let e=r,i=t.width,s=t.height;if(!t||!i&&!s)throw Error(`invalid region dimensions: ${JSON.stringify(t,null,2)}`);this.validate("size",e);let o=!1;e.charAt(0)==="^"&&(o=!0,e=e.substring(1));let n=null;if(e==="full"||(e==="max"?n=this._sizeMaxScale(t):j.test(e)?n=this._sizePctScale(e.match(j)[1]):e.charAt(0)==="!"&&(e=e.substring(1),n=this._sizeBangScale(e,o,t)),n===1))return null;if(n){let a=Math.ceil(i*n),l=Math.ceil(s*n);return this._sizeWH(`${a},${l}`,o,t)}else return this._sizeWH(e,o,t)}_sizeBangScale(r,t,e){let i=e.width,s=e.height,[o,n]=r.split(",").map(l=>l===""?null:Number(l)),a=Math.min(o/i,n/s);if(o>i&&n>s&&!t)throw Error("should not upscale without ^");return a}_sizeMaxScale(r){let t=r.width,e=r.height,i=1;return this.maxArea&&this.maxArea<t*e&&(i=Math.sqrt(this.maxArea/(t*e))),this.maxWidth&&this.maxWidth<t&&(i=Math.min(i,this.maxWidth/t)),this.maxHeight&&this.maxHeight<e&&(i=Math.min(i,this.maxHeight/e)),i}_sizePctScale(r){return Number(r)/100}_sizeWH(r,t,e){let i=e.width,s=e.height,[o,n]=r.split(",").map(a=>a===""?null:Number(a));if(o?n||(n=Math.ceil(s*o/i),n=n===0?1:n):(o=Math.ceil(i*n/s),o=o===0?1:o),(o>i||n>s)&&!t)throw Error("should not upscale without ^");return{width:o,height:n}}normalizeRotationParams(r){this.validate("rotation",r);let t=!1;if(r==="0")return null;r[0]==="!"&&(t=!0);let e=Number(r.replace(/^!/,""));return{isMirror:t,degree:e}}normalizeQualityParams(r){return this.validate("quality",r),r==="native"||r==="default"?null:r}normalizeFormatParams(r,t){this.validate("format",r);let e=G[r],i=G[t];return e===i?null:r}getContentType(r){return G[r]}generateImageInfoTemp(r,t,e){this.validate("version",e);let i={},s={};return i.info=s,e==="1.0"?(s.identifier=r,s.width=t.width,s.height=t.height,s.scale_factors=this.factors(t),s.tile_width=this.tileWidth,s.tile_height=this.tileHeight,s.formats=A.format,s.qualities=A.quality,s.profile=this.uriPattern("compliance",e),i.contentType="application/json",i.body=JSON.stringify(s)):(e==="1.1"?(s["@context"]=this.uriPattern("context",e),s["@id"]=r,s.width=t.width,s.height=t.height,s.scale_factors=this.factors(t),s.tile_width=this.tileWidth,s.tile_height=this.tileHeight,s.formats=A.format,s.qualities=A.quality,s.profile=this.uriPattern("compliance",e)):e==="2.0"||e==="2.1"?(s["@context"]=this.uriPattern("context",e),s["@id"]=r,s.protocol="http://iiif.io/api/image",s.width=t.width,s.height=t.height,this.level==="0"?s.sizes=this.sizes(t):s.tiles=[{scaleFactors:this.factors(t),width:this.tileWidth,height:this.tileHeight}],s.profile=[this.uriPattern("compliance",e)]):e==="3.0"&&(s["@context"]=[this.uriPattern("context",e)],s.id=r,s.type="ImageService3",s.protocol="http://iiif.io/api/image",s.width=t.width,s.height=t.height,this.level==="0"?s.sizes=this.sizes(t):s.tiles=[{scaleFactors:this.factors(t),width:this.tileWidth,height:this.tileHeight}],s.profile=this.uriPattern("compliance",e)),i.contentType="application/ld+json"),i}factors(r){let t=1,e=[];for(;this.tileWidth*t<=r.width||this.tileHeight*t<=r.height;)e.push(t),t*=2;return e.length===0&&e.push(1),e}uriPattern(r,t){let e="",i="";return t==="1.0"?e=`http://library.stanford.edu/iiif/image-api/compliance.html#level${this.level}`:t==="1.1"?(e=`http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level${this.level}`,i="http://library.stanford.edu/iiif/image-api/1.1/context.json"):t==="2.0"||t==="2.1"?(e=`http://iiif.io/api/image/2/level${this.level}.json`,i="http://iiif.io/api/image/2/context.json"):t==="3.0"&&(e=`level${this.level}`,i="http://iiif.io/api/image/3/context.json"),r==="compliance"?e:r==="context"?i:""}sizes(r){return[{width:r.width,height:r.height}]}};import{addDecoder as he,BaseDecoder as ce,fromCustomClient as re,fromUrl as ge,BaseClient as oe,BaseResponse as ne}from"geotiff";var ue=1e8,fe=1e4,pe=1e4,me=512,de=512,we={2:["baseUriRedirect","canonicalLinkHeader","cors","jsonldMediaType","mirroring","profileLinkHeader","regionByPct","regionByPx","rotationArbitrary","rotationBy90s","sizeAboveFull","sizeByWhListed","sizeByForcedWh","sizeByH","sizeByPct","sizeByW","sizeByWh"],2.1:["baseUriRedirect","canonicalLinkHeader","cors","jsonldMediaType","mirroring","profileLinkHeader","regionByPct","regionByPx","regionSquare","rotationArbitrary","rotationBy90s","sizeAboveFull","sizeByConfinedWh","sizeByDistortedWh","sizeByH","sizeByPct","sizeByW","sizeByWh","sizeByWhListed","sizeByForcedWh"],3:["baseUriRedirect","canonicalLinkHeader","cors","jsonldMediaType","mirroring","profileLinkHeader","regionByPct","regionByPx","regionSquare","rotationArbitrary","rotationBy90s","sizeByConfinedWh","sizeByH","sizeByPct","sizeByW","sizeByWh","sizeUpscaling"]},Y=class extends ce{async decode(t,e){let i=Array.isArray(t.BitsPerSample)?t.BitsPerSample.length:t.SamplesPerPixel||4,s=W(e,{sequentialRead:!0}),n=(await s.metadata()).channels||4;i===4&&n<4&&s.ensureAlpha?s=s.ensureAlpha():i===3&&n>3&&s.removeAlpha&&(s=s.removeAlpha());let{data:a,info:l}=await s.raw().toBuffer({resolveWithObject:!0});if(l.channels!==i){let p=l.width*l.height,h=Buffer.alloc(p*i),c=a;for(let g=0;g<p;g+=1){let d=g*l.channels,P=g*i;for(let u=0;u<i;u+=1)u<l.channels?h[P+u]=c[d+u]:h[P+u]=u===3?255:0}return h.buffer.slice(h.byteOffset,h.byteOffset+h.byteLength)}return a.buffer.slice(a.byteOffset,a.byteOffset+a.byteLength)}};he(50001,()=>Promise.resolve(Y));var K=class extends ne{constructor(t){super(),this.result=t}get ok(){return this.result.res.status>=200&&this.result.res.status<300}get status(){return this.result.res.status}getHeader(t){return this.result.res.headers[t.toLowerCase()]}getData(){return Buffer.isBuffer(this.result.content)?this.result.content.buffer.slice(this.result.content.byteOffset,this.result.content.byteOffset+this.result.content.byteLength):this.result.content}},Q=class extends oe{constructor(t,e){super(t),this.objectKey=t,this.ossClient=e}async request({headers:t={}}={}){let e=await this.ossClient.get(this.objectKey,{headers:t,timeout:3e4});return new K(e)}};async function ye(r,t){let e=new Q(r,t);return re(e)}var ze=new Map,Pe=new Map,O=new Map,E=new Map,J=class extends ne{constructor(t,e){super(),this.response=t,this.arrayBuffer=e}get ok(){return this.response.ok}get status(){return this.response.status}getHeader(t){return this.response.headers.get(t)||""}getData(){return this.arrayBuffer}},Z=class extends oe{constructor(t,e,i,s){super(t),this.ipfsUrl=t,this.verifiedFetch=e,this.peerCache=i,this.inFlightRequests=s}extractCID(t){let e=t.match(/(?:ipfs:\/\/|\/ipfs\/)([a-zA-Z0-9]+)/);return e?e[1]:null}async request({headers:t={}}={}){let e=this.extractCID(this.ipfsUrl),i=e?this.peerCache?.get(e):null,s=i==="discovering",o=i&&Array.isArray(i)&&i.length>0,n=i&&Array.isArray(i),a=n?3e4:6e4,l=new AbortController,p=setTimeout(()=>{console.log("[IPFSClient] Request timeout, aborting..."),l.abort()},a);try{let h={headers:t,signal:l.signal,session:!1};e&&(n?console.log(`[IPFSClient] Using fast path for previously accessed ${e}`):(console.log(`[IPFSClient] First fetch for ${e}, using HTTP gateways...`),this.peerCache&&this.peerCache.set(e,"discovering")));let c=await this.verifiedFetch(this.ipfsUrl,h);if(!c.ok)throw new Error(`Failed to fetch from IPFS: ${c.status} ${c.statusText}`);let g=await c.arrayBuffer();return clearTimeout(p),e&&this.peerCache&&this.peerCache.get(e)==="discovering"&&(this.peerCache.set(e,[]),console.log(`[IPFSClient] Marked ${e} as discovered`)),new J(c,g)}catch(h){throw clearTimeout(p),e&&this.peerCache&&this.peerCache.get(e)==="discovering"&&this.peerCache.delete(e),console.error("[IPFSClient] Error during request:",h),h instanceof Error&&(console.error("[IPFSClient] Error name:",h.name),console.error("[IPFSClient] Error message:",h.message),console.error("[IPFSClient] Error stack:",h.stack)),h&&typeof h=="object"&&"errors"in h&&console.error("[IPFSClient] AggregateError details:",h.errors),h}}};async function se(r,t,e){let i=`${e}:${t}`,s=E.get(i);if(s)return s instanceof Promise?await s:s;let o=r.getImage(t);E.set(i,o);try{let n=await o;return E.set(i,n),n}catch(n){throw E.delete(i),n}}async function $e(r,t){let e=O.get(r);if(e)return e instanceof Promise?(console.log(`[fromIPFS] Waiting for in-flight GeoTIFF creation for ${r}`),await e):(console.log(`[fromIPFS] Using cached GeoTIFF client for ${r}`),e);console.log(`[fromIPFS] Creating new GeoTIFF client for ${r}`);let i=(async()=>{let s=new Z(r,t,ze,Pe),o=await re(s,{cacheSize:128*1024*1024,blockSize:65536});return O.set(r,o),o})();O.set(r,i);try{return await i}catch(s){throw O.delete(r),s}}var V=class extends ie{constructor(t,e=ue,i=fe,s=pe,o=me,n=de){super(t,e,i,s,o,n)}regionImpl(t,e){t&&(e=e.extract({left:t.x,top:t.y,width:t.w,height:t.h}))}sizeImpl(t,e){t&&(e=e.resize({...t,fit:"fill"}))}rotationImpl(t,e){t&&(t.isMirror&&(e=e.flop()),e=e.rotate(t.degree))}qualityFormatImpl(t,e,i,s,o){t&&(t==="color"?i=i.toColorspace("srgb"):t==="gray"||t==="grey"?i=i.grayscale():t==="bitonal"&&(i=i.threshold())),e&&(i=i.toFormat(e)),s==="png"&&(o.paletteBitDepth===1||o.space==="b-w")&&(i=i.toColorspace("b-w").png({colors:2}))}async generateImageTile(t,e,i){let s=t.split("/"),o=s.pop(),n=o.split(".")[0],a=o.split(".")[1],l=s.pop(),p=s.pop(),h=s.pop(),c=s.pop(),g={width:e.width,height:e.height},d=super.normalizeRegionParams(h,g),P=super.normalizeSizeParams(p,{width:d?d.w:g.width,height:d?d.h:g.height}),{x:u,y:I,w:b,h:$}=d??{x:0,y:0,w:g.width,h:g.height},{width:v,height:S}=P;console.log(`Attempting to fetch from URL: ${i}`);let x,w;typeof i=="string"?(console.log("Using standard HTTP fetch"),x=await ge(i),w=i):typeof c=="string"&&c.startsWith("bafy")?(console.log("Detected CID id, using fromIPFS"),w=`ipfs://${c}`,x=await $e(w,i)):(x=await ye(c,i),w=`oss://${c}`);let f=await se(x,0,w);console.log(`Source dimensions: ${f.getWidth()} x ${f.getHeight()}`),console.log(`Extracting region: x=${u}, y=${I}, w=${b}, h=${$}`),console.log(`Output size: ${v} x ${S}`);let M=await x.getImageCount();console.log(`Total images (including overviews): ${M}`);let C=f.getSamplesPerPixel(),F;C>=3?(F=[0,1,2],C>=4&&F.push(3)):F=[0],console.log("Using automatic overview selection based on resolution...");let R=Math.max(b/v,$/S),H=f,y=1;for(let q=0;q<M;q++){let T=await se(x,q,w),X=f.getWidth()/T.getWidth();X<=R&&X>y&&(y=X,H=T)}console.log(`Selected overview with scale: ${y.toFixed(2)}x`),console.log(`Overview dimensions: ${H.getWidth()} x ${H.getHeight()}`);let B=[Math.floor(u/y),Math.floor(I/y),Math.floor((u+b)/y),Math.floor((I+$)/y)],m;try{m=await H.readRasters({window:B,width:v,height:S,samples:F,interleave:!0,resampleMethod:"bilinear"})}catch(q){console.log(`Failed to read from overview, falling back to main image: ${q}`);let T=[u,I,u+b,I+$];m=await f.readRasters({window:T,width:v,height:S,samples:F,interleave:!0,resampleMethod:"bilinear"})}let k=F.length,L=Buffer.from(m.buffer,m.byteOffset,m.byteLength),D=W(L,{raw:{width:v,height:S,channels:k}}),ae=super.normalizeRotationParams(l);this.rotationImpl(ae,D);let le=super.normalizeQualityParams(n),ee=super.normalizeFormatParams(a,e.format);this.qualityFormatImpl(le,ee,D,a,e);let N={};return N.body=D,N.contentType=super.getContentType(ee),N}iiifTransform(t,e){let i=e.isHDImage?W({limitInputPixels:!1,sequentialRead:!0}):W(),s=t.split("/"),o=s.pop(),n=o.split(".")[0],a=o.split(".")[1],l=s.pop(),p=s.pop(),h=s.pop(),c=!1,g=i,d={width:e.width,height:e.height};e&&e.orientation&&(c=!0,g=g.rotate(),e.orientation>=5&&(d={width:e.height,height:e.width}));let P=super.normalizeRegionParams(h,d);this.regionImpl(P,g);let u=super.normalizeSizeParams(p,{width:P?P.w:d.width,height:P?P.h:d.height});this.sizeImpl(u,g);let I=super.normalizeRotationParams(l);this.rotationImpl(I,g);let b=super.normalizeQualityParams(n),$=super.normalizeFormatParams(a,e.format);return this.qualityFormatImpl(b,$,g,a,e),P||u||I||b||$||c?g:(console.log("skip iiif transform"),null)}async generateIiifImage(t,e,i){let s=t.split("/"),o=s.pop(),n=o.split(".")[0],a=o.split(".")[1],l=s.pop(),p=s.pop(),h=s.pop(),c=super.normalizeRegionParams(h,i),g=super.normalizeSizeParams(p,{width:c?c.w:i.width,height:c?c.h:i.height}),d=super.normalizeRotationParams(l),P=super.normalizeQualityParams(n),u=super.normalizeFormatParams(a,i.format),{x:I,y:b,w:$,h:v}=c||{x:0,y:0,w:i.width,h:i.height},{width:S,height:x}=g||{width:i.width,height:i.height},w=0,f;if(i.pages&&i.pages>1){let C=S/$,F=x/v,R=Math.max(C,F);if(R>=.95)console.log("Pyramid optimization: using full resolution page (scale \u2248 1.0)"),w=0;else{w=i.pages-1;let y=Math.pow(2,i.pages-1),B=i.width/y,m=i.height/y;for(;w>0;){let k=$*(B/i.width),L=v*(m/i.height);if(k>=S*1.1&&L>=x*1.1)break;w--,B*=2,m*=2}console.log(`Pyramid optimization: selected page ${w}/${i.pages-1} (scale: ${R.toFixed(2)}x, target: ${S}x${x})`)}let H=i.isHDImage?{limitInputPixels:!1,page:w,sequentialRead:!0,failOn:"none"}:{page:w,sequentialRead:!0,failOn:"none"};if(f=W(e,H),c&&w>0){let y=await f.metadata(),B=y.width/i.width,m={x:Math.floor(I*B),y:Math.floor(b*B),w:Math.floor($*B),h:Math.floor(v*B)};m.w=Math.min(m.w,y.width-m.x),m.h=Math.min(m.h,y.height-m.y),this.regionImpl(m,f)}else this.regionImpl(c,f)}else{let C=i.isHDImage?{limitInputPixels:!1,sequentialRead:!0,failOn:"none"}:{sequentialRead:!0,failOn:"none"};f=W(e,C),this.regionImpl(c,f)}this.sizeImpl(g,f),this.rotationImpl(d,f),this.qualityFormatImpl(P,u,f,a,i);let M={};return M.body=f,M.contentType=super.getContentType(u),M}generateImageInfo(t,e,i="",s){let o=this.level,n={width:e.width,height:e.height};e&&e.orientation&&e.orientation>=5&&(console.log(e.orientation),n={width:e.height,height:e.width});let a=super.generateImageInfoTemp(t,n,s),l=a.info;if((s==="2.0"||s==="2.1")&&(l.profile=[super.uriPattern("compliance",s)],o==="2")){let p={};p.formats=["jpg","png","webp","jp2","pdf","tif"],p.qualities=["color","gray","bitonal","default","native","grey"],p.supports=we[Number(s)],l.profile.push(p)}return s==="3.0"&&i&&(l.extraFormats=[i],l.preferredFormats=[i]),i&&(l.formats=[i]),a}};export{V as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etu-wiki/sharp-iiif-shims",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",
@@ -30,7 +30,7 @@
30
30
  "dist"
31
31
  ],
32
32
  "dependencies": {
33
- "@etu-wiki/iiif-image-shims": "^0.0.28",
33
+ "@etu-wiki/iiif-image-shims": "^0.0.29",
34
34
  "geotiff": "^2.1.3"
35
35
  },
36
36
  "peerDependencies": {