summit/frontend/node_modules/@monogrid/gainmap-js/dist/decode.webgpu.umd.min.cjs

6 lines
18 KiB
JavaScript

/**
* @monogrid/gainmap-js v3.4.0
* With ❤️, by MONOGRID <gainmap@monogrid.com>
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("three"),require("three/webgpu"),require("three/tsl")):"function"==typeof define&&define.amd?define(["exports","three","three/webgpu","three/tsl"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self)["@monogrid/gainmap-js"]={},e.three,e["three/webgpu"],e["three/tsl"])}(this,function(e,t,r,a){"use strict";function i(e){return r=>{const{sdr:a,gainMap:i,renderer:n}=r;a.colorSpace!==t.SRGBColorSpace&&(console.warn("SDR Colorspace needs to be *SRGBColorSpace*, setting it automatically"),a.colorSpace=t.SRGBColorSpace),a.needsUpdate=!0,i.colorSpace!==t.LinearSRGBColorSpace&&(console.warn("Gainmap Colorspace needs to be *LinearSRGBColorSpace*, setting it automatically"),i.colorSpace=t.LinearSRGBColorSpace),i.needsUpdate=!0;const s=e.createMaterial({...r,sdr:a,gainMap:i});return e.createQuadRenderer({width:a.image.width,height:a.image.height,type:t.HalfFloatType,colorSpace:t.LinearSRGBColorSpace,material:s,renderer:n,renderTargetOptions:r.renderTargetOptions})}}class n extends Error{}class s extends Error{}const o=(e,t,r)=>{const a=new RegExp(`${t}="([^"]*)"`,"i").exec(e);if(a)return a[1];const i=new RegExp(`<${t}[^>]*>([\\s\\S]*?)</${t}>`,"i").exec(e);if(i){const e=i[1].match(/<rdf:li>([^<]*)<\/rdf:li>/g);return e&&3===e.length?e.map(e=>e.replace(/<\/?rdf:li>/g,"")):i[1].trim()}if(void 0!==r)return r;throw new Error(`Can't find ${t} in gainmap metadata`)},d=e=>{let t;t="undefined"!=typeof TextDecoder?(new TextDecoder).decode(e):e.toString();let r=t.indexOf("<x:xmpmeta");for(;-1!==r;){const e=t.indexOf("x:xmpmeta>",r),a=t.slice(r,e+10);try{const e=o(a,"hdrgm:GainMapMin","0"),t=o(a,"hdrgm:GainMapMax"),r=o(a,"hdrgm:Gamma","1"),i=o(a,"hdrgm:OffsetSDR","0.015625"),n=o(a,"hdrgm:OffsetHDR","0.015625"),s=/hdrgm:HDRCapacityMin="([^"]*)"/.exec(a),d=s?s[1]:"0",p=/hdrgm:HDRCapacityMax="([^"]*)"/.exec(a);if(!p)throw new Error("Incomplete gainmap metadata");const h=p[1];return{gainMapMin:Array.isArray(e)?e.map(e=>parseFloat(e)):[parseFloat(e),parseFloat(e),parseFloat(e)],gainMapMax:Array.isArray(t)?t.map(e=>parseFloat(e)):[parseFloat(t),parseFloat(t),parseFloat(t)],gamma:Array.isArray(r)?r.map(e=>parseFloat(e)):[parseFloat(r),parseFloat(r),parseFloat(r)],offsetSdr:Array.isArray(i)?i.map(e=>parseFloat(e)):[parseFloat(i),parseFloat(i),parseFloat(i)],offsetHdr:Array.isArray(n)?n.map(e=>parseFloat(e)):[parseFloat(n),parseFloat(n),parseFloat(n)],hdrCapacityMin:parseFloat(d),hdrCapacityMax:parseFloat(h)}}catch(e){}r=t.indexOf("<x:xmpmeta",e)}};class p{options;constructor(e){this.options={debug:!(!e||void 0===e.debug)&&e.debug,extractFII:!e||void 0===e.extractFII||e.extractFII,extractNonFII:!e||void 0===e.extractNonFII||e.extractNonFII}}extract(e){return new Promise((t,r)=>{const a=this.options.debug,i=new DataView(e.buffer);if(65496!==i.getUint16(0))return void r(new Error("Not a valid jpeg"));const n=i.byteLength;let s,o=2,d=0;for(;o<n;){if(++d>250)return void r(new Error(`Found no marker after ${d} loops 😵`));if(255!==i.getUint8(o))return void r(new Error(`Not a valid marker at offset 0x${o.toString(16)}, found: 0x${i.getUint8(o).toString(16)}`));if(s=i.getUint8(o+1),a&&console.log(`Marker: ${s.toString(16)}`),226===s){a&&console.log("Found APP2 marker (0xffe2)");const e=o+4;if(1297106432===i.getUint32(e)){const a=e+4;let n;if(18761===i.getUint16(a))n=!1;else{if(19789!==i.getUint16(a))return void r(new Error("No valid endianness marker found in TIFF header"));n=!0}if(42!==i.getUint16(a+2,!n))return void r(new Error("Not valid TIFF data! (no 0x002A marker)"));const s=i.getUint32(a+4,!n);if(s<8)return void r(new Error("Not valid TIFF data! (First offset less than 8)"));const o=a+s,d=i.getUint16(o,!n),p=o+2;let h=0;for(let e=p;e<p+12*d;e+=12)45057===i.getUint16(e,!n)&&(h=i.getUint32(e+8,!n));const g=o+2+12*d+4,l=[];for(let e=g;e<g+16*h;e+=16){const t={MPType:i.getUint32(e,!n),size:i.getUint32(e+4,!n),dataOffset:i.getUint32(e+8,!n),dependantImages:i.getUint32(e+12,!n),start:-1,end:-1,isFII:!1};t.dataOffset?(t.start=a+t.dataOffset,t.isFII=!1):(t.start=0,t.isFII=!0),t.end=t.start+t.size,l.push(t)}if(this.options.extractNonFII&&l.length){const e=new Blob([i]),r=[];for(const t of l){if(t.isFII&&!this.options.extractFII)continue;const a=e.slice(t.start,t.end+1,"image/jpeg");r.push(a)}t(r)}}}o+=2+i.getUint16(o+2)}})}}const h=async e=>{const t=d(e);if(!t)throw new s("Gain map XMP metadata not found");const r=new p({extractFII:!0,extractNonFII:!0}),a=await r.extract(e);if(2!==a.length)throw new n("Gain map recovery image not found");return{sdr:new Uint8Array(await a[0].arrayBuffer()),gainMap:new Uint8Array(await a[1].arrayBuffer()),metadata:t}},g=e=>new Promise((t,r)=>{const a=document.createElement("img");a.onload=()=>{t(a)},a.onerror=e=>{r(e)},a.src=URL.createObjectURL(e)});class l extends t.Loader{_renderer;_renderTargetOptions;_internalLoadingManager;_config;constructor(e,r){super(r),this._config=e,e.renderer&&(this._renderer=e.renderer),this._internalLoadingManager=new t.LoadingManager}setRenderer(e){return this._renderer=e,this}setRenderTargetOptions(e){return this._renderTargetOptions=e,this}prepareQuadRenderer(){this._renderer||console.warn("WARNING: A Renderer was not passed to this Loader constructor or in setRenderer, the result of this Loader will need to be converted to a Data Texture with toDataTexture() before you can use it in your renderer.");const e=this._config.createMaterial({gainMapMax:[1,1,1],gainMapMin:[0,0,0],gamma:[1,1,1],offsetHdr:[1,1,1],offsetSdr:[1,1,1],hdrCapacityMax:1,hdrCapacityMin:0,maxDisplayBoost:1,gainMap:new t.Texture,sdr:new t.Texture});return this._config.createQuadRenderer({width:16,height:16,type:t.HalfFloatType,colorSpace:t.LinearSRGBColorSpace,material:e,renderer:this._renderer,renderTargetOptions:this._renderTargetOptions})}async processImages(e,t,r){const a=t?new Blob([t],{type:"image/jpeg"}):void 0,i=new Blob([e],{type:"image/jpeg"});let n,s,o=!1;if("undefined"==typeof createImageBitmap){const e=await Promise.all([a?g(a):Promise.resolve(void 0),g(i)]);s=e[0],n=e[1],o="flipY"===r}else{const e=await Promise.all([a?createImageBitmap(a,{imageOrientation:r||"flipY"}):Promise.resolve(void 0),createImageBitmap(i,{imageOrientation:r||"flipY"})]);s=e[0],n=e[1]}return{sdrImage:n,gainMapImage:s,needsFlip:o}}createTextures(e,r,a){const i=new t.Texture(r||new ImageData(2,2),t.UVMapping,t.ClampToEdgeWrapping,t.ClampToEdgeWrapping,t.LinearFilter,t.LinearMipMapLinearFilter,t.RGBAFormat,t.UnsignedByteType,1,t.LinearSRGBColorSpace);i.flipY=a,i.needsUpdate=!0;const n=new t.Texture(e,t.UVMapping,t.ClampToEdgeWrapping,t.ClampToEdgeWrapping,t.LinearFilter,t.LinearMipMapLinearFilter,t.RGBAFormat,t.UnsignedByteType,1,t.SRGBColorSpace);return n.flipY=a,n.needsUpdate=!0,{gainMap:i,sdr:n}}updateQuadRenderer(e,t,r,a,i){e.width=t.width,e.height=t.height,e.material.gainMap=r,e.material.sdr=a,e.material.gainMapMin=i.gainMapMin,e.material.gainMapMax=i.gainMapMax,e.material.offsetHdr=i.offsetHdr,e.material.offsetSdr=i.offsetSdr,e.material.gamma=i.gamma,e.material.hdrCapacityMin=i.hdrCapacityMin,e.material.hdrCapacityMax=i.hdrCapacityMax,e.material.maxDisplayBoost=Math.pow(2,i.hdrCapacityMax),e.material.needsUpdate=!0}}class m{_renderer;_rendererIsDisposable=!1;_material;_scene;_camera;_quad;_renderTarget;_width;_height;_type;_colorSpace;_supportsReadPixels=!0;constructor(e){this._width=e.width,this._height=e.height,this._type=e.type,this._colorSpace=e.colorSpace;const t={format:r.RGBAFormat,depthBuffer:!1,stencilBuffer:!1,type:this._type,colorSpace:this._colorSpace,anisotropy:void 0!==e.renderTargetOptions?.anisotropy?e.renderTargetOptions?.anisotropy:1,generateMipmaps:void 0!==e.renderTargetOptions?.generateMipmaps&&e.renderTargetOptions?.generateMipmaps,magFilter:void 0!==e.renderTargetOptions?.magFilter?e.renderTargetOptions?.magFilter:r.LinearFilter,minFilter:void 0!==e.renderTargetOptions?.minFilter?e.renderTargetOptions?.minFilter:r.LinearFilter,samples:void 0!==e.renderTargetOptions?.samples?e.renderTargetOptions?.samples:void 0,wrapS:void 0!==e.renderTargetOptions?.wrapS?e.renderTargetOptions?.wrapS:r.ClampToEdgeWrapping,wrapT:void 0!==e.renderTargetOptions?.wrapT?e.renderTargetOptions?.wrapT:r.ClampToEdgeWrapping};this._material=e.material,e.renderer?this._renderer=e.renderer:(this._renderer=m.instantiateRenderer(),this._rendererIsDisposable=!0),this._scene=new r.Scene,this._camera=new r.OrthographicCamera,this._camera.position.set(0,0,10),this._camera.left=-.5,this._camera.right=.5,this._camera.top=.5,this._camera.bottom=-.5,this._camera.updateProjectionMatrix(),this._quad=new r.Mesh(new r.PlaneGeometry,this._material),this._quad.geometry.computeBoundingBox(),this._scene.add(this._quad),this._renderTarget=new r.RenderTarget(this.width,this.height,t),this._renderTarget.texture.mapping=void 0!==e.renderTargetOptions?.mapping?e.renderTargetOptions?.mapping:r.UVMapping}static instantiateRenderer(){const e=new r.WebGPURenderer;return e.setSize(128,128),e}render=async()=>{this._renderer.hasInitialized()||await this._renderer.init(),this._renderer.setRenderTarget(this._renderTarget);try{this._renderer.render(this._scene,this._camera)}catch(e){throw this._renderer.setRenderTarget(null),e}this._renderer.setRenderTarget(null)};async toArray(){if(!this._supportsReadPixels)throw new Error("Can't read pixels in this browser");return await this._renderer.readRenderTargetPixelsAsync(this._renderTarget,0,0,this._width,this._height)}async toDataTexture(e){const t=new r.DataTexture(await this.toArray(),this.width,this.height,r.RGBAFormat,this._type,e?.mapping||r.UVMapping,e?.wrapS||r.ClampToEdgeWrapping,e?.wrapT||r.ClampToEdgeWrapping,e?.magFilter||r.LinearFilter,e?.minFilter||r.LinearFilter,e?.anisotropy||1,r.LinearSRGBColorSpace);return t.flipY=void 0===e?.flipY||e?.flipY,t.generateMipmaps=void 0!==e?.generateMipmaps&&e?.generateMipmaps,t}disposeOnDemandRenderer(){this._renderer.setRenderTarget(null),this._rendererIsDisposable&&this._renderer.dispose()}dispose(e){e&&this.renderTarget.dispose(),this.material instanceof r.ShaderMaterial&&Object.values(this.material.uniforms).forEach(e=>{e.value instanceof r.Texture&&e.value.dispose()}),Object.values(this.material).forEach(e=>{e instanceof r.Texture&&e.dispose()}),this.material.dispose(),this._quad.geometry.dispose(),this.disposeOnDemandRenderer()}get width(){return this._width}set width(e){this._width=e,this._renderTarget.setSize(this._width,this._height)}get height(){return this._height}set height(e){this._height=e,this._renderTarget.setSize(this._width,this._height)}get renderer(){return this._renderer}get renderTarget(){return this._renderTarget}set renderTarget(e){this._renderTarget=e,this._width=e.width,this._height=e.height}get material(){return this._material}get type(){return this._type}get colorSpace(){return this._colorSpace}}const c=a.vec3(-65504,-65504,-65504),f=a.vec3(65504,65504,65504);class u extends r.MeshBasicNodeMaterial{_maxDisplayBoost;_hdrCapacityMin;_hdrCapacityMax;_gammaUniform;_offsetHdrUniform;_offsetSdrUniform;_gainMapMinUniform;_gainMapMaxUniform;_weightFactorUniform;_sdrTexture;_gainMapTexture;constructor({gamma:e,offsetHdr:t,offsetSdr:i,gainMapMin:n,gainMapMax:s,maxDisplayBoost:o,hdrCapacityMin:d,hdrCapacityMax:p,sdr:h,gainMap:g}){super(),this.name="GainMapDecoderMaterial",this.blending=r.NoBlending,this.depthTest=!1,this.depthWrite=!1,this._sdrTexture=a.texture(h),this._gainMapTexture=a.texture(g),this._gammaUniform=a.uniform(a.vec3(1/e[0],1/e[1],1/e[2])),this._offsetHdrUniform=a.uniform(a.vec3(t[0],t[1],t[2])),this._offsetSdrUniform=a.uniform(a.vec3(i[0],i[1],i[2])),this._gainMapMinUniform=a.uniform(a.vec3(n[0],n[1],n[2])),this._gainMapMaxUniform=a.uniform(a.vec3(s[0],s[1],s[2]));const l=(Math.log2(o)-d)/(p-d);this._weightFactorUniform=a.uniform(l),this._maxDisplayBoost=o,this._hdrCapacityMin=d,this._hdrCapacityMax=p;const m=this._sdrTexture.rgb,u=this._gainMapTexture.rgb,M=a.pow(u,this._gammaUniform),_=a.sub(a.float(1),M),y=a.add(a.mul(this._gainMapMinUniform,_),a.mul(this._gainMapMaxUniform,M)),x=a.sub(a.mul(a.add(m,this._offsetSdrUniform),a.exp2(a.mul(y,this._weightFactorUniform))),this._offsetHdrUniform),w=a.max(c,a.min(f,x));this.colorNode=w}get sdr(){return this._sdrTexture.value}set sdr(e){this._sdrTexture.value=e}get gainMap(){return this._gainMapTexture.value}set gainMap(e){this._gainMapTexture.value=e}get offsetHdr(){return[this._offsetHdrUniform.value.x,this._offsetHdrUniform.value.y,this._offsetHdrUniform.value.z]}set offsetHdr(e){this._offsetHdrUniform.value.x=e[0],this._offsetHdrUniform.value.y=e[1],this._offsetHdrUniform.value.z=e[2]}get offsetSdr(){return[this._offsetSdrUniform.value.x,this._offsetSdrUniform.value.y,this._offsetSdrUniform.value.z]}set offsetSdr(e){this._offsetSdrUniform.value.x=e[0],this._offsetSdrUniform.value.y=e[1],this._offsetSdrUniform.value.z=e[2]}get gainMapMin(){return[this._gainMapMinUniform.value.x,this._gainMapMinUniform.value.y,this._gainMapMinUniform.value.z]}set gainMapMin(e){this._gainMapMinUniform.value.x=e[0],this._gainMapMinUniform.value.y=e[1],this._gainMapMinUniform.value.z=e[2]}get gainMapMax(){return[this._gainMapMaxUniform.value.x,this._gainMapMaxUniform.value.y,this._gainMapMaxUniform.value.z]}set gainMapMax(e){this._gainMapMaxUniform.value.x=e[0],this._gainMapMaxUniform.value.y=e[1],this._gainMapMaxUniform.value.z=e[2]}get gamma(){return[1/this._gammaUniform.value.x,1/this._gammaUniform.value.y,1/this._gammaUniform.value.z]}set gamma(e){this._gammaUniform.value.x=1/e[0],this._gammaUniform.value.y=1/e[1],this._gammaUniform.value.z=1/e[2]}get hdrCapacityMin(){return this._hdrCapacityMin}set hdrCapacityMin(e){this._hdrCapacityMin=e,this.calculateWeight()}get hdrCapacityMax(){return this._hdrCapacityMax}set hdrCapacityMax(e){this._hdrCapacityMax=e,this.calculateWeight()}get maxDisplayBoost(){return this._maxDisplayBoost}set maxDisplayBoost(e){this._maxDisplayBoost=Math.max(1,Math.min(65504,e)),this.calculateWeight()}calculateWeight(){const e=(Math.log2(this._maxDisplayBoost)-this._hdrCapacityMin)/(this._hdrCapacityMax-this._hdrCapacityMin);this._weightFactorUniform.value=Math.max(0,Math.min(1,e))}}const M=i({renderer:r.WebGPURenderer,createMaterial:e=>new u(e),createQuadRenderer:e=>new m(e)});class _ extends l{constructor(e,t){super({renderer:e,createMaterial:e=>new u(e),createQuadRenderer:e=>new m(e)},t)}async render(e,t,r,a){const{sdrImage:i,gainMapImage:n,needsFlip:s}=await this.processImages(r,a,"from-image"),{gainMap:o,sdr:d}=this.createTextures(i,n,s);this.updateQuadRenderer(e,i,o,d,t),await e.render()}}class y extends _{load(e,t,a,i){const o=this.prepareQuadRenderer(),d=new r.FileLoader(this._internalLoadingManager);return d.setResponseType("arraybuffer"),d.setRequestHeader(this.requestHeader),d.setPath(this.path),d.setWithCredentials(this.withCredentials),this.manager.itemStart(e),d.load(e,async r=>{if("string"==typeof r)throw new Error("Invalid buffer, received [string], was expecting [ArrayBuffer]");const a=new Uint8Array(r);let d,p,g;try{const e=await h(a);d=e.sdr,p=e.gainMap,g=e.metadata}catch(t){if(!(t instanceof s||t instanceof n))throw t;console.warn(`Failure to reconstruct an HDR image from ${e}: Gain map metadata not found in the file, HDRJPGLoader will render the SDR jpeg`),g={gainMapMin:[0,0,0],gainMapMax:[1,1,1],gamma:[1,1,1],hdrCapacityMin:0,hdrCapacityMax:1,offsetHdr:[0,0,0],offsetSdr:[0,0,0]},d=a}try{await this.render(o,g,d.buffer,p?.buffer)}catch(t){return this.manager.itemError(e),"function"==typeof i&&i(t),void o.disposeOnDemandRenderer()}"function"==typeof t&&t(o),this.manager.itemEnd(e),o.disposeOnDemandRenderer()},a,t=>{this.manager.itemError(e),"function"==typeof i&&i(t)}),o}}e.GainMapDecoderMaterial=u,e.GainMapLoader=class extends _{load([e,t,a],i,n,s){const o=this.prepareQuadRenderer();let d,p,h;const g=async()=>{if(d&&p&&h){try{await this.render(o,h,d,p)}catch(r){return this.manager.itemError(e),this.manager.itemError(t),this.manager.itemError(a),"function"==typeof s&&s(r),void o.disposeOnDemandRenderer()}"function"==typeof i&&i(o),this.manager.itemEnd(e),this.manager.itemEnd(t),this.manager.itemEnd(a),o.disposeOnDemandRenderer()}};let l=!0,m=0,c=0,f=!0,u=0,M=0,_=!0,y=0,x=0;const w=()=>{if("function"==typeof n){n(new ProgressEvent("progress",{lengthComputable:l&&f&&_,loaded:c+M+x,total:m+u+y}))}};this.manager.itemStart(e),this.manager.itemStart(t),this.manager.itemStart(a);const T=new r.FileLoader(this._internalLoadingManager);T.setResponseType("arraybuffer"),T.setRequestHeader(this.requestHeader),T.setPath(this.path),T.setWithCredentials(this.withCredentials),T.load(e,async e=>{if("string"==typeof e)throw new Error("Invalid sdr buffer");d=e,await g()},e=>{l=e.lengthComputable,c=e.loaded,m=e.total,w()},t=>{this.manager.itemError(e),"function"==typeof s&&s(t)});const v=new r.FileLoader(this._internalLoadingManager);v.setResponseType("arraybuffer"),v.setRequestHeader(this.requestHeader),v.setPath(this.path),v.setWithCredentials(this.withCredentials),v.load(t,async e=>{if("string"==typeof e)throw new Error("Invalid gainmap buffer");p=e,await g()},e=>{f=e.lengthComputable,M=e.loaded,u=e.total,w()},e=>{this.manager.itemError(t),"function"==typeof s&&s(e)});const U=new r.FileLoader(this._internalLoadingManager);return U.setRequestHeader(this.requestHeader),U.setPath(this.path),U.setWithCredentials(this.withCredentials),U.load(a,async e=>{if("string"!=typeof e)throw new Error("Invalid metadata string");h=JSON.parse(e),await g()},e=>{_=e.lengthComputable,x=e.loaded,y=e.total,w()},e=>{this.manager.itemError(a),"function"==typeof s&&s(e)}),o}},e.GainMapNotFoundError=n,e.HDRJPGLoader=y,e.JPEGRLoader=y,e.LoaderBaseShared=l,e.MPFExtractor=p,e.QuadRenderer=m,e.XMPMetadataNotFoundError=s,e.createDecodeFunction=i,e.decode=async e=>{if(!e.renderer)throw new Error("Renderer is required for decode function");const t=M({...e,renderer:e.renderer});try{await t.render()}catch(e){throw t.disposeOnDemandRenderer(),e}return t},e.extractGainmapFromJPEG=h,e.extractXMP=d});