From 828a6ef1cf9c1046b3500db88c3cb023f2cf8332 Mon Sep 17 00:00:00 2001 From: "Mr.doob" Date: Mon, 10 Nov 2025 12:35:06 +0900 Subject: [PATCH 1/2] EXRLoader: Add HTJ2K compression support. --- examples/jsm/libs/openjph/libopenjph.wasm | Bin 0 -> 107948 bytes examples/jsm/libs/openjph/openjph.module.js | 16 ++ examples/jsm/loaders/EXRLoader.js | 188 ++++++++++++- examples/jsm/loaders/JPHLoader.js | 284 ++++++++++++++++++++ examples/webgl_loader_exr_htj2k.html | 180 +++++++++++++ examples/webgl_loader_jph.html | 109 ++++++++ 6 files changed, 769 insertions(+), 8 deletions(-) create mode 100755 examples/jsm/libs/openjph/libopenjph.wasm create mode 100644 examples/jsm/libs/openjph/openjph.module.js create mode 100644 examples/jsm/loaders/JPHLoader.js create mode 100644 examples/webgl_loader_exr_htj2k.html create mode 100644 examples/webgl_loader_jph.html diff --git a/examples/jsm/libs/openjph/libopenjph.wasm b/examples/jsm/libs/openjph/libopenjph.wasm new file mode 100755 index 0000000000000000000000000000000000000000..1b9972639e3aa235c129179a58e67de848f27798 GIT binary patch literal 107948 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 Q46F8jr%*2K`o)d^4@S~2UjP6A literal 0 HcmV?d00001 diff --git a/examples/jsm/libs/openjph/openjph.module.js b/examples/jsm/libs/openjph/openjph.module.js new file mode 100644 index 00000000000000..3e3c18939ece73 --- /dev/null +++ b/examples/jsm/libs/openjph/openjph.module.js @@ -0,0 +1,16 @@ + +var Module = (() => { + var _scriptDir = import.meta.url; + + return ( +function(Module) { + Module = Module || {}; + +var Module=typeof Module!="undefined"?Module:{};var readyPromiseResolve,readyPromiseReject;Module["ready"]=new Promise(function(resolve,reject){readyPromiseResolve=resolve;readyPromiseReject=reject});var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var ENVIRONMENT_IS_WEB=true;var ENVIRONMENT_IS_WORKER=false;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptDir){scriptDirectory=_scriptDir}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=(url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText});if(ENVIRONMENT_IS_WORKER){readBinary=(url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)})}readAsync=((url,onload,onerror)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=(()=>{if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()});xhr.onerror=onerror;xhr.send(null)})}setWindowTitle=(title=>document.title=title)}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var tempRet0=0;var setTempRet0=value=>{tempRet0=value};var getTempRet0=()=>tempRet0;var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime=Module["noExitRuntime"]||true;if(typeof WebAssembly!="object"){abort("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;function getCFunc(ident){var func=Module["_"+ident];return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len)}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;var wasmTable;var __ATPRERUN__=[];var __ATINIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){{if(Module["onAbort"]){Module["onAbort"](what)}}what="Aborted("+what+")";err(what);ABORT=true;EXITSTATUS=1;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return filename.startsWith(dataURIPrefix)}var wasmBinaryFile;if(Module["locateFile"]){wasmBinaryFile="libopenjph.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}}else{wasmBinaryFile=new URL("libopenjph.wasm",import.meta.url).toString()}function getBinary(file){try{if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}else{throw"both async and sync fetching of the wasm failed"}}catch(err){abort(err)}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)){if(typeof fetch=="function"){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw"failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary(wasmBinaryFile)})}}return Promise.resolve().then(function(){return getBinary(wasmBinaryFile)})}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=Module["asm"]["u"];updateGlobalBufferAndViews(wasmMemory.buffer);wasmTable=Module["asm"]["K"];addOnInit(Module["asm"]["v"]);removeRunDependency("wasm-instantiate")}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(function(instance){return instance}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(wasmBinaryFile)&&typeof fetch=="function"){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiationResult,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(receiveInstantiationResult)})})}else{return instantiateArrayBuffer(receiveInstantiationResult)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync().catch(readyPromiseReject);return{}}function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func=="number"){if(callback.arg===undefined){getWasmTableEntry(func)()}else{getWasmTableEntry(func)(callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var wasmTableMirror=[];function getWasmTableEntry(funcPtr){var func=wasmTableMirror[funcPtr];if(!func){if(funcPtr>=wasmTableMirror.length)wasmTableMirror.length=funcPtr+1;wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func}function ___cxa_allocate_exception(size){return _malloc(size+24)+24}var exceptionCaught=[];function exception_addRef(info){info.add_ref()}var uncaughtExceptionCount=0;function ___cxa_begin_catch(ptr){var info=new ExceptionInfo(ptr);if(!info.get_caught()){info.set_caught(true);uncaughtExceptionCount--}info.set_rethrown(false);exceptionCaught.push(info);exception_addRef(info);return info.get_exception_ptr()}var exceptionLast=0;function ExceptionInfo(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24;this.set_type=function(type){HEAPU32[this.ptr+4>>2]=type};this.get_type=function(){return HEAPU32[this.ptr+4>>2]};this.set_destructor=function(destructor){HEAPU32[this.ptr+8>>2]=destructor};this.get_destructor=function(){return HEAPU32[this.ptr+8>>2]};this.set_refcount=function(refcount){HEAP32[this.ptr>>2]=refcount};this.set_caught=function(caught){caught=caught?1:0;HEAP8[this.ptr+12>>0]=caught};this.get_caught=function(){return HEAP8[this.ptr+12>>0]!=0};this.set_rethrown=function(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13>>0]=rethrown};this.get_rethrown=function(){return HEAP8[this.ptr+13>>0]!=0};this.init=function(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor);this.set_refcount(0);this.set_caught(false);this.set_rethrown(false)};this.add_ref=function(){var value=HEAP32[this.ptr>>2];HEAP32[this.ptr>>2]=value+1};this.release_ref=function(){var prev=HEAP32[this.ptr>>2];HEAP32[this.ptr>>2]=prev-1;return prev===1};this.set_adjusted_ptr=function(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr};this.get_adjusted_ptr=function(){return HEAPU32[this.ptr+16>>2]};this.get_exception_ptr=function(){var isPointer=___cxa_is_pointer_type(this.get_type());if(isPointer){return HEAPU32[this.excPtr>>2]}var adjusted=this.get_adjusted_ptr();if(adjusted!==0)return adjusted;return this.excPtr}}function ___cxa_free_exception(ptr){return _free(new ExceptionInfo(ptr).ptr)}function exception_decRef(info){if(info.release_ref()&&!info.get_rethrown()){var destructor=info.get_destructor();if(destructor){getWasmTableEntry(destructor)(info.excPtr)}___cxa_free_exception(info.excPtr)}}function ___cxa_end_catch(){_setThrew(0);var info=exceptionCaught.pop();exception_decRef(info);exceptionLast=0}function ___resumeException(ptr){if(!exceptionLast){exceptionLast=ptr}throw ptr}function ___cxa_find_matching_catch_2(){var thrown=exceptionLast;if(!thrown){setTempRet0(0);return 0}var info=new ExceptionInfo(thrown);info.set_adjusted_ptr(thrown);var thrownType=info.get_type();if(!thrownType){setTempRet0(0);return thrown}var typeArray=Array.prototype.slice.call(arguments);for(var i=0;i>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){var oldSize=HEAPU8.length;requestedSize=requestedSize>>>0;var maxHeapSize=_emscripten_get_heap_max();if(requestedSize>maxHeapSize){return false}let alignUp=(x,multiple)=>x+(multiple-x%multiple)%multiple;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}var SYSCALLS={varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret}};function _fd_close(fd){return 52}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){return 70}var printCharBuffers=[null,[],[]];function printChar(stream,curr){var buffer=printCharBuffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0}else{buffer.push(curr)}}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;for(var j=0;j>2]=num;return 0}function _getTempRet0(){return getTempRet0()}function _llvm_eh_typeid_for(type){return type}var asmLibraryArg={"a":___cxa_allocate_exception,"k":___cxa_begin_catch,"j":___cxa_end_catch,"f":___cxa_find_matching_catch_2,"m":___cxa_find_matching_catch_3,"r":___cxa_free_exception,"b":___cxa_throw,"e":___resumeException,"h":_abort,"q":_emscripten_memcpy_big,"o":_emscripten_resize_heap,"p":_fd_close,"n":_fd_seek,"i":_fd_write,"c":_getTempRet0,"g":invoke_ii,"s":invoke_iii,"t":invoke_viiiiii,"d":invoke_viiiiiii,"l":_llvm_eh_typeid_for};var asm=createWasm();var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return(___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["v"]).apply(null,arguments)};var _create_j2c_data=Module["_create_j2c_data"]=function(){return(_create_j2c_data=Module["_create_j2c_data"]=Module["asm"]["w"]).apply(null,arguments)};var _init_j2c_data=Module["_init_j2c_data"]=function(){return(_init_j2c_data=Module["_init_j2c_data"]=Module["asm"]["x"]).apply(null,arguments)};var _get_j2c_width=Module["_get_j2c_width"]=function(){return(_get_j2c_width=Module["_get_j2c_width"]=Module["asm"]["y"]).apply(null,arguments)};var _get_j2c_height=Module["_get_j2c_height"]=function(){return(_get_j2c_height=Module["_get_j2c_height"]=Module["asm"]["z"]).apply(null,arguments)};var _get_j2c_bit_depth=Module["_get_j2c_bit_depth"]=function(){return(_get_j2c_bit_depth=Module["_get_j2c_bit_depth"]=Module["asm"]["A"]).apply(null,arguments)};var _get_j2c_is_signed=Module["_get_j2c_is_signed"]=function(){return(_get_j2c_is_signed=Module["_get_j2c_is_signed"]=Module["asm"]["B"]).apply(null,arguments)};var _get_j2c_num_components=Module["_get_j2c_num_components"]=function(){return(_get_j2c_num_components=Module["_get_j2c_num_components"]=Module["asm"]["C"]).apply(null,arguments)};var _get_j2c_downsampling_x=Module["_get_j2c_downsampling_x"]=function(){return(_get_j2c_downsampling_x=Module["_get_j2c_downsampling_x"]=Module["asm"]["D"]).apply(null,arguments)};var _get_j2c_downsampling_y=Module["_get_j2c_downsampling_y"]=function(){return(_get_j2c_downsampling_y=Module["_get_j2c_downsampling_y"]=Module["asm"]["E"]).apply(null,arguments)};var _parse_j2c_data=Module["_parse_j2c_data"]=function(){return(_parse_j2c_data=Module["_parse_j2c_data"]=Module["asm"]["F"]).apply(null,arguments)};var _restrict_input_resolution=Module["_restrict_input_resolution"]=function(){return(_restrict_input_resolution=Module["_restrict_input_resolution"]=Module["asm"]["G"]).apply(null,arguments)};var _enable_resilience=Module["_enable_resilience"]=function(){return(_enable_resilience=Module["_enable_resilience"]=Module["asm"]["H"]).apply(null,arguments)};var _pull_j2c_line=Module["_pull_j2c_line"]=function(){return(_pull_j2c_line=Module["_pull_j2c_line"]=Module["asm"]["I"]).apply(null,arguments)};var _release_j2c_data=Module["_release_j2c_data"]=function(){return(_release_j2c_data=Module["_release_j2c_data"]=Module["asm"]["J"]).apply(null,arguments)};var _free=Module["_free"]=function(){return(_free=Module["_free"]=Module["asm"]["L"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return(_malloc=Module["_malloc"]=Module["asm"]["M"]).apply(null,arguments)};var _setThrew=Module["_setThrew"]=function(){return(_setThrew=Module["_setThrew"]=Module["asm"]["N"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return(stackSave=Module["stackSave"]=Module["asm"]["O"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return(stackRestore=Module["stackRestore"]=Module["asm"]["P"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return(stackAlloc=Module["stackAlloc"]=Module["asm"]["Q"]).apply(null,arguments)};var ___cxa_can_catch=Module["___cxa_can_catch"]=function(){return(___cxa_can_catch=Module["___cxa_can_catch"]=Module["asm"]["R"]).apply(null,arguments)};var ___cxa_is_pointer_type=Module["___cxa_is_pointer_type"]=function(){return(___cxa_is_pointer_type=Module["___cxa_is_pointer_type"]=Module["asm"]["S"]).apply(null,arguments)};function invoke_ii(index,a1){var sp=stackSave();try{return getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iii(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}Module["ccall"]=ccall;Module["cwrap"]=cwrap;Module["writeArrayToMemory"]=writeArrayToMemory;var calledRun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve(Module);if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run(); + + + return Module.ready +} +); +})(); +export default Module; \ No newline at end of file diff --git a/examples/jsm/loaders/EXRLoader.js b/examples/jsm/loaders/EXRLoader.js index 2307151b0aaacf..17deee5633d01a 100644 --- a/examples/jsm/loaders/EXRLoader.js +++ b/examples/jsm/loaders/EXRLoader.js @@ -10,6 +10,9 @@ import { RGBAFormat } from 'three'; import * as fflate from '../libs/fflate.module.js'; +import OpenJPHModule from '../libs/openjph/openjph.module.js'; + +let _openjph; // Referred to the original Industrial Light & Magic OpenEXR implementation and the TinyEXR / Syoyo Fujita // implementation, so I have preserved their copyright notices. @@ -84,11 +87,15 @@ import * as fflate from '../libs/fflate.module.js'; * A loader for the OpenEXR texture format. * * `EXRLoader` currently supports uncompressed, ZIP(S), RLE, PIZ and DWA/B compression. + * HTJ2K (High Throughput JPEG 2000) compression is supported when the OpenJPH WASM module is loaded. * Supports reading as UnsignedByte, HalfFloat and Float type data texture. * * ```js * const loader = new EXRLoader(); * const texture = await loader.loadAsync( 'textures/memorial.exr' ); + * + * // For HTJ2K support: + * EXRLoader.setOpenJPH( openjphModule ); * ``` * * @augments DataTextureLoader @@ -129,7 +136,7 @@ class EXRLoader extends DataTextureLoader { * @param {ArrayBuffer} buffer - The raw texture data. * @return {DataTextureLoader~TexData} An object representing the parsed texture data. */ - parse( buffer ) { + async parse( buffer ) { const USHORT_RANGE = ( 1 << 16 ); const BITMAP_SIZE = ( USHORT_RANGE >> 3 ); @@ -1777,7 +1784,165 @@ class EXRLoader extends DataTextureLoader { } - function parseNullTerminatedString( buffer, offset ) { + async function uncompressHTJ2K( info ) { + + // HTJ2K (High Throughput JPEG 2000) decompression + // Reference: ISO/IEC 15444-15 / ITU-T T.814 + + // Lazy initialization of OpenJPH WASM module + let openjph; + + if ( ! _openjph ) { + + _openjph = new Promise( async ( resolve ) => { + + const openjph = await OpenJPHModule(); + resolve( openjph ); + + } ); + + } + + openjph = await _openjph; + + const compressedData = info.array; + const wasm = openjph; + const dv = new DataView( compressedData.buffer, compressedData.byteOffset, compressedData.byteLength ); + + // Parse HTJ2K header + let offset = 0; + + // Read magic number (0x4854 = 'HT') + const magic = dv.getUint16( offset, false ); // big-endian + offset += 2; + + if ( magic !== 0x4854 ) { + + throw new Error( + `THREE.EXRLoader: Invalid HTJ2K magic number: 0x${magic.toString( 16 )}. Expected 0x4854.` + ); + + } + + // Read payload length + const payloadLength = dv.getUint32( offset, false ); // big-endian + offset += 4; + + // Read number of channels + const numChannels = dv.getUint16( offset, false ); // big-endian + offset += 2; + + // Read channel map + const channelMap = new Uint16Array( numChannels ); + for ( let i = 0; i < numChannels; i ++ ) { + + channelMap[ i ] = dv.getUint16( offset, false ); // big-endian + offset += 2; + + } + + const headerSize = offset; + + // Extract JPEG 2000 codestream (data after header) + const codestreamSize = compressedData.byteLength - headerSize; + const codestreamData = new Uint8Array( compressedData.buffer, compressedData.byteOffset + headerSize, codestreamSize ); + + // Create J2K data structure + const j2kData = wasm._create_j2c_data(); + + if ( ! j2kData ) { + + throw new Error( 'THREE.EXRLoader: Failed to create J2K data structure.' ); + + } + + try { + + // Allocate memory for codestream + const dataPtr = wasm._malloc( codestreamSize ); + wasm.HEAPU8.set( codestreamData, dataPtr ); + + // Initialize codestream + wasm._init_j2c_data( j2kData, dataPtr, codestreamSize ); + + // Free input data + wasm._free( dataPtr ); + + // Parse codestream + wasm._parse_j2c_data( j2kData ); + + // Get dimensions from codestream + const width = wasm._get_width( j2kData ); + const height = wasm._get_height( j2kData ); + const numComponents = wasm._get_num_components( j2kData ); + + // Determine bytes per element from EXR info + const bytesPerElement = info.type === 1 ? 2 : 4; // HALF=1, FLOAT=2 + const totalBytes = width * height * numChannels * bytesPerElement; + + // Allocate output buffer + const outputBuffer = new ArrayBuffer( totalBytes ); + const outputView = new DataView( outputBuffer ); + + // Decode scanlines + let outputOffset = 0; + + for ( let y = 0; y < height; y ++ ) { + + for ( let c = 0; c < numComponents; c ++ ) { + + const linePtr = wasm._pull_j2c_line( j2kData ); + + if ( ! linePtr ) { + + throw new Error( `THREE.EXRLoader: Failed to decode HTJ2K line ${y}, component ${c}.` ); + + } + + // Copy and convert line data + for ( let x = 0; x < width; x ++ ) { + + const value = wasm.HEAP32[ ( linePtr >> 2 ) + x ]; + + if ( bytesPerElement === 2 ) { + + // HALF float - store as uint16 + outputView.setUint16( outputOffset, value, true ); + outputOffset += 2; + + } else { + + // FLOAT - store as int32 (will be reinterpreted as float) + outputView.setInt32( outputOffset, value, true ); + outputOffset += 4; + + } + + } + + } + + } + + // Release J2K data + wasm._release_j2c_data( j2kData ); + + return outputView; + + } catch ( error ) { + + // Clean up on error + if ( j2kData ) { + + wasm._release_j2c_data( j2kData ); + + } + + throw error; + + } + + } function parseNullTerminatedString( buffer, offset ) { const uintBuffer = new Uint8Array( buffer ); let endOffset = 0; @@ -1995,7 +2160,9 @@ class EXRLoader extends DataTextureLoader { 'B44_COMPRESSION', 'B44A_COMPRESSION', 'DWAA_COMPRESSION', - 'DWAB_COMPRESSION' + 'DWAB_COMPRESSION', + 'UNKNOWN_COMPRESSION', // 10 + 'HTJ2K_COMPRESSION' // 11 - High Throughput JPEG 2000 (ISO/IEC 15444-15) ]; const compression = parseUint8( dataView, offset ); @@ -2210,7 +2377,7 @@ class EXRLoader extends DataTextureLoader { } - function parseTiles() { + async function parseTiles() { const EXRDecoder = this; const offset = EXRDecoder.offset; @@ -2230,7 +2397,7 @@ class EXRLoader extends DataTextureLoader { const bytesBlockLine = EXRDecoder.columns * EXRDecoder.totalBytes; const isCompressed = EXRDecoder.size < EXRDecoder.lines * bytesBlockLine; - const viewer = isCompressed ? EXRDecoder.uncompress( EXRDecoder ) : uncompressRAW( EXRDecoder ); + const viewer = isCompressed ? await EXRDecoder.uncompress( EXRDecoder ) : uncompressRAW( EXRDecoder ); offset.value += EXRDecoder.size; @@ -2264,7 +2431,7 @@ class EXRLoader extends DataTextureLoader { } - function parseScanline() { + async function parseScanline() { const EXRDecoder = this; const offset = EXRDecoder.offset; @@ -2278,7 +2445,7 @@ class EXRLoader extends DataTextureLoader { const bytesPerLine = EXRDecoder.columns * EXRDecoder.totalBytes; const isCompressed = EXRDecoder.size < EXRDecoder.lines * bytesPerLine; - const viewer = isCompressed ? EXRDecoder.uncompress( EXRDecoder ) : uncompressRAW( EXRDecoder ); + const viewer = isCompressed ? await EXRDecoder.uncompress( EXRDecoder ) : uncompressRAW( EXRDecoder ); offset.value += EXRDecoder.size; @@ -2447,6 +2614,11 @@ class EXRLoader extends DataTextureLoader { EXRDecoder.uncompress = uncompressDWA; break; + case 'HTJ2K_COMPRESSION': + EXRDecoder.blockHeight = 32; // Typical block height for HTJ2K, may vary + EXRDecoder.uncompress = uncompressHTJ2K; + break; + default: throw new Error( 'EXRLoader.parse: ' + EXRHeader.compression + ' is unsupported' ); @@ -2702,7 +2874,7 @@ class EXRLoader extends DataTextureLoader { const EXRDecoder = setupDecoder( EXRHeader, bufferDataView, uInt8Array, offset, this.type, this.outputFormat ); // parse input data - EXRDecoder.decode(); + await EXRDecoder.decode(); // output texture post-processing if ( EXRDecoder.shouldExpand ) { diff --git a/examples/jsm/loaders/JPHLoader.js b/examples/jsm/loaders/JPHLoader.js new file mode 100644 index 00000000000000..78f07f6c66b9f7 --- /dev/null +++ b/examples/jsm/loaders/JPHLoader.js @@ -0,0 +1,284 @@ +import { + DataTexture, + FileLoader, + FloatType, + HalfFloatType, + LinearFilter, + LinearSRGBColorSpace, + Loader +} from 'three'; +import OpenJPHModule from '../libs/openjph/openjph.module.js'; + +let _openjph; + +/** + * Loader for JPEG 2000 codestreams using OpenJPH (High-Throughput JPEG 2000). + * + * This loader wraps the OpenJPH WebAssembly module to decode HTJ2K (High Throughput JPEG 2000) + * compressed image data. HTJ2K is defined in ISO/IEC 15444-15 / ITU-T T.814. + * + * Features: + * - Supports lossless and lossy JPEG 2000 compression + * - Handles 8-bit, 16-bit, and 32-bit data + * - Multiple component/channel support + * - Optional resolution reduction for faster decoding + * + * Usage: + * ```javascript + * import { JPHLoader } from 'three/examples/jsm/loaders/JPHLoader.js'; + * + * // Initialize with OpenJPH WASM module + * const loader = new JPHLoader(); + * + * // Load WASM module first (required) + * await loader.setWASMModule(openjphModule); + * + * // Load a J2K/JP2 file + * loader.load('texture.j2k', (texture) => { + * // Use texture + * }); + * + * // Or decode from buffer directly + * const texture = loader.parse(arrayBuffer); + * ``` + * + * OpenJPH WASM Module: + * The OpenJPH library must be compiled to WebAssembly using Emscripten. + * See: https://github.com/aous72/OpenJPH/tree/main/subprojects/js + * + * Build instructions: + * ```bash + * git clone https://github.com/aous72/OpenJPH.git + * cd OpenJPH + * mkdir build && cd build + * emcmake cmake -DCMAKE_BUILD_TYPE=Release .. + * emmake make + * ``` + * + * @author mrdoob / http://mrdoob.com/ + */ + +class JPHLoader extends Loader { + + constructor( manager ) { + + super( manager ); + + this.type = FloatType; + + } + + load( url, onLoad, onProgress, onError ) { + + const scope = this; + + const loader = new FileLoader( this.manager ); + loader.setPath( this.path ); + loader.setResponseType( 'arraybuffer' ); + loader.setRequestHeader( this.requestHeader ); + loader.setWithCredentials( this.withCredentials ); + + loader.load( url, function ( buffer ) { + + try { + + onLoad( scope.parse( buffer ) ); + + } catch ( e ) { + + if ( onError ) { + + onError( e ); + + } else { + + console.error( e ); + + } + + scope.manager.itemError( url ); + + } + + }, onProgress, onError ); + + } + + /** + * Parses JPEG 2000 codestream data and returns a DataTexture. + * + * @param {ArrayBuffer} buffer - The J2K/JP2 file data + * @param {Object} options - Decoding options + * @param {number} options.skipResolutionsRead - Number of resolutions to skip during read (default: 0) + * @param {number} options.skipResolutionsRecon - Number of resolutions to skip during reconstruction (default: 0) + * @returns {DataTexture} The decoded texture + */ + async parse( buffer, options = {} ) { + + // Lazy initialization of OpenJPH WASM module + let openjph; + + if ( ! _openjph ) { + + _openjph = new Promise( async ( resolve ) => { + + const openjph = await OpenJPHModule(); + resolve( openjph ); + + } ); + + } + + openjph = await _openjph; + + const { + skipResolutionsRead = 0, + skipResolutionsRecon = 0 + } = options; + + const wasm = openjph; + + // Create J2K data structure + const j2kData = wasm._create_j2c_data(); + + if ( ! j2kData ) { + + throw new Error( 'THREE.JPHLoader: Failed to create J2K data structure.' ); + + } + + try { + + // Allocate memory for input data + const dataPtr = wasm._malloc( buffer.byteLength ); + wasm.HEAPU8.set( new Uint8Array( buffer ), dataPtr ); + + // Initialize codestream + wasm._init_j2c_data( j2kData, dataPtr, buffer.byteLength ); + + // Free input data + wasm._free( dataPtr ); + + // Get codestream info + const width = wasm._get_width( j2kData ); + const height = wasm._get_height( j2kData ); + const numComponents = wasm._get_num_components( j2kData ); + const bitDepth = wasm._get_bit_depth( j2kData, 0 ); + const isSigned = wasm._is_signed( j2kData, 0 ); + + // Apply resolution reduction if requested + if ( skipResolutionsRead > 0 || skipResolutionsRecon > 0 ) { + + wasm._restrict_input_resolution( j2kData, skipResolutionsRead, skipResolutionsRecon ); + + } + + // Parse and prepare for decoding + wasm._parse_j2c_data( j2kData ); + + // Determine output data type + let outputData; + let textureType; + + if ( bitDepth <= 8 ) { + + // 8-bit output + outputData = new Uint8Array( width * height * numComponents ); + textureType = this.type; // Use default type + + } else if ( bitDepth <= 16 ) { + + // 16-bit output - use Half or Float + outputData = new Uint16Array( width * height * numComponents ); + textureType = HalfFloatType; + + } else { + + // 32-bit float output + outputData = new Float32Array( width * height * numComponents ); + textureType = FloatType; + + } + + // Decode scanlines + let offset = 0; + + for ( let y = 0; y < height; y ++ ) { + + for ( let c = 0; c < numComponents; c ++ ) { + + const linePtr = wasm._pull_j2c_line( j2kData ); + + if ( ! linePtr ) { + + throw new Error( `THREE.JPHLoader: Failed to decode line ${y}, component ${c}.` ); + + } + + // Copy line data + for ( let x = 0; x < width; x ++ ) { + + const value = wasm.HEAP32[ ( linePtr >> 2 ) + x ]; + + // Convert signed to unsigned if needed + if ( isSigned ) { + + outputData[ offset ++ ] = value + ( 1 << ( bitDepth - 1 ) ); + + } else { + + outputData[ offset ++ ] = value; + + } + + } + + } + + } + + // Release J2K data + wasm._release_j2c_data( j2kData ); + + // Create and configure texture + const texture = new DataTexture( outputData, width, height ); + texture.type = textureType; + texture.minFilter = LinearFilter; + texture.magFilter = LinearFilter; + texture.generateMipmaps = false; + texture.needsUpdate = true; + + // Set color space based on number of components + if ( numComponents >= 3 ) { + + texture.colorSpace = LinearSRGBColorSpace; + + } + + return texture; + + } catch ( error ) { + + // Clean up on error + if ( j2kData ) { + + wasm._release_j2c_data( j2kData ); + + } + + throw error; + + } + + } + + setDataType( value ) { + + this.type = value; + return this; + + } + +} + +export { JPHLoader }; diff --git a/examples/webgl_loader_exr_htj2k.html b/examples/webgl_loader_exr_htj2k.html new file mode 100644 index 00000000000000..29012b14450146 --- /dev/null +++ b/examples/webgl_loader_exr_htj2k.html @@ -0,0 +1,180 @@ + + + + three.js webgl - loaders - EXR with HTJ2K compression + + + + + + +
+ three.js - + EXR loader with HTJ2K compression support +
+ + + + + + + diff --git a/examples/webgl_loader_jph.html b/examples/webgl_loader_jph.html new file mode 100644 index 00000000000000..01f843a1eedbc0 --- /dev/null +++ b/examples/webgl_loader_jph.html @@ -0,0 +1,109 @@ + + + + three.js webgl - loaders - JPEG 2000 (HTJ2K) loader + + + + + + +
+ three.js - + OpenJPH JPEG 2000 (HTJ2K) loader +
+ + + + + + + From 36d4c2991e205977fff094b0d3cfd84e4b8c0188 Mon Sep 17 00:00:00 2001 From: mrdoob Date: Tue, 11 Nov 2025 00:46:24 -0800 Subject: [PATCH 2/2] Potential fix for code scanning alert no. 3729: Unused variable, import, function or class Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- examples/jsm/loaders/EXRLoader.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/jsm/loaders/EXRLoader.js b/examples/jsm/loaders/EXRLoader.js index 17deee5633d01a..5276439b732689 100644 --- a/examples/jsm/loaders/EXRLoader.js +++ b/examples/jsm/loaders/EXRLoader.js @@ -1825,8 +1825,7 @@ class EXRLoader extends DataTextureLoader { } // Read payload length - const payloadLength = dv.getUint32( offset, false ); // big-endian - offset += 4; + offset += 4; // skip payloadLength field (unused) // Read number of channels const numChannels = dv.getUint16( offset, false ); // big-endian