diff --git a/webgl/ktx2_encode_test/index.html b/webgl/ktx2_encode_test/index.html
index 1835ae7..10045bb 100644
--- a/webgl/ktx2_encode_test/index.html
+++ b/webgl/ktx2_encode_test/index.html
@@ -1,7 +1,13 @@
+
+
+
-
- Basis Universal KTX2 encoding and transcoding test
+ Basis Universal .KTX2 GPU Texture Encoding and Transcoding Test
- This demo uses the Basis C++ transcoder (compiled to Javascript using Emscripten) to transcode a .ktx2 file to FORMAT
- It also supports encoding .PNG files to .KTX2.
- Thanks to Evan Parker for providing webgl-texture-utils and this test bed.
+ This demo uses the Basis Universal C++ transcoder (compiled to WebAssembly using Emscripten) to transcode a .ktx2 file to FORMAT
+ It also supports encoding .PNG, .EXR or .HDR files to LDR or HDR .KTX2 files.
+ Thanks to Evan Parker for providing webgl-texture-utils and this test bed. Go back.
.ktx2 file:
@@ -593,47 +891,57 @@ function downloadEncodedFile()
- .png file:
-
-
+ .png/.exr/.hdr file:
+
+
+
- Debug:
-
+ Use UASTC HDR:
+
+
+
+ Use UASTC LDR:
+
+
+
+ Convert LDR images to linear light (UASTC HDR mode):
+
+
+ Debug output:
+
Compute Stats:
- sRGB:
+ Use sRGB/perceptual metrics:
- Mipmaps:
+ Generate Mipmaps:
- UASTC:
-
-
-
-
-
ETC1S Quality:
-
-
+
-
-
+
+
+
+
+
+ Scale:
+
+ 1
-
-
- NOTE: Your browser does not support several compressed texture format, so using RGB565.
-
-
-
+
+
+
+
+
diff --git a/webgl/ktx2_encode_test/renderer.js b/webgl/ktx2_encode_test/renderer.js
index 26f1a65..93a0ffe 100644
--- a/webgl/ktx2_encode_test/renderer.js
+++ b/webgl/ktx2_encode_test/renderer.js
@@ -106,11 +106,10 @@ Renderer.prototype.createDxtTexture = function(dxtData, width, height, format) {
height,
0,
dxtData);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
- //gl.generateMipmap(gl.TEXTURE_2D)
gl.bindTexture(gl.TEXTURE_2D, null);
return tex;
};
@@ -127,15 +126,35 @@ Renderer.prototype.createCompressedTexture = function(data, width, height, forma
height,
0,
data);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
- //gl.generateMipmap(gl.TEXTURE_2D)
gl.bindTexture(gl.TEXTURE_2D, null);
return tex;
};
+Renderer.prototype.createHalfRGBATexture = function(data, width, height, format) {
+ var gl = this.gl_;
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(
+ gl.TEXTURE_2D,
+ 0,
+ gl.RGBA,
+ width,
+ height,
+ 0,
+ gl.RGBA,
+ format,
+ data);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ return tex;
+};
Renderer.prototype.createRgb565Texture = function(rgb565Data, width, height) {
var gl = this.gl_;
@@ -151,17 +170,38 @@ Renderer.prototype.createRgb565Texture = function(rgb565Data, width, height) {
gl.RGB,
gl.UNSIGNED_SHORT_5_6_5,
rgb565Data);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ return tex;
+};
+
+Renderer.prototype.createRgbaTexture = function(rgbaData, width, height) {
+ var gl = this.gl_;
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(
+ gl.TEXTURE_2D,
+ 0,
+ gl.RGBA,
+ width,
+ height,
+ 0,
+ gl.RGBA,
+ gl.UNSIGNED_BYTE,
+ rgbaData);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
- //gl.generateMipmap(gl.TEXTURE_2D)
gl.bindTexture(gl.TEXTURE_2D, null);
return tex;
};
-Renderer.prototype.drawTexture = function(texture, width, height, mode) {
+Renderer.prototype.drawTexture = function(texture, width, height, mode, scale, linearToSRGBFlag) {
var gl = this.gl_;
// draw scene
gl.clearColor(0, 0, 0, 1);
@@ -179,8 +219,8 @@ Renderer.prototype.drawTexture = function(texture, width, height, mode) {
x = 1.0;
else if (mode == 2)
y = 1.0;
-
- gl.uniform4f(this.uniformLocations_.control, x, y, 0.0, 0.0);
+
+ gl.uniform4f(this.uniformLocations_.control, x, y, scale, linearToSRGBFlag ? 1.0 : 0.0);
gl.enableVertexAttribArray(this.attribLocations_.vert);
gl.bindBuffer(gl.ARRAY_BUFFER, this.quadVertexBuffer_);
@@ -229,9 +269,18 @@ Renderer.fragmentShaderSource_ = [
'uniform sampler2D texSampler;',
'uniform vec4 control;',
'varying vec2 v_texCoord;',
+
+ // Function to convert linear RGB to sRGB
+ 'vec3 linearToSrgb(vec3 linearRGB) {',
+ ' vec3 srgbLow = linearRGB * 12.92;',
+ ' vec3 srgbHigh = 1.055 * pow(linearRGB, vec3(1.0/2.4)) - 0.055;',
+ ' return clamp(mix(srgbLow, srgbHigh, step(0.0031308, linearRGB)), 0.0, 1.0);',
+ '}',
+
'void main() {',
' vec4 c;',
' c = texture2D(texSampler, v_texCoord);',
+ ' c.rgb *= control.z;',
' if (control.x > 0.0)',
' {',
' c.w = 1.0;',
@@ -240,6 +289,8 @@ Renderer.fragmentShaderSource_ = [
' {',
' c.rgb = c.aaa; c.w = 1.0;',
' }',
+ ' if (control.w > 0.0)',
+ ' c.rgb = linearToSrgb(c.rgb);',
' gl_FragColor = c;',
'}'
].join('\n');
diff --git a/webgl/transcoder/CMakeLists.txt b/webgl/transcoder/CMakeLists.txt
index 372653d..afdf83f 100644
--- a/webgl/transcoder/CMakeLists.txt
+++ b/webgl/transcoder/CMakeLists.txt
@@ -41,7 +41,21 @@ if (EMSCRIPTEN)
add_executable(basis_transcoder.js ${SRC_LIST})
- target_compile_definitions(basis_transcoder.js PRIVATE NDEBUG BASISD_SUPPORT_UASTC=1 BASISD_SUPPORT_BC7=1 BASISD_SUPPORT_ATC=0 BASISD_SUPPORT_ASTC_HIGHER_OPAQUE_QUALITY=0 BASISD_SUPPORT_PVRTC2=0 BASISD_SUPPORT_FXT1=0 BASISD_SUPPORT_ETC2_EAC_RG11=0 BASISU_SUPPORT_ENCODING=0 ${KTX2_DEFINITION} ${ZSTD_DEFINITION} )
+ target_compile_definitions(basis_transcoder.js PRIVATE NDEBUG
+ BASISD_SUPPORT_UASTC_HDR=1
+ BASISD_SUPPORT_UASTC=1
+ BASISD_SUPPORT_BC7=1
+ BASISD_SUPPORT_ATC=0
+ BASISD_SUPPORT_ASTC_HIGHER_OPAQUE_QUALITY=0
+ BASISD_SUPPORT_PVRTC2=0
+ BASISD_SUPPORT_FXT1=0
+ BASISD_SUPPORT_ETC2_EAC_RG11=0
+ BASISU_SUPPORT_ENCODING=0
+ BASISD_ENABLE_DEBUG_FLAGS=1
+ ${KTX2_DEFINITION}
+ ${ZSTD_DEFINITION}
+ )
+
target_compile_options(basis_transcoder.js PRIVATE -O3 -fno-strict-aliasing)
target_include_directories(basis_transcoder.js PRIVATE ../../transcoder)
diff --git a/webgl/transcoder/basis_wrappers.cpp b/webgl/transcoder/basis_wrappers.cpp
index 739f092..0e7f78f 100644
--- a/webgl/transcoder/basis_wrappers.cpp
+++ b/webgl/transcoder/basis_wrappers.cpp
@@ -1,7 +1,8 @@
// basis_wrappers.cpp - Wrappers to the C++ compressor and transcoder for WebAssembly/WebGL use.
+// This file exposes wrappers for transcoding and encoding .basis and .KTX2 files.
//
-// **Important**:
-// Compile with -fno-strict-aliasing
+// **Important**:
+// Compile with -fno-strict-aliasing (same as the Linux kernel).
// This code HAS NOT been tested with strict aliasing enabled.
// The "initializeBasis()" function MUST be called at least once before using either the compressor or transcoder.
//
@@ -10,11 +11,12 @@
// getFileDesc(), getImageDesc(), getImageLevelDesc(): These functions return low-level information about where compressed data is located for each image in a .basis file.
// This is useful for when you want to extract the compressed data and embed it into your own file formats, for container independent transcoding.
//
-// 2. Encoding (optional): See class basis_encoder. Encodes PNG or 32bpp images to .basis files in memory. Must compile with BASISU_SUPPORT_ENCODING=1.
+// 2. Encoding (optional): See class basis_encoder. Encodes LDR .PNG or 32bpp images, or HDR half-float/float or .EXR/.HDR images to .basis/.ktx2 files in memory.
+// Must compile with BASISU_SUPPORT_ENCODING=1.
// Requires basisu_transcoder.cpp as well as all the .cpp files in the "encoder" directory. Results in a larger WebAssembly executable.
//
-// 3. Low level transcoding/container independent transcoding: See class lowlevel_etc1s_image_transcoder or function transcodeUASTCImage(). For
-// transcoding raw compressed ETC1S/UASTC texture data from non-.basis files (say from KTX2) to GPU texture data.
+// 3. Low level transcoding/container independent transcoding: See class lowlevel_etc1s_image_transcoder or function transcodeUASTCImage().
+// For transcoding raw compressed ETC1S/UASTC LDR/UASTC HDR texture data from non-.basis files (say from KTX2) to GPU texture data.
//
// 4. Helpers, transcoder texture format information: See functions getBytesPerBlockOrPixel(), formatHasAlpha(), etc.
@@ -43,66 +45,67 @@ using namespace basisu;
static bool g_basis_initialized_flag;
+// Global one-time initialization. MUST be called before using any other functionality.
void basis_init()
{
#if BASISU_DEBUG_PRINTF
- printf("basis_init()\n");
-#endif
-
- if (g_basis_initialized_flag)
- return;
-
-#if BASISU_SUPPORT_ENCODING
- basisu_encoder_init();
+ printf("basis_init()\n");
#endif
- basisu_transcoder_init();
+ if (g_basis_initialized_flag)
+ return;
- g_basis_initialized_flag = true;
+#if BASISU_SUPPORT_ENCODING
+ basisu_encoder_init();
+#endif
+
+ basisu_transcoder_init();
+
+ g_basis_initialized_flag = true;
}
static void copy_from_jsbuffer(const emscripten::val& srcBuffer, basisu::vector& dstVec)
{
- unsigned int length = srcBuffer["length"].as();
+ unsigned int length = srcBuffer["length"].as();
- dstVec.resize(length);
+ dstVec.resize(length);
- emscripten::val memory = emscripten::val::module_property("HEAP8")["buffer"];
- emscripten::val memoryView = srcBuffer["constructor"].new_(memory, reinterpret_cast(dstVec.data()), length);
-
- // Copy the bytes from the Javascript buffer.
- memoryView.call("set", srcBuffer);
+ emscripten::val memory = emscripten::val::module_property("HEAP8")["buffer"];
+ emscripten::val memoryView = srcBuffer["constructor"].new_(memory, reinterpret_cast(dstVec.data()), length);
+
+ // Copy the bytes from the Javascript buffer.
+ memoryView.call("set", srcBuffer);
}
static bool copy_to_jsbuffer(const emscripten::val& dstBuffer, const basisu::vector& srcVec)
{
- if (srcVec.empty())
- {
-#if BASISU_DEBUG_PRINTF
- printf("copy_to_jsbuffer: Provided source buffer is empty\n");
+ if (srcVec.empty())
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("copy_to_jsbuffer: Provided source buffer is empty\n");
#endif
- return false;
- }
-
- // Make sure the provided buffer from Javascript is big enough. If not, bail.
- int dstBufferLen = dstBuffer["byteLength"].as();
-
- if (srcVec.size() > dstBufferLen)
- {
-#if BASISU_DEBUG_PRINTF
- printf("copy_to_jsbuffer: Provided destination buffer is too small (wanted %u bytes, got %u bytes)!\n", (uint32_t)srcVec.size(), dstBufferLen);
+ return false;
+ }
+
+ // Make sure the provided buffer from Javascript is big enough. If not, bail.
+ int dstBufferLen = dstBuffer["byteLength"].as();
+
+ if (srcVec.size() > dstBufferLen)
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("copy_to_jsbuffer: Provided destination buffer is too small (wanted %u bytes, got %u bytes)!\n", (uint32_t)srcVec.size(), dstBufferLen);
#endif
- assert(0);
- return false;
- }
+ assert(0);
+ return false;
+ }
- emscripten::val memory = emscripten::val::module_property("HEAP8")["buffer"];
- emscripten::val memoryView = emscripten::val::global("Uint8Array").new_(memory, reinterpret_cast(srcVec.data()), srcVec.size());
+ emscripten::val memory = emscripten::val::module_property("HEAP8")["buffer"];
+ emscripten::val memoryView = emscripten::val::global("Uint8Array").new_(memory, reinterpret_cast(srcVec.data()), srcVec.size());
- // Copy the bytes into the Javascript buffer.
- dstBuffer.call("set", memoryView);
-
- return true;
+ // Copy the bytes into the Javascript buffer.
+ dstBuffer.call("set", memoryView);
+
+ return true;
}
#define BASIS_MAGIC 0xDEADBEE1
@@ -110,1360 +113,1466 @@ static bool copy_to_jsbuffer(const emscripten::val& dstBuffer, const basisu::vec
struct basis_file_desc
{
- uint32_t m_version;
-
- uint32_t m_us_per_frame;
-
- uint32_t m_total_images;
-
- uint32_t m_userdata0;
- uint32_t m_userdata1;
-
- // Type of texture (cETC1S or cUASTC4x4)
- uint32_t m_tex_format; // basis_tex_format
-
- bool m_y_flipped;
- bool m_has_alpha_slices;
-
- // ETC1S endpoint codebook
- uint32_t m_num_endpoints;
- uint32_t m_endpoint_palette_ofs;
- uint32_t m_endpoint_palette_len;
+ uint32_t m_version;
- // ETC1S selector codebook
- uint32_t m_num_selectors;
- uint32_t m_selector_palette_ofs;
- uint32_t m_selector_palette_len;
+ uint32_t m_us_per_frame;
- // Huffman codelength tables
- uint32_t m_tables_ofs;
- uint32_t m_tables_len;
+ uint32_t m_total_images;
+
+ uint32_t m_userdata0;
+ uint32_t m_userdata1;
+
+ // Type of texture (cETC1S, cUASTC4x4, or cUASTC_HDR_4x4)
+ uint32_t m_tex_format; // basis_tex_format
+
+ bool m_y_flipped;
+ bool m_has_alpha_slices;
+
+ // ETC1S endpoint codebook
+ uint32_t m_num_endpoints;
+ uint32_t m_endpoint_palette_ofs;
+ uint32_t m_endpoint_palette_len;
+
+ // ETC1S selector codebook
+ uint32_t m_num_selectors;
+ uint32_t m_selector_palette_ofs;
+ uint32_t m_selector_palette_len;
+
+ // Huffman codelength tables
+ uint32_t m_tables_ofs;
+ uint32_t m_tables_len;
};
struct basis_image_desc
{
- uint32_t m_orig_width;
- uint32_t m_orig_height;
- uint32_t m_num_blocks_x;
- uint32_t m_num_blocks_y;
- uint32_t m_num_levels;
+ uint32_t m_orig_width;
+ uint32_t m_orig_height;
+ uint32_t m_num_blocks_x;
+ uint32_t m_num_blocks_y;
+ uint32_t m_num_levels;
- // Will be true if the image has alpha (for UASTC this may vary per-image)
- bool m_alpha_flag;
- bool m_iframe_flag;
+ // Will be true if the image has alpha (for UASTC this may vary per-image)
+ bool m_alpha_flag;
+ bool m_iframe_flag;
};
struct basis_image_level_desc
{
- // File offset/length of the compressed ETC1S or UASTC texture data.
- uint32_t m_rgb_file_ofs;
- uint32_t m_rgb_file_len;
+ // File offset/length of the compressed ETC1S or UASTC LDR/HDR texture data.
+ uint32_t m_rgb_file_ofs;
+ uint32_t m_rgb_file_len;
- // Optional alpha data file offset/length - will be 0's for UASTC or opaque ETC1S files.
- uint32_t m_alpha_file_ofs;
- uint32_t m_alpha_file_len;
+ // Optional alpha data file offset/length - will be 0's for UASTC LDR/HDR or opaque ETC1S files.
+ uint32_t m_alpha_file_ofs;
+ uint32_t m_alpha_file_len;
};
struct basis_file
{
- int m_magic = 0;
- basisu_transcoder m_transcoder;
- basisu::vector m_file;
+ int m_magic = 0;
+ basisu_transcoder m_transcoder;
+ basisu::vector m_file;
- basis_file(const emscripten::val& jsBuffer)
- : m_file([&]() {
- size_t byteLength = jsBuffer["byteLength"].as();
- return basisu::vector(byteLength);
- }())
- {
- if (!g_basis_initialized_flag)
- {
-#if BASISU_DEBUG_PRINTF
- printf("basis_file::basis_file: Must call basis_init() first!\n");
-#endif
- assert(0);
- return;
- }
-
- unsigned int length = jsBuffer["length"].as();
- emscripten::val memory = emscripten::val::module_property("HEAP8")["buffer"];
- emscripten::val memoryView = jsBuffer["constructor"].new_(memory, reinterpret_cast(m_file.data()), length);
- memoryView.call("set", jsBuffer);
+ basis_file(const emscripten::val& jsBuffer)
+ : m_file([&]() {
+ size_t byteLength = jsBuffer["byteLength"].as();
+ return basisu::vector(byteLength);
+ }())
+ {
+ if (!g_basis_initialized_flag)
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("basis_file::basis_file: Must call basis_init() first!\n");
+#endif
+ assert(0);
+ return;
+ }
- if (!m_transcoder.validate_header(m_file.data(), m_file.size()))
- {
-#if BASISU_DEBUG_PRINTF
- printf("basis_file::basis_file: m_transcoder.validate_header() failed!\n");
-#endif
- m_file.clear();
- }
+ unsigned int length = jsBuffer["length"].as();
+ emscripten::val memory = emscripten::val::module_property("HEAP8")["buffer"];
+ emscripten::val memoryView = jsBuffer["constructor"].new_(memory, reinterpret_cast(m_file.data()), length);
+ memoryView.call("set", jsBuffer);
- // Initialized after validation
- m_magic = BASIS_MAGIC;
- }
+ if (!m_transcoder.validate_header(m_file.data(), m_file.size()))
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("basis_file::basis_file: m_transcoder.validate_header() failed!\n");
+#endif
+ m_file.clear();
+ }
- void close()
- {
- assert(m_magic == BASIS_MAGIC);
- if (m_magic != BASIS_MAGIC)
- return;
+ // Initialized after validation
+ m_magic = BASIS_MAGIC;
+ }
- m_file.clear();
- }
+ void close()
+ {
+ assert(m_magic == BASIS_MAGIC);
+ if (m_magic != BASIS_MAGIC)
+ return;
- uint32_t getHasAlpha()
- {
- assert(m_magic == BASIS_MAGIC);
- if (m_magic != BASIS_MAGIC)
- return 0;
+ m_file.clear();
+ }
- basisu_image_level_info li;
- if (!m_transcoder.get_image_level_info(m_file.data(), m_file.size(), li, 0, 0))
- return 0;
+ uint32_t getHasAlpha()
+ {
+ assert(m_magic == BASIS_MAGIC);
+ if (m_magic != BASIS_MAGIC)
+ return 0;
- return li.m_alpha_flag;
- }
+ basisu_image_level_info li;
+ if (!m_transcoder.get_image_level_info(m_file.data(), m_file.size(), li, 0, 0))
+ return 0;
- uint32_t getNumImages()
- {
- assert(m_magic == BASIS_MAGIC);
- if (m_magic != BASIS_MAGIC)
- return 0;
+ return li.m_alpha_flag;
+ }
- return m_transcoder.get_total_images(m_file.data(), m_file.size());
- }
+ uint32_t getNumImages()
+ {
+ assert(m_magic == BASIS_MAGIC);
+ if (m_magic != BASIS_MAGIC)
+ return 0;
- uint32_t getNumLevels(uint32_t image_index)
- {
- assert(m_magic == BASIS_MAGIC);
- if (m_magic != BASIS_MAGIC)
- return 0;
+ return m_transcoder.get_total_images(m_file.data(), m_file.size());
+ }
- basisu_image_info ii;
- if (!m_transcoder.get_image_info(m_file.data(), m_file.size(), ii, image_index))
- return 0;
+ uint32_t getNumLevels(uint32_t image_index)
+ {
+ assert(m_magic == BASIS_MAGIC);
+ if (m_magic != BASIS_MAGIC)
+ return 0;
- return ii.m_total_levels;
- }
+ basisu_image_info ii;
+ if (!m_transcoder.get_image_info(m_file.data(), m_file.size(), ii, image_index))
+ return 0;
- uint32_t getImageWidth(uint32_t image_index, uint32_t level_index)
- {
- assert(m_magic == BASIS_MAGIC);
- if (m_magic != BASIS_MAGIC)
- return 0;
+ return ii.m_total_levels;
+ }
- uint32_t orig_width, orig_height, total_blocks;
- if (!m_transcoder.get_image_level_desc(m_file.data(), m_file.size(), image_index, level_index, orig_width, orig_height, total_blocks))
- return 0;
+ uint32_t getImageWidth(uint32_t image_index, uint32_t level_index)
+ {
+ assert(m_magic == BASIS_MAGIC);
+ if (m_magic != BASIS_MAGIC)
+ return 0;
- return orig_width;
- }
+ uint32_t orig_width, orig_height, total_blocks;
+ if (!m_transcoder.get_image_level_desc(m_file.data(), m_file.size(), image_index, level_index, orig_width, orig_height, total_blocks))
+ return 0;
- uint32_t getImageHeight(uint32_t image_index, uint32_t level_index)
- {
- assert(m_magic == BASIS_MAGIC);
- if (m_magic != BASIS_MAGIC)
- return 0;
+ return orig_width;
+ }
- uint32_t orig_width, orig_height, total_blocks;
- if (!m_transcoder.get_image_level_desc(m_file.data(), m_file.size(), image_index, level_index, orig_width, orig_height, total_blocks))
- return 0;
+ uint32_t getImageHeight(uint32_t image_index, uint32_t level_index)
+ {
+ assert(m_magic == BASIS_MAGIC);
+ if (m_magic != BASIS_MAGIC)
+ return 0;
- return orig_height;
- }
-
- basis_file_desc getFileDesc()
- {
- basis_file_desc result;
- memset(&result, 0, sizeof(result));
-
- assert(m_magic == BASIS_MAGIC);
- if (m_magic != BASIS_MAGIC)
- return result;
-
- basisu_file_info file_info;
-
- if (!m_transcoder.get_file_info(m_file.data(), m_file.size(), file_info))
- {
- assert(0);
- return result;
- }
-
- result.m_version = file_info.m_version;
- result.m_us_per_frame = file_info.m_us_per_frame;
- result.m_total_images = file_info.m_total_images;
- result.m_userdata0 = file_info.m_userdata0;
- result.m_userdata1 = file_info.m_userdata1;
- result.m_tex_format = static_cast(file_info.m_tex_format);
- result.m_y_flipped = file_info.m_y_flipped;
- result.m_has_alpha_slices = file_info.m_has_alpha_slices;
-
- result.m_num_endpoints = file_info.m_total_endpoints;
- result.m_endpoint_palette_ofs = file_info.m_endpoint_codebook_ofs;
- result.m_endpoint_palette_len = file_info.m_endpoint_codebook_size;
-
- result.m_num_selectors = file_info.m_total_selectors;
- result.m_selector_palette_ofs = file_info.m_selector_codebook_ofs;
- result.m_selector_palette_len = file_info.m_selector_codebook_size;
-
- result.m_tables_ofs = file_info.m_tables_ofs;
- result.m_tables_len = file_info.m_tables_size;
+ uint32_t orig_width, orig_height, total_blocks;
+ if (!m_transcoder.get_image_level_desc(m_file.data(), m_file.size(), image_index, level_index, orig_width, orig_height, total_blocks))
+ return 0;
- return result;
- }
-
- basis_image_desc getImageDesc(uint32_t image_index)
- {
- basis_image_desc result;
- memset(&result, 0, sizeof(result));
-
- assert(m_magic == BASIS_MAGIC);
- if (m_magic != BASIS_MAGIC)
- return result;
-
- basisu_image_info image_info;
-
- // bool get_image_info(const void *pData, uint32_t data_size, basisu_image_info &image_info, uint32_t image_index) const;
- if (!m_transcoder.get_image_info(m_file.data(), m_file.size(), image_info, image_index))
- {
- assert(0);
- return result;
- }
-
- result.m_orig_width = image_info.m_orig_width;
- result.m_orig_height = image_info.m_orig_height;
- result.m_num_blocks_x = image_info.m_num_blocks_x;
- result.m_num_blocks_y = image_info.m_num_blocks_y;
- result.m_num_levels = image_info.m_total_levels;
- result.m_alpha_flag = image_info.m_alpha_flag;
- result.m_iframe_flag = image_info.m_iframe_flag;
-
- return result;
- }
-
- basis_image_level_desc getImageLevelDesc(uint32_t image_index, uint32_t level_index)
- {
- basis_image_level_desc result;
- memset(&result, 0, sizeof(result));
-
- assert(m_magic == BASIS_MAGIC);
- if (m_magic != BASIS_MAGIC)
- return result;
-
- basisu_image_level_info image_info;
-
- if (!m_transcoder.get_image_level_info(m_file.data(), m_file.size(), image_info, image_index, level_index))
- {
- assert(0);
- return result;
- }
-
- result.m_rgb_file_ofs = image_info.m_rgb_file_ofs;
- result.m_rgb_file_len = image_info.m_rgb_file_len;
- result.m_alpha_file_ofs = image_info.m_alpha_file_ofs;
- result.m_alpha_file_len = image_info.m_alpha_file_len;
-
- return result;
- }
+ return orig_height;
+ }
- uint32_t getImageTranscodedSizeInBytes(uint32_t image_index, uint32_t level_index, uint32_t format)
- {
- assert(m_magic == BASIS_MAGIC);
- if (m_magic != BASIS_MAGIC)
- return 0;
+ basis_file_desc getFileDesc()
+ {
+ basis_file_desc result;
+ memset(&result, 0, sizeof(result));
- if (format >= (int)transcoder_texture_format::cTFTotalTextureFormats)
- return 0;
+ assert(m_magic == BASIS_MAGIC);
+ if (m_magic != BASIS_MAGIC)
+ return result;
- uint32_t orig_width, orig_height, total_blocks;
- if (!m_transcoder.get_image_level_desc(m_file.data(), m_file.size(), image_index, level_index, orig_width, orig_height, total_blocks))
- return 0;
+ basisu_file_info file_info;
- const transcoder_texture_format transcoder_format = static_cast(format);
+ if (!m_transcoder.get_file_info(m_file.data(), m_file.size(), file_info))
+ {
+ assert(0);
+ return result;
+ }
- if (basis_transcoder_format_is_uncompressed(transcoder_format))
- {
- // Uncompressed formats are just plain raster images.
- const uint32_t bytes_per_pixel = basis_get_uncompressed_bytes_per_pixel(transcoder_format);
- const uint32_t bytes_per_line = orig_width * bytes_per_pixel;
- const uint32_t bytes_per_slice = bytes_per_line * orig_height;
- return bytes_per_slice;
- }
- else
- {
- // Compressed formats are 2D arrays of blocks.
- const uint32_t bytes_per_block = basis_get_bytes_per_block_or_pixel(transcoder_format);
+ result.m_version = file_info.m_version;
+ result.m_us_per_frame = file_info.m_us_per_frame;
+ result.m_total_images = file_info.m_total_images;
+ result.m_userdata0 = file_info.m_userdata0;
+ result.m_userdata1 = file_info.m_userdata1;
+ result.m_tex_format = static_cast(file_info.m_tex_format);
+ result.m_y_flipped = file_info.m_y_flipped;
+ result.m_has_alpha_slices = file_info.m_has_alpha_slices;
- if (transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGB || transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGBA)
- {
- // For PVRTC1, Basis only writes (or requires) total_blocks * bytes_per_block. But GL requires extra padding for very small textures:
- // https://www.khronos.org/registry/OpenGL/extensions/IMG/IMG_texture_compression_pvrtc.txt
- const uint32_t width = (orig_width + 3) & ~3;
- const uint32_t height = (orig_height + 3) & ~3;
- const uint32_t size_in_bytes = (std::max(8U, width) * std::max(8U, height) * 4 + 7) / 8;
- return size_in_bytes;
- }
+ result.m_num_endpoints = file_info.m_total_endpoints;
+ result.m_endpoint_palette_ofs = file_info.m_endpoint_codebook_ofs;
+ result.m_endpoint_palette_len = file_info.m_endpoint_codebook_size;
- return total_blocks * bytes_per_block;
- }
- }
+ result.m_num_selectors = file_info.m_total_selectors;
+ result.m_selector_palette_ofs = file_info.m_selector_codebook_ofs;
+ result.m_selector_palette_len = file_info.m_selector_codebook_size;
- bool isUASTC()
- {
- assert(m_magic == BASIS_MAGIC);
- if (m_magic != BASIS_MAGIC)
- return false;
+ result.m_tables_ofs = file_info.m_tables_ofs;
+ result.m_tables_len = file_info.m_tables_size;
- return m_transcoder.get_tex_format(m_file.data(), m_file.size()) == basis_tex_format::cUASTC4x4;
- }
+ return result;
+ }
- uint32_t startTranscoding()
- {
- assert(m_magic == BASIS_MAGIC);
- if (m_magic != BASIS_MAGIC)
- return 0;
+ basis_image_desc getImageDesc(uint32_t image_index)
+ {
+ basis_image_desc result;
+ memset(&result, 0, sizeof(result));
- return m_transcoder.start_transcoding(m_file.data(), m_file.size());
- }
+ assert(m_magic == BASIS_MAGIC);
+ if (m_magic != BASIS_MAGIC)
+ return result;
- uint32_t transcodeImage(const emscripten::val& dst, uint32_t image_index, uint32_t level_index, uint32_t format, uint32_t unused, uint32_t get_alpha_for_opaque_formats)
- {
- (void)unused;
+ basisu_image_info image_info;
- assert(m_magic == BASIS_MAGIC);
- if (m_magic != BASIS_MAGIC)
- return 0;
+ // bool get_image_info(const void *pData, uint32_t data_size, basisu_image_info &image_info, uint32_t image_index) const;
+ if (!m_transcoder.get_image_info(m_file.data(), m_file.size(), image_info, image_index))
+ {
+ assert(0);
+ return result;
+ }
- if (format >= (int)transcoder_texture_format::cTFTotalTextureFormats)
- return 0;
+ result.m_orig_width = image_info.m_orig_width;
+ result.m_orig_height = image_info.m_orig_height;
+ result.m_num_blocks_x = image_info.m_num_blocks_x;
+ result.m_num_blocks_y = image_info.m_num_blocks_y;
+ result.m_num_levels = image_info.m_total_levels;
+ result.m_alpha_flag = image_info.m_alpha_flag;
+ result.m_iframe_flag = image_info.m_iframe_flag;
- const transcoder_texture_format transcoder_format = static_cast(format);
+ return result;
+ }
- uint32_t orig_width, orig_height, total_blocks;
- if (!m_transcoder.get_image_level_desc(m_file.data(), m_file.size(), image_index, level_index, orig_width, orig_height, total_blocks))
- return 0;
+ basis_image_level_desc getImageLevelDesc(uint32_t image_index, uint32_t level_index)
+ {
+ basis_image_level_desc result;
+ memset(&result, 0, sizeof(result));
- basisu::vector dst_data;
+ assert(m_magic == BASIS_MAGIC);
+ if (m_magic != BASIS_MAGIC)
+ return result;
- uint32_t flags = get_alpha_for_opaque_formats ? cDecodeFlagsTranscodeAlphaDataToOpaqueFormats : 0;
+ basisu_image_level_info image_info;
- uint32_t status;
+ if (!m_transcoder.get_image_level_info(m_file.data(), m_file.size(), image_info, image_index, level_index))
+ {
+ assert(0);
+ return result;
+ }
- if (basis_transcoder_format_is_uncompressed(transcoder_format))
- {
- const uint32_t bytes_per_pixel = basis_get_uncompressed_bytes_per_pixel(transcoder_format);
- const uint32_t bytes_per_line = orig_width * bytes_per_pixel;
- const uint32_t bytes_per_slice = bytes_per_line * orig_height;
+ result.m_rgb_file_ofs = image_info.m_rgb_file_ofs;
+ result.m_rgb_file_len = image_info.m_rgb_file_len;
+ result.m_alpha_file_ofs = image_info.m_alpha_file_ofs;
+ result.m_alpha_file_len = image_info.m_alpha_file_len;
- dst_data.resize(bytes_per_slice);
+ return result;
+ }
- status = m_transcoder.transcode_image_level(
- m_file.data(), m_file.size(), image_index, level_index,
- dst_data.data(), orig_width * orig_height,
- transcoder_format,
- flags,
- orig_width,
- nullptr,
- orig_height);
- }
- else
- {
- uint32_t bytes_per_block = basis_get_bytes_per_block_or_pixel(transcoder_format);
+ uint32_t getImageTranscodedSizeInBytes(uint32_t image_index, uint32_t level_index, uint32_t format)
+ {
+ assert(m_magic == BASIS_MAGIC);
+ if (m_magic != BASIS_MAGIC)
+ return 0;
- uint32_t required_size = total_blocks * bytes_per_block;
+ if (format >= (int)transcoder_texture_format::cTFTotalTextureFormats)
+ return 0;
- if (transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGB || transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGBA)
- {
- // For PVRTC1, Basis only writes (or requires) total_blocks * bytes_per_block. But GL requires extra padding for very small textures:
- // https://www.khronos.org/registry/OpenGL/extensions/IMG/IMG_texture_compression_pvrtc.txt
- // The transcoder will clear the extra bytes followed the used blocks to 0.
- const uint32_t width = (orig_width + 3) & ~3;
- const uint32_t height = (orig_height + 3) & ~3;
- required_size = (std::max(8U, width) * std::max(8U, height) * 4 + 7) / 8;
- assert(required_size >= total_blocks * bytes_per_block);
- }
+ uint32_t orig_width, orig_height, total_blocks;
+ if (!m_transcoder.get_image_level_desc(m_file.data(), m_file.size(), image_index, level_index, orig_width, orig_height, total_blocks))
+ return 0;
- dst_data.resize(required_size);
+ const transcoder_texture_format transcoder_format = static_cast(format);
- status = m_transcoder.transcode_image_level(
- m_file.data(), m_file.size(), image_index, level_index,
- dst_data.data(), dst_data.size() / bytes_per_block,
- static_cast(format),
- flags);
- }
+ if (basis_transcoder_format_is_uncompressed(transcoder_format))
+ {
+ // Uncompressed formats are just plain raster images.
+ const uint32_t bytes_per_pixel = basis_get_uncompressed_bytes_per_pixel(transcoder_format);
+ const uint32_t bytes_per_line = orig_width * bytes_per_pixel;
+ const uint32_t bytes_per_slice = bytes_per_line * orig_height;
+ return bytes_per_slice;
+ }
+ else
+ {
+ // Compressed formats are 2D arrays of blocks.
+ const uint32_t bytes_per_block = basis_get_bytes_per_block_or_pixel(transcoder_format);
- emscripten::val memory = emscripten::val::module_property("HEAP8")["buffer"];
- emscripten::val memoryView = emscripten::val::global("Uint8Array").new_(memory, reinterpret_cast(dst_data.data()), dst_data.size());
+ if (transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGB || transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGBA)
+ {
+ // For PVRTC1, Basis only writes (or requires) total_blocks * bytes_per_block. But GL requires extra padding for very small textures:
+ // https://www.khronos.org/registry/OpenGL/extensions/IMG/IMG_texture_compression_pvrtc.txt
+ const uint32_t width = (orig_width + 3) & ~3;
+ const uint32_t height = (orig_height + 3) & ~3;
+ const uint32_t size_in_bytes = (std::max(8U, width) * std::max(8U, height) * 4 + 7) / 8;
+ return size_in_bytes;
+ }
- dst.call("set", memoryView);
- return status;
- }
+ return total_blocks * bytes_per_block;
+ }
+ }
+
+ bool isUASTC()
+ {
+ assert(m_magic == BASIS_MAGIC);
+ if (m_magic != BASIS_MAGIC)
+ return false;
+
+ return m_transcoder.get_tex_format(m_file.data(), m_file.size()) == basis_tex_format::cUASTC4x4;
+ }
+
+ // Returns true if the texture is UASTC HDR. In this case, it can only be transcoded to BC6H, ASTC 4x4 HDR, or half-float RGB/RGBA images.
+ bool isHDR()
+ {
+ assert(m_magic == BASIS_MAGIC);
+ if (m_magic != BASIS_MAGIC)
+ return false;
+
+ return m_transcoder.get_tex_format(m_file.data(), m_file.size()) == basis_tex_format::cUASTC_HDR_4x4;
+ }
+
+ uint32_t startTranscoding()
+ {
+ assert(m_magic == BASIS_MAGIC);
+ if (m_magic != BASIS_MAGIC)
+ return 0;
+
+ return m_transcoder.start_transcoding(m_file.data(), m_file.size());
+ }
+
+ uint32_t transcodeImage(const emscripten::val& dst, uint32_t image_index, uint32_t level_index, uint32_t format, uint32_t unused, uint32_t get_alpha_for_opaque_formats)
+ {
+ (void)unused;
+
+ assert(m_magic == BASIS_MAGIC);
+ if (m_magic != BASIS_MAGIC)
+ return 0;
+
+ if (format >= (int)transcoder_texture_format::cTFTotalTextureFormats)
+ return 0;
+
+ const transcoder_texture_format transcoder_format = static_cast(format);
+
+ uint32_t orig_width, orig_height, total_blocks;
+ if (!m_transcoder.get_image_level_desc(m_file.data(), m_file.size(), image_index, level_index, orig_width, orig_height, total_blocks))
+ return 0;
+
+ basisu::vector dst_data;
+
+ uint32_t flags = get_alpha_for_opaque_formats ? cDecodeFlagsTranscodeAlphaDataToOpaqueFormats : 0;
+
+ uint32_t status;
+
+ if (basis_transcoder_format_is_uncompressed(transcoder_format))
+ {
+ const uint32_t bytes_per_pixel = basis_get_uncompressed_bytes_per_pixel(transcoder_format);
+ const uint32_t bytes_per_line = orig_width * bytes_per_pixel;
+ const uint32_t bytes_per_slice = bytes_per_line * orig_height;
+
+ dst_data.resize(bytes_per_slice);
+
+ status = m_transcoder.transcode_image_level(
+ m_file.data(), m_file.size(), image_index, level_index,
+ dst_data.data(), orig_width * orig_height,
+ transcoder_format,
+ flags,
+ orig_width,
+ nullptr,
+ orig_height);
+ }
+ else
+ {
+ uint32_t bytes_per_block = basis_get_bytes_per_block_or_pixel(transcoder_format);
+
+ uint32_t required_size = total_blocks * bytes_per_block;
+
+ if (transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGB || transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGBA)
+ {
+ // For PVRTC1, Basis only writes (or requires) total_blocks * bytes_per_block. But GL requires extra padding for very small textures:
+ // https://www.khronos.org/registry/OpenGL/extensions/IMG/IMG_texture_compression_pvrtc.txt
+ // The transcoder will clear the extra bytes followed the used blocks to 0.
+ const uint32_t width = (orig_width + 3) & ~3;
+ const uint32_t height = (orig_height + 3) & ~3;
+ required_size = (std::max(8U, width) * std::max(8U, height) * 4 + 7) / 8;
+ assert(required_size >= total_blocks * bytes_per_block);
+ }
+
+ dst_data.resize(required_size);
+
+ status = m_transcoder.transcode_image_level(
+ m_file.data(), m_file.size(), image_index, level_index,
+ dst_data.data(), dst_data.size() / bytes_per_block,
+ static_cast(format),
+ flags);
+ }
+
+ emscripten::val memory = emscripten::val::module_property("HEAP8")["buffer"];
+ emscripten::val memoryView = emscripten::val::global("Uint8Array").new_(memory, reinterpret_cast(dst_data.data()), dst_data.size());
+
+ dst.call("set", memoryView);
+ return status;
+ }
};
#if BASISD_SUPPORT_KTX2
struct ktx2_header_js
{
- uint32_t m_vk_format;
- uint32_t m_type_size;
- uint32_t m_pixel_width;
- uint32_t m_pixel_height;
- uint32_t m_pixel_depth;
- uint32_t m_layer_count;
- uint32_t m_face_count;
- uint32_t m_level_count;
- uint32_t m_supercompression_scheme;
- uint32_t m_dfd_byte_offset;
- uint32_t m_dfd_byte_length;
- uint32_t m_kvd_byte_offset;
- uint32_t m_kvd_byte_length;
- uint32_t m_sgd_byte_offset;
- uint32_t m_sgd_byte_length;
+ uint32_t m_vk_format;
+ uint32_t m_type_size;
+ uint32_t m_pixel_width;
+ uint32_t m_pixel_height;
+ uint32_t m_pixel_depth;
+ uint32_t m_layer_count;
+ uint32_t m_face_count;
+ uint32_t m_level_count;
+ uint32_t m_supercompression_scheme;
+ uint32_t m_dfd_byte_offset;
+ uint32_t m_dfd_byte_length;
+ uint32_t m_kvd_byte_offset;
+ uint32_t m_kvd_byte_length;
+ uint32_t m_sgd_byte_offset;
+ uint32_t m_sgd_byte_length;
};
struct ktx2_file
{
- int m_magic = 0;
- basist::ktx2_transcoder m_transcoder;
- basisu::vector m_file;
- bool m_is_valid = false;
+ int m_magic = 0;
+ basist::ktx2_transcoder m_transcoder;
+ basisu::vector m_file;
+ bool m_is_valid = false;
- ktx2_file(const emscripten::val& jsBuffer)
- : m_file([&]() {
- size_t byteLength = jsBuffer["byteLength"].as();
- return basisu::vector(byteLength);
- }())
- {
- if (!g_basis_initialized_flag)
- {
-#if BASISU_DEBUG_PRINTF
- printf("basis_file::basis_file: Must call basis_init() first!\n");
-#endif
- assert(0);
- return;
- }
-
- unsigned int length = jsBuffer["length"].as();
- emscripten::val memory = emscripten::val::module_property("HEAP8")["buffer"];
- emscripten::val memoryView = jsBuffer["constructor"].new_(memory, reinterpret_cast(m_file.data()), length);
- memoryView.call("set", jsBuffer);
-
- if (!m_transcoder.init(m_file.data(), m_file.size()))
- {
-#if BASISU_DEBUG_PRINTF
- printf("m_transcoder.init() failed!\n");
+ ktx2_file(const emscripten::val& jsBuffer)
+ : m_file([&]() {
+ size_t byteLength = jsBuffer["byteLength"].as();
+ return basisu::vector(byteLength);
+ }())
+ {
+ if (!g_basis_initialized_flag)
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("basis_file::basis_file: Must call basis_init() first!\n");
#endif
- assert(0);
-
- m_file.clear();
- }
-
- m_is_valid = true;
-
- // Initialized after validation
- m_magic = KTX2_MAGIC;
- }
-
- bool isValid()
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return false;
-
- return m_is_valid;
- }
-
- void close()
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return;
-
- m_file.clear();
- m_transcoder.clear();
- }
-
- uint32_t getDFDSize()
- {
- return m_transcoder.get_dfd().size();
- }
-
- uint32_t getDFD(const emscripten::val& dst)
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return 0;
-
- const uint8_vec &dst_data = m_transcoder.get_dfd();
-
- if (dst_data.size())
- return copy_to_jsbuffer(dst, dst_data);
-
- return 1;
- }
-
- ktx2_header_js getHeader()
- {
- ktx2_header_js hdr;
- memset(&hdr, 0, sizeof(hdr));
-
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return hdr;
-
- const basist::ktx2_header& h = m_transcoder.get_header();
-
- hdr.m_vk_format = h.m_vk_format;
- hdr.m_type_size = h.m_type_size;
- hdr.m_pixel_width = h.m_pixel_width;
- hdr.m_pixel_height = h.m_pixel_height;
- hdr.m_pixel_depth = h.m_pixel_depth;
- hdr.m_layer_count = h.m_layer_count;
- hdr.m_face_count = h.m_face_count;
- hdr.m_level_count = h.m_level_count;
- hdr.m_supercompression_scheme = h.m_supercompression_scheme;
- hdr.m_dfd_byte_offset = h.m_dfd_byte_offset;
- hdr.m_dfd_byte_length = h.m_dfd_byte_length;
- hdr.m_kvd_byte_offset = h.m_kvd_byte_offset;
- hdr.m_kvd_byte_length = h.m_kvd_byte_length;
-
- // emscripten doesn't support binding uint64_t for some reason
- assert(h.m_sgd_byte_offset <= UINT32_MAX);
- assert(h.m_sgd_byte_length <= UINT32_MAX);
- hdr.m_sgd_byte_offset = (uint32_t)h.m_sgd_byte_offset;
- hdr.m_sgd_byte_length = (uint32_t)h.m_sgd_byte_length;
-
- return hdr;
- }
-
- bool hasKey(std::string key_name)
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return false;
-
- return m_transcoder.find_key(key_name) != nullptr;
- }
-
- uint32_t getTotalKeys()
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return 0;
-
- return m_transcoder.get_key_values().size();
- }
-
- std::string getKey(uint32_t index)
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return std::string("");
-
- return std::string((const char*)m_transcoder.get_key_values()[index].m_key.data());
- }
-
- uint32_t getKeyValueSize(std::string key_name)
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return 0;
-
- const uint8_vec* p = m_transcoder.find_key(key_name);
- return p ? p->size() : 0;
- }
-
- uint32_t getKeyValue(std::string key_name, const emscripten::val& dst)
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return 0;
-
- const uint8_vec* p = m_transcoder.find_key(key_name);
- if (!p)
- return 0;
-
- if (p->size())
- return copy_to_jsbuffer(dst, *p);
-
- return 1;
- }
-
- uint32_t getWidth()
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return 0;
- return m_transcoder.get_width();
- }
-
- uint32_t getHeight()
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return 0;
- return m_transcoder.get_height();
- }
-
- uint32_t getFaces()
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return 0;
- return m_transcoder.get_faces();
- }
-
- uint32_t getLayers()
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return 0;
- return m_transcoder.get_layers();
- }
-
- uint32_t getLevels()
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return 0;
- return m_transcoder.get_levels();
- }
-
- uint32_t getFormat()
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return 0;
- return (uint32_t)m_transcoder.get_format();
- }
-
- bool isUASTC()
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return false;
- return m_transcoder.is_uastc();
- }
-
- bool isETC1S()
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return false;
- return m_transcoder.is_etc1s();
- }
-
- bool getHasAlpha()
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return false;
- return m_transcoder.get_has_alpha();
- }
-
- uint32_t getDFDColorModel()
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return 0;
- return m_transcoder.get_dfd_color_model();
- }
-
- uint32_t getDFDColorPrimaries()
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return 0;
- return m_transcoder.get_dfd_color_primaries();
- }
-
- uint32_t getDFDTransferFunc()
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return 0;
- return m_transcoder.get_dfd_transfer_func();
- }
-
- uint32_t getDFDFlags()
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return 0;
- return m_transcoder.get_dfd_flags();
- }
-
- uint32_t getDFDTotalSamples()
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return 0;
- return m_transcoder.get_dfd_total_samples();
- }
-
- uint32_t getDFDChannelID0()
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return 0;
- return m_transcoder.get_dfd_channel_id0();
- }
-
- uint32_t getDFDChannelID1()
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return 0;
- return m_transcoder.get_dfd_channel_id1();
- }
-
- // isVideo() will return true if there was a KTXanimData key, or if (after calling start_transcoding()) there were any P-frames on ETC1S files.
- bool isVideo()
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return 0;
- return m_transcoder.is_video();
- }
-
- // startTranscoding() must be called before calling getETC1SImageDescImageFlags().
- uint32_t getETC1SImageDescImageFlags(uint32_t level_index, uint32_t layer_index, uint32_t face_index)
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return 0;
-
- return m_transcoder.get_etc1s_image_descs_image_flags(level_index, layer_index, face_index);
- }
-
- ktx2_image_level_info getImageLevelInfo(uint32_t level_index, uint32_t layer_index, uint32_t face_index)
- {
- ktx2_image_level_info info;
- memset(&info, 0, sizeof(info));
-
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return info;
-
- if (!m_transcoder.get_image_level_info(info, level_index, layer_index, face_index))
- {
- assert(0);
- return info;
- }
-
- return info;
- }
-
- uint32_t getImageTranscodedSizeInBytes(uint32_t level_index, uint32_t layer_index, uint32_t face_index, uint32_t format)
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return 0;
-
- if (format >= (int)transcoder_texture_format::cTFTotalTextureFormats)
- return 0;
-
- ktx2_image_level_info info;
- if (!m_transcoder.get_image_level_info(info, level_index, layer_index, face_index))
- return 0;
-
- uint32_t orig_width = info.m_orig_width, orig_height = info.m_orig_height, total_blocks = info.m_total_blocks;
-
- const transcoder_texture_format transcoder_format = static_cast(format);
-
- if (basis_transcoder_format_is_uncompressed(transcoder_format))
- {
- // Uncompressed formats are just plain raster images.
- const uint32_t bytes_per_pixel = basis_get_uncompressed_bytes_per_pixel(transcoder_format);
- const uint32_t bytes_per_line = orig_width * bytes_per_pixel;
- const uint32_t bytes_per_slice = bytes_per_line * orig_height;
- return bytes_per_slice;
- }
- else
- {
- // Compressed formats are 2D arrays of blocks.
- const uint32_t bytes_per_block = basis_get_bytes_per_block_or_pixel(transcoder_format);
-
- if (transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGB || transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGBA)
- {
- // For PVRTC1, Basis only writes (or requires) total_blocks * bytes_per_block. But GL requires extra padding for very small textures:
- // https://www.khronos.org/registry/OpenGL/extensions/IMG/IMG_texture_compression_pvrtc.txt
- const uint32_t width = (orig_width + 3) & ~3;
- const uint32_t height = (orig_height + 3) & ~3;
- const uint32_t size_in_bytes = (std::max(8U, width) * std::max(8U, height) * 4 + 7) / 8;
- return size_in_bytes;
- }
-
- return total_blocks * bytes_per_block;
- }
- }
-
- // Must be called before transcodeImage() can be called.
- // On ETC1S files this method decompresses the ETC1S global data, along with fetching the ETC1S image desc array, so it's not free to call.
- uint32_t startTranscoding()
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return 0;
-
- return m_transcoder.start_transcoding();
- }
-
- // get_alpha_for_opaque_formats defaults to false
- // channel0/channel1 default to -1
- uint32_t transcodeImage(const emscripten::val& dst, uint32_t level_index, uint32_t layer_index, uint32_t face_index, uint32_t format, uint32_t get_alpha_for_opaque_formats, int channel0, int channel1)
- {
- assert(m_magic == KTX2_MAGIC);
- if (m_magic != KTX2_MAGIC)
- return 0;
-
- if (format >= (int)transcoder_texture_format::cTFTotalTextureFormats)
- return 0;
-
- const transcoder_texture_format transcoder_format = static_cast(format);
-
- ktx2_image_level_info info;
- if (!m_transcoder.get_image_level_info(info, level_index, layer_index, face_index))
- return 0;
-
- uint32_t orig_width = info.m_orig_width, orig_height = info.m_orig_height, total_blocks = info.m_total_blocks;
-
- basisu::vector dst_data;
-
- uint32_t flags = get_alpha_for_opaque_formats ? cDecodeFlagsTranscodeAlphaDataToOpaqueFormats : 0;
-
- uint32_t status;
-
- if (basis_transcoder_format_is_uncompressed(transcoder_format))
- {
- const uint32_t bytes_per_pixel = basis_get_uncompressed_bytes_per_pixel(transcoder_format);
- const uint32_t bytes_per_line = orig_width * bytes_per_pixel;
- const uint32_t bytes_per_slice = bytes_per_line * orig_height;
-
- dst_data.resize(bytes_per_slice);
-
- status = m_transcoder.transcode_image_level(
- level_index, layer_index, face_index,
- dst_data.data(), orig_width * orig_height,
- transcoder_format,
- flags,
- orig_width,
- orig_height,
- channel0, channel1,
- nullptr);
- }
- else
- {
- uint32_t bytes_per_block = basis_get_bytes_per_block_or_pixel(transcoder_format);
-
- uint32_t required_size = total_blocks * bytes_per_block;
-
- if (transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGB || transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGBA)
- {
- // For PVRTC1, Basis only writes (or requires) total_blocks * bytes_per_block. But GL requires extra padding for very small textures:
- // https://www.khronos.org/registry/OpenGL/extensions/IMG/IMG_texture_compression_pvrtc.txt
- // The transcoder will clear the extra bytes followed the used blocks to 0.
- const uint32_t width = (orig_width + 3) & ~3;
- const uint32_t height = (orig_height + 3) & ~3;
- required_size = (std::max(8U, width) * std::max(8U, height) * 4 + 7) / 8;
- assert(required_size >= total_blocks * bytes_per_block);
- }
-
- dst_data.resize(required_size);
-
- status = m_transcoder.transcode_image_level(
- level_index, layer_index, face_index,
- dst_data.data(), dst_data.size() / bytes_per_block,
- static_cast(format),
- flags,
- 0,
- 0,
- channel0, channel1,
- nullptr);
- }
-
- emscripten::val memory = emscripten::val::module_property("HEAP8")["buffer"];
- emscripten::val memoryView = emscripten::val::global("Uint8Array").new_(memory, reinterpret_cast(dst_data.data()), dst_data.size());
-
- dst.call("set", memoryView);
- return status;
- }
+ assert(0);
+ return;
+ }
+
+ unsigned int length = jsBuffer["length"].as();
+ emscripten::val memory = emscripten::val::module_property("HEAP8")["buffer"];
+ emscripten::val memoryView = jsBuffer["constructor"].new_(memory, reinterpret_cast(m_file.data()), length);
+ memoryView.call("set", jsBuffer);
+
+ if (!m_transcoder.init(m_file.data(), m_file.size()))
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("m_transcoder.init() failed!\n");
+#endif
+ assert(0);
+
+ m_file.clear();
+ }
+
+ m_is_valid = true;
+
+ // Initialized after validation
+ m_magic = KTX2_MAGIC;
+ }
+
+ bool isValid()
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return false;
+
+ return m_is_valid;
+ }
+
+ void close()
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return;
+
+ m_file.clear();
+ m_transcoder.clear();
+ }
+
+ uint32_t getDFDSize()
+ {
+ return m_transcoder.get_dfd().size();
+ }
+
+ uint32_t getDFD(const emscripten::val& dst)
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return 0;
+
+ const uint8_vec &dst_data = m_transcoder.get_dfd();
+
+ if (dst_data.size())
+ return copy_to_jsbuffer(dst, dst_data);
+
+ return 1;
+ }
+
+ ktx2_header_js getHeader()
+ {
+ ktx2_header_js hdr;
+ memset(&hdr, 0, sizeof(hdr));
+
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return hdr;
+
+ const basist::ktx2_header& h = m_transcoder.get_header();
+
+ hdr.m_vk_format = h.m_vk_format;
+ hdr.m_type_size = h.m_type_size;
+ hdr.m_pixel_width = h.m_pixel_width;
+ hdr.m_pixel_height = h.m_pixel_height;
+ hdr.m_pixel_depth = h.m_pixel_depth;
+ hdr.m_layer_count = h.m_layer_count;
+ hdr.m_face_count = h.m_face_count;
+ hdr.m_level_count = h.m_level_count;
+ hdr.m_supercompression_scheme = h.m_supercompression_scheme;
+ hdr.m_dfd_byte_offset = h.m_dfd_byte_offset;
+ hdr.m_dfd_byte_length = h.m_dfd_byte_length;
+ hdr.m_kvd_byte_offset = h.m_kvd_byte_offset;
+ hdr.m_kvd_byte_length = h.m_kvd_byte_length;
+
+ // emscripten doesn't support binding uint64_t for some reason
+ assert(h.m_sgd_byte_offset <= UINT32_MAX);
+ assert(h.m_sgd_byte_length <= UINT32_MAX);
+ hdr.m_sgd_byte_offset = (uint32_t)h.m_sgd_byte_offset;
+ hdr.m_sgd_byte_length = (uint32_t)h.m_sgd_byte_length;
+
+ return hdr;
+ }
+
+ bool hasKey(std::string key_name)
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return false;
+
+ return m_transcoder.find_key(key_name) != nullptr;
+ }
+
+ uint32_t getTotalKeys()
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return 0;
+
+ return m_transcoder.get_key_values().size();
+ }
+
+ std::string getKey(uint32_t index)
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return std::string("");
+
+ return std::string((const char*)m_transcoder.get_key_values()[index].m_key.data());
+ }
+
+ uint32_t getKeyValueSize(std::string key_name)
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return 0;
+
+ const uint8_vec* p = m_transcoder.find_key(key_name);
+ return p ? p->size() : 0;
+ }
+
+ uint32_t getKeyValue(std::string key_name, const emscripten::val& dst)
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return 0;
+
+ const uint8_vec* p = m_transcoder.find_key(key_name);
+ if (!p)
+ return 0;
+
+ if (p->size())
+ return copy_to_jsbuffer(dst, *p);
+
+ return 1;
+ }
+
+ uint32_t getWidth()
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return 0;
+ return m_transcoder.get_width();
+ }
+
+ uint32_t getHeight()
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return 0;
+ return m_transcoder.get_height();
+ }
+
+ uint32_t getFaces()
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return 0;
+ return m_transcoder.get_faces();
+ }
+
+ uint32_t getLayers()
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return 0;
+ return m_transcoder.get_layers();
+ }
+
+ uint32_t getLevels()
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return 0;
+ return m_transcoder.get_levels();
+ }
+
+ // Returns cETC1S, cUASTC4x4, or cUASTC_HDR_4x4.
+ uint32_t getFormat()
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return 0;
+ return (uint32_t)m_transcoder.get_format();
+ }
+
+ // Returns true if the texture is UASTC LDR (and not HDR - see isHDR()).
+ bool isUASTC()
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return false;
+ return m_transcoder.is_uastc();
+ }
+
+ bool isETC1S()
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return false;
+ return m_transcoder.is_etc1s();
+ }
+
+ // Returns true if the texture is UASTC HDR. In this case, it can only be transcoded to BC6H, ASTC 4x4 HDR, or half-float RGB/RGBA images.
+ bool isHDR()
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return false;
+ return m_transcoder.is_hdr();
+ }
+
+ bool getHasAlpha()
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return false;
+ return m_transcoder.get_has_alpha();
+ }
+
+ uint32_t getDFDColorModel()
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return 0;
+ return m_transcoder.get_dfd_color_model();
+ }
+
+ uint32_t getDFDColorPrimaries()
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return 0;
+ return m_transcoder.get_dfd_color_primaries();
+ }
+
+ uint32_t getDFDTransferFunc()
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return 0;
+ return m_transcoder.get_dfd_transfer_func();
+ }
+
+ uint32_t getDFDFlags()
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return 0;
+ return m_transcoder.get_dfd_flags();
+ }
+
+ uint32_t getDFDTotalSamples()
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return 0;
+ return m_transcoder.get_dfd_total_samples();
+ }
+
+ uint32_t getDFDChannelID0()
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return 0;
+ return m_transcoder.get_dfd_channel_id0();
+ }
+
+ uint32_t getDFDChannelID1()
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return 0;
+ return m_transcoder.get_dfd_channel_id1();
+ }
+
+ // isVideo() will return true if there was a KTXanimData key, or if (after calling start_transcoding()) there were any P-frames on ETC1S files.
+ bool isVideo()
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return 0;
+ return m_transcoder.is_video();
+ }
+
+ // startTranscoding() must be called before calling getETC1SImageDescImageFlags().
+ uint32_t getETC1SImageDescImageFlags(uint32_t level_index, uint32_t layer_index, uint32_t face_index)
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return 0;
+
+ return m_transcoder.get_etc1s_image_descs_image_flags(level_index, layer_index, face_index);
+ }
+
+ ktx2_image_level_info getImageLevelInfo(uint32_t level_index, uint32_t layer_index, uint32_t face_index)
+ {
+ ktx2_image_level_info info;
+ memset(&info, 0, sizeof(info));
+
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return info;
+
+ if (!m_transcoder.get_image_level_info(info, level_index, layer_index, face_index))
+ {
+ assert(0);
+ return info;
+ }
+
+ return info;
+ }
+
+ uint32_t getImageTranscodedSizeInBytes(uint32_t level_index, uint32_t layer_index, uint32_t face_index, uint32_t format)
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return 0;
+
+ if (format >= (int)transcoder_texture_format::cTFTotalTextureFormats)
+ return 0;
+
+ ktx2_image_level_info info;
+ if (!m_transcoder.get_image_level_info(info, level_index, layer_index, face_index))
+ return 0;
+
+ uint32_t orig_width = info.m_orig_width, orig_height = info.m_orig_height, total_blocks = info.m_total_blocks;
+
+ const transcoder_texture_format transcoder_format = static_cast(format);
+
+ if (basis_transcoder_format_is_uncompressed(transcoder_format))
+ {
+ // Uncompressed formats are just plain raster images.
+ const uint32_t bytes_per_pixel = basis_get_uncompressed_bytes_per_pixel(transcoder_format);
+ const uint32_t bytes_per_line = orig_width * bytes_per_pixel;
+ const uint32_t bytes_per_slice = bytes_per_line * orig_height;
+ return bytes_per_slice;
+ }
+ else
+ {
+ // Compressed formats are 2D arrays of blocks.
+ const uint32_t bytes_per_block = basis_get_bytes_per_block_or_pixel(transcoder_format);
+
+ if (transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGB || transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGBA)
+ {
+ // For PVRTC1, Basis only writes (or requires) total_blocks * bytes_per_block. But GL requires extra padding for very small textures:
+ // https://www.khronos.org/registry/OpenGL/extensions/IMG/IMG_texture_compression_pvrtc.txt
+ const uint32_t width = (orig_width + 3) & ~3;
+ const uint32_t height = (orig_height + 3) & ~3;
+ const uint32_t size_in_bytes = (std::max(8U, width) * std::max(8U, height) * 4 + 7) / 8;
+ return size_in_bytes;
+ }
+
+ return total_blocks * bytes_per_block;
+ }
+ }
+
+ // Must be called before transcodeImage() can be called.
+ // On ETC1S files this method decompresses the ETC1S global data, along with fetching the ETC1S image desc array, so it's not free to call.
+ uint32_t startTranscoding()
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return 0;
+
+ return m_transcoder.start_transcoding();
+ }
+
+ // get_alpha_for_opaque_formats defaults to false
+ // channel0/channel1 default to -1
+ uint32_t transcodeImage(const emscripten::val& dst, uint32_t level_index, uint32_t layer_index, uint32_t face_index, uint32_t format, uint32_t get_alpha_for_opaque_formats, int channel0, int channel1)
+ {
+ assert(m_magic == KTX2_MAGIC);
+ if (m_magic != KTX2_MAGIC)
+ return 0;
+
+ if (format >= (int)transcoder_texture_format::cTFTotalTextureFormats)
+ return 0;
+
+ const transcoder_texture_format transcoder_format = static_cast(format);
+
+ ktx2_image_level_info info;
+ if (!m_transcoder.get_image_level_info(info, level_index, layer_index, face_index))
+ return 0;
+
+ uint32_t orig_width = info.m_orig_width, orig_height = info.m_orig_height, total_blocks = info.m_total_blocks;
+
+ basisu::vector dst_data;
+
+ uint32_t flags = get_alpha_for_opaque_formats ? cDecodeFlagsTranscodeAlphaDataToOpaqueFormats : 0;
+
+ uint32_t status;
+
+ if (basis_transcoder_format_is_uncompressed(transcoder_format))
+ {
+ const uint32_t bytes_per_pixel = basis_get_uncompressed_bytes_per_pixel(transcoder_format);
+ const uint32_t bytes_per_line = orig_width * bytes_per_pixel;
+ const uint32_t bytes_per_slice = bytes_per_line * orig_height;
+
+ dst_data.resize(bytes_per_slice);
+
+ status = m_transcoder.transcode_image_level(
+ level_index, layer_index, face_index,
+ dst_data.data(), orig_width * orig_height,
+ transcoder_format,
+ flags,
+ orig_width,
+ orig_height,
+ channel0, channel1,
+ nullptr);
+ }
+ else
+ {
+ uint32_t bytes_per_block = basis_get_bytes_per_block_or_pixel(transcoder_format);
+
+ uint32_t required_size = total_blocks * bytes_per_block;
+
+ if (transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGB || transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGBA)
+ {
+ // For PVRTC1, Basis only writes (or requires) total_blocks * bytes_per_block. But GL requires extra padding for very small textures:
+ // https://www.khronos.org/registry/OpenGL/extensions/IMG/IMG_texture_compression_pvrtc.txt
+ // The transcoder will clear the extra bytes followed the used blocks to 0.
+ const uint32_t width = (orig_width + 3) & ~3;
+ const uint32_t height = (orig_height + 3) & ~3;
+ required_size = (std::max(8U, width) * std::max(8U, height) * 4 + 7) / 8;
+ assert(required_size >= total_blocks * bytes_per_block);
+ }
+
+ dst_data.resize(required_size);
+
+ status = m_transcoder.transcode_image_level(
+ level_index, layer_index, face_index,
+ dst_data.data(), dst_data.size() / bytes_per_block,
+ static_cast(format),
+ flags,
+ 0,
+ 0,
+ channel0, channel1,
+ nullptr);
+ }
+
+ emscripten::val memory = emscripten::val::module_property("HEAP8")["buffer"];
+ emscripten::val memoryView = emscripten::val::global("Uint8Array").new_(memory, reinterpret_cast(dst_data.data()), dst_data.size());
+
+ dst.call("set", memoryView);
+ return status;
+ }
};
#endif // BASISD_SUPPORT_KTX2
#if BASISU_SUPPORT_ENCODING
+
class basis_encoder
{
public:
- basis_compressor_params m_params;
+ basis_compressor_params m_params;
- basis_encoder()
- {
- }
+ basis_encoder()
+ {
+ }
- bool set_slice_source_image(uint32_t slice_index, const emscripten::val& src_image_js_val, uint32_t src_image_width, uint32_t src_image_height, bool src_image_is_png)
- {
- // Resize the source_images array if necessary
- if (slice_index >= m_params.m_source_images.size())
- m_params.m_source_images.resize(slice_index + 1);
+ // Only works for LDR inputs.
+ bool set_slice_source_image(uint32_t slice_index, const emscripten::val& src_image_js_val, uint32_t src_image_width, uint32_t src_image_height, bool src_image_is_png)
+ {
+ // Resize the source_images array if necessary
+ if (slice_index >= m_params.m_source_images.size())
+ m_params.m_source_images.resize(slice_index + 1);
- // First copy the src image buffer to the heap.
- basisu::vector src_image_buf;
- copy_from_jsbuffer(src_image_js_val, src_image_buf);
+ // First copy the src image buffer to the heap.
+ basisu::vector src_image_buf;
+ copy_from_jsbuffer(src_image_js_val, src_image_buf);
- // Now extract the source image.
- image& src_img = m_params.m_source_images[slice_index];
- if (src_image_is_png)
- {
- // It's a PNG file, so try and parse it.
- if (!load_png(src_image_buf.data(), src_image_buf.size(), src_img, nullptr))
- {
+ // Now load the source image.
+ image& src_img = m_params.m_source_images[slice_index];
+ if (src_image_is_png)
+ {
+ // It's a PNG file, so try and parse it.
+ if (!load_png(src_image_buf.data(), src_image_buf.size(), src_img, nullptr))
+ {
#if BASISU_DEBUG_PRINTF
- printf("basis_encoder::set_slice_source_image: Failed parsing provided PNG file!\n");
-#endif
- return false;
- }
+ printf("basis_encoder::set_slice_source_image: Failed parsing provided PNG file!\n");
+#endif
+ return false;
+ }
- src_image_width = src_img.get_width();
- src_image_height = src_img.get_height();
- }
- else
- {
- // It's a raw image, so check the buffer's size.
- if (src_image_buf.size() != src_image_width * src_image_height * sizeof(uint32_t))
- {
+ src_image_width = src_img.get_width();
+ src_image_height = src_img.get_height();
+ }
+ else
+ {
+ // It's a raw image, so check the buffer's size.
+ if (src_image_buf.size() != src_image_width * src_image_height * sizeof(uint32_t))
+ {
#if BASISU_DEBUG_PRINTF
- printf("basis_encoder::set_slice_source_image: Provided source buffer has an invalid size!\n");
-#endif
- return false;
- }
+ printf("basis_encoder::set_slice_source_image: Provided source buffer has an invalid size!\n");
+#endif
+ return false;
+ }
- // Copy the raw image's data into our source image.
- src_img.resize(src_image_width, src_image_height);
- memcpy(src_img.get_ptr(), src_image_buf.data(), src_image_width * src_image_height * sizeof(uint32_t));
- }
+ // Copy the raw image's data into our source image.
+ src_img.resize(src_image_width, src_image_height);
+ memcpy(src_img.get_ptr(), src_image_buf.data(), src_image_width * src_image_height * sizeof(uint32_t));
+ }
+
+ return true;
+ }
+
+ // Accepts RGBA half float or RGBA float images, or .EXR, .HDR, or .PNG file data.
+ bool set_slice_source_image_hdr(
+ uint32_t slice_index,
+ const emscripten::val& src_image_js_val,
+ uint32_t src_image_width, uint32_t src_image_height,
+ hdr_image_type img_type, bool ldr_srgb_to_linear_conversion)
+ {
+ // Resize the source_images_hdr array if necessary
+ if (slice_index >= m_params.m_source_images_hdr.size())
+ m_params.m_source_images_hdr.resize(slice_index + 1);
+
+ // First copy the src image buffer to the heap.
+ basisu::vector src_image_buf;
+ copy_from_jsbuffer(src_image_js_val, src_image_buf);
+
+ // Now load the source image.
+ imagef& src_img = m_params.m_source_images_hdr[slice_index];
- return true;
- }
-
- uint32_t encode(const emscripten::val& dst_basis_file_js_val)
- {
- if (!g_basis_initialized_flag)
- {
-#if BASISU_DEBUG_PRINTF
- printf("basis_encoder::encode: Must call basis_init() first!\n");
-#endif
- assert(0);
- return 0;
- }
+ return load_image_hdr(src_image_buf.get_ptr(), src_image_buf.size(), src_img, src_image_width, src_image_height, img_type, ldr_srgb_to_linear_conversion);
+ }
- // We don't use threading for now, but the compressor needs a job pool.
- job_pool jpool(1);
+ uint32_t encode(const emscripten::val& dst_basis_file_js_val)
+ {
+ if (!g_basis_initialized_flag)
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("basis_encoder::encode: Must call basis_init() first!\n");
+#endif
+ assert(0);
+ return 0;
+ }
- // Initialize the compression parameters structure. This is the same structure that the command line tool fills in.
- basis_compressor_params ¶ms = m_params;
+ // We don't use threading for now, but the compressor needs a job pool.
+ job_pool jpool(1);
- params.m_pJob_pool = &jpool;
+ // Initialize the compression parameters structure. This is the same structure that the command line tool fills in.
+ basis_compressor_params ¶ms = m_params;
- // Disabling multithreading for now, which sucks.
- params.m_multithreading = false;
-
- params.m_status_output = params.m_debug;
+ params.m_pJob_pool = &jpool;
- params.m_read_source_images = false;
- params.m_write_output_basis_files = false;
+ // Disabling multithreading for now, which sucks.
+ params.m_multithreading = false;
- basis_compressor comp;
+ params.m_status_output = params.m_debug;
- if (!comp.init(params))
- {
-#if BASISU_DEBUG_PRINTF
- printf("Failed initializing BasisU compressor! One or more provided parameters may be invalid.\n");
-#endif
- return 0;
- }
+ params.m_read_source_images = false;
+ params.m_write_output_basis_or_ktx2_files = false;
-#if BASISU_DEBUG_PRINTF
- printf("Begin BasisU compression\n");
-#endif
+ basis_compressor comp;
- basis_compressor::error_code ec = comp.process();
+ if (!comp.init(params))
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("Failed initializing BasisU compressor! One or more provided parameters may be invalid.\n");
+#endif
+ return 0;
+ }
#if BASISU_DEBUG_PRINTF
- printf("BasisU compression done, status %u, %u bytes\n", (uint32_t)ec, (uint32_t)comp.get_output_basis_file().size());
-#endif
+ printf("Begin BasisU compression\n");
+#endif
- if (ec != basis_compressor::cECSuccess)
- {
- // Something failed during compression.
-#if BASISU_DEBUG_PRINTF
- printf("BasisU compression failed with status %u!\n", (uint32_t)ec);
-#endif
- return 0;
- }
+ basis_compressor::error_code ec = comp.process();
- if (params.m_create_ktx2_file)
- {
- // Compression succeeded, so copy the .ktx2 file bytes to the caller's buffer.
- if (!copy_to_jsbuffer(dst_basis_file_js_val, comp.get_output_ktx2_file()))
- return 0;
+#if BASISU_DEBUG_PRINTF
+ printf("BasisU compression done, status %u, %u bytes\n", (uint32_t)ec, (uint32_t)comp.get_output_basis_file().size());
+#endif
- // Return the file size of the .basis file in bytes.
- return (uint32_t)comp.get_output_ktx2_file().size();
- }
- else
- {
- // Compression succeeded, so copy the .basis file bytes to the caller's buffer.
- if (!copy_to_jsbuffer(dst_basis_file_js_val, comp.get_output_basis_file()))
- return 0;
-
- // Return the file size of the .basis file in bytes.
- return (uint32_t)comp.get_output_basis_file().size();
- }
- }
+ if (ec != basis_compressor::cECSuccess)
+ {
+ // Something failed during compression.
+#if BASISU_DEBUG_PRINTF
+ printf("BasisU compression failed with status %u!\n", (uint32_t)ec);
+#endif
+ return 0;
+ }
+
+ if (params.m_create_ktx2_file)
+ {
+ // Compression succeeded, so copy the .ktx2 file bytes to the caller's buffer.
+ if (!copy_to_jsbuffer(dst_basis_file_js_val, comp.get_output_ktx2_file()))
+ return 0;
+
+ // Return the file size of the .basis file in bytes.
+ return (uint32_t)comp.get_output_ktx2_file().size();
+ }
+ else
+ {
+ // Compression succeeded, so copy the .basis file bytes to the caller's buffer.
+ if (!copy_to_jsbuffer(dst_basis_file_js_val, comp.get_output_basis_file()))
+ return 0;
+
+ // Return the file size of the .basis file in bytes.
+ return (uint32_t)comp.get_output_basis_file().size();
+ }
+ }
};
#endif
class lowlevel_etc1s_image_transcoder : public basisu_lowlevel_etc1s_transcoder
{
- // Using our own transcoder state, for video support.
- basisu_transcoder_state m_state;
-
+ // Using our own transcoder state, for video support.
+ basisu_transcoder_state m_state;
+
public:
- lowlevel_etc1s_image_transcoder()
- {
- }
-
- bool decode_palettes(uint32_t num_endpoints, const emscripten::val& endpoint_data, uint32_t num_selectors, const emscripten::val& selector_data)
- {
- basisu::vector temp_endpoint_data, temp_selector_data;
- copy_from_jsbuffer(endpoint_data, temp_endpoint_data);
- copy_from_jsbuffer(selector_data, temp_selector_data);
+ lowlevel_etc1s_image_transcoder()
+ {
+ }
-#if 0
- printf("decode_palettes: %u %u %u %u, %u %u\n",
- num_endpoints, (uint32_t)temp_endpoint_data.size(),
- num_selectors, (uint32_t)temp_selector_data.size(),
- temp_endpoint_data[0], temp_selector_data[0]);
-#endif
-
- if (!temp_endpoint_data.size() || !temp_selector_data.size())
- {
-#if BASISU_DEBUG_PRINTF
- printf("decode_tables: endpoint_data and/or selector_data is empty\n");
-#endif
- assert(0);
- return false;
- }
-
- return basisu_lowlevel_etc1s_transcoder::decode_palettes(num_endpoints, &temp_endpoint_data[0], (uint32_t)temp_endpoint_data.size(),
- num_selectors, &temp_selector_data[0], (uint32_t)temp_selector_data.size());
- }
-
- bool decode_tables(const emscripten::val& table_data)
- {
- basisu::vector temp_table_data;
- copy_from_jsbuffer(table_data, temp_table_data);
-
- if (!temp_table_data.size())
- {
-#if BASISU_DEBUG_PRINTF
- printf("decode_tables: table_data is empty\n");
-#endif
- assert(0);
- return false;
- }
-
- return basisu_lowlevel_etc1s_transcoder::decode_tables(&temp_table_data[0], (uint32_t)temp_table_data.size());
- }
-
- bool transcode_image(
- uint32_t target_format, // see transcoder_texture_format
- const emscripten::val& output_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels,
- const emscripten::val& compressed_data,
- uint32_t num_blocks_x, uint32_t num_blocks_y, uint32_t orig_width, uint32_t orig_height, uint32_t level_index,
- uint32_t rgb_offset, uint32_t rgb_length, uint32_t alpha_offset, uint32_t alpha_length,
- uint32_t decode_flags, // see cDecodeFlagsPVRTCDecodeToNextPow2
- bool basis_file_has_alpha_slices,
- bool is_video,
- uint32_t output_row_pitch_in_blocks_or_pixels,
- uint32_t output_rows_in_pixels)
- {
- if (!g_basis_initialized_flag)
- {
-#if BASISU_DEBUG_PRINTF
- printf("transcode_etc1s_image: basis_init() must be called first\n");
-#endif
- assert(0);
- return false;
- }
-
- // FIXME: Access the JavaScript buffer directly vs. copying it.
- basisu::vector temp_comp_data;
- copy_from_jsbuffer(compressed_data, temp_comp_data);
-
- if (!temp_comp_data.size())
- {
-#if BASISU_DEBUG_PRINTF
- printf("transcode_etc1s_image: compressed_data is empty\n");
-#endif
- assert(0);
- return false;
- }
-
- uint32_t output_blocks_len = output_blocks["byteLength"].as();
- if (!output_blocks_len)
- {
-#if BASISU_DEBUG_PRINTF
- printf("transcode_etc1s_image: output_blocks is empty\n");
-#endif
- assert(0);
- return false;
- }
-
- basisu::vector temp_output_blocks(output_blocks_len);
-
- bool status = basisu_lowlevel_etc1s_transcoder::transcode_image(
- (transcoder_texture_format)target_format,
- &temp_output_blocks[0], output_blocks_buf_size_in_blocks_or_pixels,
- &temp_comp_data[0], temp_comp_data.size(),
- num_blocks_x, num_blocks_y, orig_width, orig_height, level_index,
- rgb_offset, rgb_length, alpha_offset, alpha_length,
- decode_flags,
- basis_file_has_alpha_slices,
- is_video,
- output_row_pitch_in_blocks_or_pixels,
- &m_state,
- output_rows_in_pixels);
-
- if (!status)
- {
-#if BASISU_DEBUG_PRINTF
- printf("transcode_etc1s_image: basisu_lowlevel_etc1s_transcoder::transcode_image failed\n");
-#endif
- assert(0);
- return false;
- }
-
- if (!copy_to_jsbuffer(output_blocks, temp_output_blocks))
- return false;
+ bool decode_palettes(uint32_t num_endpoints, const emscripten::val& endpoint_data, uint32_t num_selectors, const emscripten::val& selector_data)
+ {
+ basisu::vector temp_endpoint_data, temp_selector_data;
+ copy_from_jsbuffer(endpoint_data, temp_endpoint_data);
+ copy_from_jsbuffer(selector_data, temp_selector_data);
- return true;
- }
+#if 0
+ printf("decode_palettes: %u %u %u %u, %u %u\n",
+ num_endpoints, (uint32_t)temp_endpoint_data.size(),
+ num_selectors, (uint32_t)temp_selector_data.size(),
+ temp_endpoint_data[0], temp_selector_data[0]);
+#endif
+
+ if (!temp_endpoint_data.size() || !temp_selector_data.size())
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("decode_tables: endpoint_data and/or selector_data is empty\n");
+#endif
+ assert(0);
+ return false;
+ }
+
+ return basisu_lowlevel_etc1s_transcoder::decode_palettes(num_endpoints, &temp_endpoint_data[0], (uint32_t)temp_endpoint_data.size(),
+ num_selectors, &temp_selector_data[0], (uint32_t)temp_selector_data.size());
+ }
+
+ bool decode_tables(const emscripten::val& table_data)
+ {
+ basisu::vector temp_table_data;
+ copy_from_jsbuffer(table_data, temp_table_data);
+
+ if (!temp_table_data.size())
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("decode_tables: table_data is empty\n");
+#endif
+ assert(0);
+ return false;
+ }
+
+ return basisu_lowlevel_etc1s_transcoder::decode_tables(&temp_table_data[0], (uint32_t)temp_table_data.size());
+ }
+
+ bool transcode_image(
+ uint32_t target_format, // see transcoder_texture_format
+ const emscripten::val& output_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels,
+ const emscripten::val& compressed_data,
+ uint32_t num_blocks_x, uint32_t num_blocks_y, uint32_t orig_width, uint32_t orig_height, uint32_t level_index,
+ uint32_t rgb_offset, uint32_t rgb_length, uint32_t alpha_offset, uint32_t alpha_length,
+ uint32_t decode_flags, // see cDecodeFlagsPVRTCDecodeToNextPow2
+ bool basis_file_has_alpha_slices,
+ bool is_video,
+ uint32_t output_row_pitch_in_blocks_or_pixels,
+ uint32_t output_rows_in_pixels)
+ {
+ if (!g_basis_initialized_flag)
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("transcode_etc1s_image: basis_init() must be called first\n");
+#endif
+ assert(0);
+ return false;
+ }
+
+ // FIXME: Access the JavaScript buffer directly vs. copying it.
+ basisu::vector temp_comp_data;
+ copy_from_jsbuffer(compressed_data, temp_comp_data);
+
+ if (!temp_comp_data.size())
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("transcode_etc1s_image: compressed_data is empty\n");
+#endif
+ assert(0);
+ return false;
+ }
+
+ uint32_t output_blocks_len = output_blocks["byteLength"].as();
+ if (!output_blocks_len)
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("transcode_etc1s_image: output_blocks is empty\n");
+#endif
+ assert(0);
+ return false;
+ }
+
+ basisu::vector temp_output_blocks(output_blocks_len);
+
+ bool status = basisu_lowlevel_etc1s_transcoder::transcode_image(
+ (transcoder_texture_format)target_format,
+ &temp_output_blocks[0], output_blocks_buf_size_in_blocks_or_pixels,
+ &temp_comp_data[0], temp_comp_data.size(),
+ num_blocks_x, num_blocks_y, orig_width, orig_height, level_index,
+ rgb_offset, rgb_length, alpha_offset, alpha_length,
+ decode_flags,
+ basis_file_has_alpha_slices,
+ is_video,
+ output_row_pitch_in_blocks_or_pixels,
+ &m_state,
+ output_rows_in_pixels);
+
+ if (!status)
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("transcode_etc1s_image: basisu_lowlevel_etc1s_transcoder::transcode_image failed\n");
+#endif
+ assert(0);
+ return false;
+ }
+
+ if (!copy_to_jsbuffer(output_blocks, temp_output_blocks))
+ return false;
+
+ return true;
+ }
};
+// Supports UASTC LDR and HDR.
bool transcode_uastc_image(
- uint32_t target_format_int, // see transcoder_texture_format
- const emscripten::val& output_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels,
- const emscripten::val& compressed_data,
- uint32_t num_blocks_x, uint32_t num_blocks_y, uint32_t orig_width, uint32_t orig_height, uint32_t level_index,
- uint32_t slice_offset, uint32_t slice_length,
- uint32_t decode_flags, // see cDecodeFlagsPVRTCDecodeToNextPow2
- bool has_alpha,
- bool is_video,
- uint32_t output_row_pitch_in_blocks_or_pixels,
- uint32_t output_rows_in_pixels,
- int channel0, int channel1)
+ uint32_t target_format_int, // see transcoder_texture_format
+ const emscripten::val& output_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels,
+ const emscripten::val& compressed_data,
+ uint32_t num_blocks_x, uint32_t num_blocks_y, uint32_t orig_width, uint32_t orig_height, uint32_t level_index,
+ uint32_t slice_offset, uint32_t slice_length,
+ uint32_t decode_flags, // see cDecodeFlagsPVRTCDecodeToNextPow2
+ bool has_alpha,
+ bool is_video,
+ uint32_t output_row_pitch_in_blocks_or_pixels,
+ uint32_t output_rows_in_pixels,
+ int channel0, int channel1)
{
- transcoder_texture_format target_format = static_cast(target_format_int);
-
- if (!g_basis_initialized_flag)
+ transcoder_texture_format target_format = static_cast(target_format_int);
+
+ if (!g_basis_initialized_flag)
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("transcode_uastc_image: basis_init() must be called first\n");
+#endif
+ assert(0);
+ return false;
+ }
+
+ // FIXME: Access the JavaScript buffer directly vs. copying it.
+ basisu::vector temp_comp_data;
+ copy_from_jsbuffer(compressed_data, temp_comp_data);
+
+ if (!temp_comp_data.size())
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("transcode_uastc_image: compressed_data is empty\n");
+#endif
+ assert(0);
+ return false;
+ }
+
+ uint32_t output_blocks_len = output_blocks["byteLength"].as();
+ if (!output_blocks_len)
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("transcode_uastc_image: output_blocks is empty\n");
+#endif
+ assert(0);
+ return false;
+ }
+
+#if 0
+ printf("format: %u\n", (uint32_t)target_format);
+ printf("output_blocks size: %u buf size: %u\n", output_blocks_len, output_blocks_buf_size_in_blocks_or_pixels);
+ printf("compressed_data size: %u\n", compressed_data["byteLength"].as());
+ printf("%u %u %u %u %u\n", num_blocks_x, num_blocks_y, orig_width, orig_height, level_index);
+ printf("%u %u\n", slice_offset, slice_length);
+ printf("%u\n", decode_flags);
+ printf("has_alpha: %u is_video: %u\n", has_alpha, is_video);
+#endif
+
+ basisu::vector temp_output_blocks(output_blocks_len);
+
+ bool status = false;
+ if (basis_transcoder_format_is_hdr(target_format))
{
-#if BASISU_DEBUG_PRINTF
- printf("transcode_uastc_image: basis_init() must be called first\n");
-#endif
- assert(0);
- return false;
+ basisu_lowlevel_uastc_hdr_transcoder transcoder;
+
+ status = transcoder.transcode_image(
+ (transcoder_texture_format)target_format,
+ &temp_output_blocks[0], output_blocks_buf_size_in_blocks_or_pixels,
+ &temp_comp_data[0], temp_comp_data.size(),
+ num_blocks_x, num_blocks_y, orig_width, orig_height, level_index,
+ slice_offset, slice_length,
+ decode_flags,
+ has_alpha,
+ is_video,
+ output_row_pitch_in_blocks_or_pixels,
+ nullptr,
+ output_rows_in_pixels,
+ channel0, channel1);
}
-
- // FIXME: Access the JavaScript buffer directly vs. copying it.
- basisu::vector temp_comp_data;
- copy_from_jsbuffer(compressed_data, temp_comp_data);
-
- if (!temp_comp_data.size())
+ else
{
-#if BASISU_DEBUG_PRINTF
- printf("transcode_uastc_image: compressed_data is empty\n");
-#endif
- assert(0);
- return false;
- }
-
- uint32_t output_blocks_len = output_blocks["byteLength"].as();
- if (!output_blocks_len)
- {
-#if BASISU_DEBUG_PRINTF
- printf("transcode_uastc_image: output_blocks is empty\n");
-#endif
- assert(0);
- return false;
+ basisu_lowlevel_uastc_transcoder transcoder;
+
+ status = transcoder.transcode_image(
+ (transcoder_texture_format)target_format,
+ &temp_output_blocks[0], output_blocks_buf_size_in_blocks_or_pixels,
+ &temp_comp_data[0], temp_comp_data.size(),
+ num_blocks_x, num_blocks_y, orig_width, orig_height, level_index,
+ slice_offset, slice_length,
+ decode_flags,
+ has_alpha,
+ is_video,
+ output_row_pitch_in_blocks_or_pixels,
+ nullptr,
+ output_rows_in_pixels,
+ channel0, channel1);
}
-#if 0
- printf("format: %u\n", (uint32_t)target_format);
- printf("output_blocks size: %u buf size: %u\n", output_blocks_len, output_blocks_buf_size_in_blocks_or_pixels);
- printf("compressed_data size: %u\n", compressed_data["byteLength"].as());
- printf("%u %u %u %u %u\n", num_blocks_x, num_blocks_y, orig_width, orig_height, level_index);
- printf("%u %u\n", slice_offset, slice_length);
- printf("%u\n", decode_flags);
- printf("has_alpha: %u is_video: %u\n", has_alpha, is_video);
-#endif
-
- basisu::vector temp_output_blocks(output_blocks_len);
-
- basisu_lowlevel_uastc_transcoder transcoder;
-
- bool status = transcoder.transcode_image(
- (transcoder_texture_format)target_format,
- &temp_output_blocks[0], output_blocks_buf_size_in_blocks_or_pixels,
- &temp_comp_data[0], temp_comp_data.size(),
- num_blocks_x, num_blocks_y, orig_width, orig_height, level_index,
- slice_offset, slice_length,
- decode_flags,
- has_alpha,
- is_video,
- output_row_pitch_in_blocks_or_pixels,
- nullptr,
- output_rows_in_pixels,
- channel0, channel1);
-
- if (!status)
- {
-#if BASISU_DEBUG_PRINTF
- printf("transcode_uastc_image: basisu_lowlevel_uastc_transcoder::transcode_image failed\n");
-#endif
- assert(0);
- return false;
- }
-
- if (!copy_to_jsbuffer(output_blocks, temp_output_blocks))
- return false;
+ if (!status)
+ {
+#if BASISU_DEBUG_PRINTF
+ printf("transcode_uastc_image: basisu_lowlevel_uastc_transcoder::transcode_image failed\n");
+#endif
+ assert(0);
+ return false;
+ }
- return true;
+ if (!copy_to_jsbuffer(output_blocks, temp_output_blocks))
+ return false;
+
+ return true;
}
uint32_t get_bytes_per_block_or_pixel(uint32_t transcoder_tex_fmt)
{
- return basis_get_bytes_per_block_or_pixel(static_cast(transcoder_tex_fmt));
+ return basis_get_bytes_per_block_or_pixel(static_cast(transcoder_tex_fmt));
}
bool format_has_alpha(uint32_t transcoder_tex_fmt)
{
- return basis_transcoder_format_has_alpha(static_cast(transcoder_tex_fmt));
+ return basis_transcoder_format_has_alpha(static_cast(transcoder_tex_fmt));
+}
+
+bool format_is_hdr(uint32_t transcode_tex_fmt)
+{
+ return basis_transcoder_format_is_hdr(static_cast(transcode_tex_fmt));
}
bool format_is_uncompressed(uint32_t transcoder_tex_fmt)
{
- return basis_transcoder_format_is_uncompressed(static_cast(transcoder_tex_fmt));
+ return basis_transcoder_format_is_uncompressed(static_cast(transcoder_tex_fmt));
}
-bool is_format_supported(uint32_t transcoder_tex_fmt)
+bool is_format_supported(uint32_t transcoder_tex_fmt, uint32_t file_fmt)
{
- return basis_is_format_supported(static_cast(transcoder_tex_fmt));
+ return basis_is_format_supported(static_cast(transcoder_tex_fmt), static_cast(file_fmt));
}
uint32_t get_format_block_width(uint32_t transcoder_tex_fmt)
{
- return basis_get_block_width(static_cast(transcoder_tex_fmt));
+ return basis_get_block_width(static_cast(transcoder_tex_fmt));
}
uint32_t get_format_block_height(uint32_t transcoder_tex_fmt)
{
- return basis_get_block_height(static_cast(transcoder_tex_fmt));
+ return basis_get_block_height(static_cast(transcoder_tex_fmt));
+}
+
+uint32_t convert_float_to_half(float f)
+{
+ return basist::float_to_half(f);
+}
+
+float convert_half_to_float(uint32_t h)
+{
+ assert(h < 65536);
+ return basist::half_to_float(h);
+}
+
+void set_debug_flags_wrapper(uint32_t flags)
+{
+ basist::set_debug_flags(flags);
+}
+
+uint32_t get_debug_flags_wrapper()
+{
+ return basist::get_debug_flags();
}
EMSCRIPTEN_BINDINGS(basis_codec) {
function("initializeBasis", &basis_init);
-
+
+ function("setDebugFlags", &set_debug_flags_wrapper);
+ function("getDebugFlags", &get_debug_flags_wrapper);
+
// Expose BasisFileDesc structure
value_object("BasisFileDesc")
- .field("version", &basis_file_desc::m_version)
- .field("usPerFrame", &basis_file_desc::m_us_per_frame)
- .field("totalImages", &basis_file_desc::m_total_images)
- .field("userdata0", &basis_file_desc::m_userdata0)
- .field("userdata1", &basis_file_desc::m_userdata1)
- .field("texFormat", &basis_file_desc::m_tex_format)
- .field("yFlipped", &basis_file_desc::m_y_flipped)
- .field("hasAlphaSlices", &basis_file_desc::m_has_alpha_slices)
- .field("numEndpoints", &basis_file_desc::m_num_endpoints)
- .field("endpointPaletteOfs", &basis_file_desc::m_endpoint_palette_ofs)
- .field("endpointPaletteLen", &basis_file_desc::m_endpoint_palette_len)
- .field("numSelectors", &basis_file_desc::m_num_selectors)
- .field("selectorPaletteOfs", &basis_file_desc::m_selector_palette_ofs)
- .field("selectorPaletteLen", &basis_file_desc::m_selector_palette_len)
- .field("tablesOfs", &basis_file_desc::m_tables_ofs)
- .field("tablesLen", &basis_file_desc::m_tables_len)
+ .field("version", &basis_file_desc::m_version)
+ .field("usPerFrame", &basis_file_desc::m_us_per_frame)
+ .field("totalImages", &basis_file_desc::m_total_images)
+ .field("userdata0", &basis_file_desc::m_userdata0)
+ .field("userdata1", &basis_file_desc::m_userdata1)
+ .field("texFormat", &basis_file_desc::m_tex_format)
+ .field("yFlipped", &basis_file_desc::m_y_flipped)
+ .field("hasAlphaSlices", &basis_file_desc::m_has_alpha_slices)
+ .field("numEndpoints", &basis_file_desc::m_num_endpoints)
+ .field("endpointPaletteOfs", &basis_file_desc::m_endpoint_palette_ofs)
+ .field("endpointPaletteLen", &basis_file_desc::m_endpoint_palette_len)
+ .field("numSelectors", &basis_file_desc::m_num_selectors)
+ .field("selectorPaletteOfs", &basis_file_desc::m_selector_palette_ofs)
+ .field("selectorPaletteLen", &basis_file_desc::m_selector_palette_len)
+ .field("tablesOfs", &basis_file_desc::m_tables_ofs)
+ .field("tablesLen", &basis_file_desc::m_tables_len)
;
- // Expose BasisImageDesc structure
+ // Expose BasisImageDesc structure
value_object("BasisImageDesc")
- .field("origWidth", &basis_image_desc::m_orig_width)
+ .field("origWidth", &basis_image_desc::m_orig_width)
.field("origHeight", &basis_image_desc::m_orig_height)
.field("numBlocksX", &basis_image_desc::m_num_blocks_x)
.field("numBlocksY", &basis_image_desc::m_num_blocks_y)
.field("numLevels", &basis_image_desc::m_num_levels)
.field("alphaFlag", &basis_image_desc::m_alpha_flag)
.field("iframeFlag", &basis_image_desc::m_iframe_flag)
- ;
+ ;
// Expose BasisImageLevelDesc structure
value_object("BasisImageLevelDesc")
- .field("rgbFileOfs", &basis_image_level_desc::m_rgb_file_ofs)
+ .field("rgbFileOfs", &basis_image_level_desc::m_rgb_file_ofs)
.field("rgbFileLen", &basis_image_level_desc::m_rgb_file_len)
.field("alphaFileOfs", &basis_image_level_desc::m_alpha_file_ofs)
.field("alphaFileLen", &basis_image_level_desc::m_alpha_file_len)
- ;
+ ;
// Expose some key enums to JavaScript code.
// enum class transcoder_texture_format
enum_("transcoder_texture_format")
- .value("cTFETC1_RGB", transcoder_texture_format::cTFETC1_RGB)
- .value("cTFETC2_RGBA", transcoder_texture_format::cTFETC2_RGBA)
- .value("cTFBC1_RGB", transcoder_texture_format::cTFBC1_RGB)
- .value("cTFBC3_RGBA", transcoder_texture_format::cTFBC3_RGBA)
- .value("cTFBC4_R", transcoder_texture_format::cTFBC4_R)
- .value("cTFBC5_RG", transcoder_texture_format::cTFBC5_RG)
- .value("cTFBC7_RGBA", transcoder_texture_format::cTFBC7_RGBA)
- .value("cTFPVRTC1_4_RGB", transcoder_texture_format::cTFPVRTC1_4_RGB)
- .value("cTFPVRTC1_4_RGBA", transcoder_texture_format::cTFPVRTC1_4_RGBA)
- .value("cTFASTC_4x4_RGBA", transcoder_texture_format::cTFASTC_4x4_RGBA)
- .value("cTFATC_RGB", transcoder_texture_format::cTFATC_RGB)
- .value("cTFATC_RGBA", transcoder_texture_format::cTFATC_RGBA)
- .value("cTFFXT1_RGB", transcoder_texture_format::cTFFXT1_RGB)
- .value("cTFPVRTC2_4_RGB", transcoder_texture_format::cTFPVRTC2_4_RGB)
- .value("cTFPVRTC2_4_RGBA", transcoder_texture_format::cTFPVRTC2_4_RGBA)
- .value("cTFETC2_EAC_R11", transcoder_texture_format::cTFETC2_EAC_R11)
- .value("cTFETC2_EAC_RG11", transcoder_texture_format::cTFETC2_EAC_RG11)
- .value("cTFRGBA32", transcoder_texture_format::cTFRGBA32)
- .value("cTFRGB565", transcoder_texture_format::cTFRGB565)
- .value("cTFBGR565", transcoder_texture_format::cTFBGR565)
- .value("cTFRGBA4444", transcoder_texture_format::cTFRGBA4444)
- .value("cTFTotalTextureFormats", transcoder_texture_format::cTFTotalTextureFormats)
- ;
+ .value("cTFETC1_RGB", transcoder_texture_format::cTFETC1_RGB)
+ .value("cTFETC2_RGBA", transcoder_texture_format::cTFETC2_RGBA)
+ .value("cTFBC1_RGB", transcoder_texture_format::cTFBC1_RGB)
+ .value("cTFBC3_RGBA", transcoder_texture_format::cTFBC3_RGBA)
+ .value("cTFBC4_R", transcoder_texture_format::cTFBC4_R)
+ .value("cTFBC5_RG", transcoder_texture_format::cTFBC5_RG)
+ .value("cTFBC7_RGBA", transcoder_texture_format::cTFBC7_RGBA)
+ .value("cTFPVRTC1_4_RGB", transcoder_texture_format::cTFPVRTC1_4_RGB)
+ .value("cTFPVRTC1_4_RGBA", transcoder_texture_format::cTFPVRTC1_4_RGBA)
+ .value("cTFASTC_4x4_RGBA", transcoder_texture_format::cTFASTC_4x4_RGBA)
+ .value("cTFATC_RGB", transcoder_texture_format::cTFATC_RGB)
+ .value("cTFATC_RGBA", transcoder_texture_format::cTFATC_RGBA)
+ .value("cTFFXT1_RGB", transcoder_texture_format::cTFFXT1_RGB)
+ .value("cTFPVRTC2_4_RGB", transcoder_texture_format::cTFPVRTC2_4_RGB)
+ .value("cTFPVRTC2_4_RGBA", transcoder_texture_format::cTFPVRTC2_4_RGBA)
+ .value("cTFETC2_EAC_R11", transcoder_texture_format::cTFETC2_EAC_R11)
+ .value("cTFETC2_EAC_RG11", transcoder_texture_format::cTFETC2_EAC_RG11)
+ .value("cTFBC6H", transcoder_texture_format::cTFBC6H)
+ .value("cTFASTC_HDR_4x4_RGBA", transcoder_texture_format::cTFASTC_HDR_4x4_RGBA)
+ .value("cTFRGBA32", transcoder_texture_format::cTFRGBA32)
+ .value("cTFRGB565", transcoder_texture_format::cTFRGB565)
+ .value("cTFBGR565", transcoder_texture_format::cTFBGR565)
+ .value("cTFRGBA4444", transcoder_texture_format::cTFRGBA4444)
+ .value("cTFRGB_HALF", transcoder_texture_format::cTFRGB_HALF)
+ .value("cTFRGBA_HALF", transcoder_texture_format::cTFRGBA_HALF)
+ .value("cTFRGB_9E5", transcoder_texture_format::cTFRGB_9E5)
+ .value("cTFTotalTextureFormats", transcoder_texture_format::cTFTotalTextureFormats)
+ ;
- // Expose some useful transcoder_texture_format helper functions
- function("getBytesPerBlockOrPixel", &get_bytes_per_block_or_pixel);
- function("formatHasAlpha", &format_has_alpha);
- function("formatIsUncompressed", &format_is_uncompressed);
- function("isFormatSupported", &is_format_supported);
- function("getFormatBlockWidth", &get_format_block_width);
- function("getFormatBlockHeight", &get_format_block_height);
-
- // Expose enum basis_texture_type
- enum_("basis_texture_type")
- .value("cBASISTexType2D", cBASISTexType2D)
- .value("cBASISTexType2DArray", cBASISTexType2DArray)
- .value("cBASISTexTypeCubemapArray", cBASISTexTypeCubemapArray)
- .value("cBASISTexTypeVideoFrames", cBASISTexTypeVideoFrames)
- .value("cBASISTexTypeVolume", cBASISTexTypeVolume)
- ;
+ // Expose some useful transcoder_texture_format helper functions
+ function("getBytesPerBlockOrPixel", &get_bytes_per_block_or_pixel);
+ function("formatHasAlpha", &format_has_alpha);
+ function("formatIsHDR", &format_is_hdr);
+ function("formatIsUncompressed", &format_is_uncompressed);
+ function("isFormatSupported", &is_format_supported);
+ function("getFormatBlockWidth", &get_format_block_width);
+ function("getFormatBlockHeight", &get_format_block_height);
- // Expose enum basis_tex_format
- enum_("basis_tex_format")
- .value("cETC1S", basis_tex_format::cETC1S)
- .value("cUASTC4x4", basis_tex_format::cUASTC4x4)
- ;
+ function("convertFloatToHalf", &convert_float_to_half);
+ function("convertHalfToFloat", &convert_half_to_float);
+
+ // Expose enum basis_texture_type
+ enum_("basis_texture_type")
+ .value("cBASISTexType2D", cBASISTexType2D)
+ .value("cBASISTexType2DArray", cBASISTexType2DArray)
+ .value("cBASISTexTypeCubemapArray", cBASISTexTypeCubemapArray)
+ .value("cBASISTexTypeVideoFrames", cBASISTexTypeVideoFrames)
+ .value("cBASISTexTypeVolume", cBASISTexTypeVolume)
+ ;
+
+ // Expose enum basis_tex_format
+ enum_("basis_tex_format")
+ .value("cETC1S", basis_tex_format::cETC1S)
+ .value("cUASTC4x4", basis_tex_format::cUASTC4x4)
+ .value("cUASTC_HDR_4x4", basis_tex_format::cUASTC_HDR_4x4)
+ ;
// .basis file transcoder object. If all you want to do is transcode already encoded .basis files, this is all you really need.
class_("BasisFile")
@@ -1476,6 +1585,9 @@ EMSCRIPTEN_BINDINGS(basis_codec) {
}))
.function("isUASTC", optional_override([](basis_file& self) {
return self.isUASTC();
+ }))
+ .function("isHDR", optional_override([](basis_file& self) {
+ return self.isHDR();
}))
.function("getNumImages", optional_override([](basis_file& self) {
return self.getNumImages();
@@ -1489,63 +1601,63 @@ EMSCRIPTEN_BINDINGS(basis_codec) {
.function("getImageHeight", optional_override([](basis_file& self, uint32_t imageIndex, uint32_t levelIndex) {
return self.getImageHeight(imageIndex, levelIndex);
}))
- // format is enum class transcoder_texture_format
+ // format is enum class transcoder_texture_format
.function("getImageTranscodedSizeInBytes", optional_override([](basis_file& self, uint32_t imageIndex, uint32_t levelIndex, uint32_t format) {
return self.getImageTranscodedSizeInBytes(imageIndex, levelIndex, format);
}))
.function("startTranscoding", optional_override([](basis_file& self) {
return self.startTranscoding();
}))
- // format is enum class transcoder_texture_format
+ // format is enum class transcoder_texture_format
.function("transcodeImage", optional_override([](basis_file& self, const emscripten::val& dst, uint32_t imageIndex, uint32_t levelIndex, uint32_t format, uint32_t unused, uint32_t getAlphaForOpaqueFormats) {
return self.transcodeImage(dst, imageIndex, levelIndex, format, unused, getAlphaForOpaqueFormats);
}))
- // Returns low-level information about the basis file.
- .function("getFileDesc", optional_override([](basis_file& self) {
+ // Returns low-level information about the basis file.
+ .function("getFileDesc", optional_override([](basis_file& self) {
return self.getFileDesc();
}))
- // Returns low-level information about a specific image in a basis file. An image can contain 1 or more mipmap levels.
- .function("getImageDesc", optional_override([](basis_file& self, uint32_t imageIndex) {
+ // Returns low-level information about a specific image in a basis file. An image can contain 1 or more mipmap levels.
+ .function("getImageDesc", optional_override([](basis_file& self, uint32_t imageIndex) {
return self.getImageDesc(imageIndex);
}))
- // Returns low-level information about a specific image mipmap level in a basis file.
- .function("getImageLevelDesc", optional_override([](basis_file& self, uint32_t imageIndex, uint32_t levelIndex) {
+ // Returns low-level information about a specific image mipmap level in a basis file.
+ .function("getImageLevelDesc", optional_override([](basis_file& self, uint32_t imageIndex, uint32_t levelIndex) {
return self.getImageLevelDesc(imageIndex, levelIndex);
}))
;
-
+
// Low-level container independent transcoding of ETC1S and UASTC slice data.
// These functions allow the caller to transcode compressed ETC1S or UASTC texture data that is embedded within arbitrary data files, such as from KTX2.
enum_("basisu_decode_flags")
- .value("cDecodeFlagsPVRTCDecodeToNextPow2", cDecodeFlagsPVRTCDecodeToNextPow2)
- .value("cDecodeFlagsTranscodeAlphaDataToOpaqueFormats", cDecodeFlagsTranscodeAlphaDataToOpaqueFormats)
- .value("cDecodeFlagsBC1ForbidThreeColorBlocks", cDecodeFlagsBC1ForbidThreeColorBlocks)
- .value("cDecodeFlagsOutputHasAlphaIndices", cDecodeFlagsOutputHasAlphaIndices)
- .value("cDecodeFlagsHighQuality", cDecodeFlagsHighQuality)
+ .value("cDecodeFlagsPVRTCDecodeToNextPow2", cDecodeFlagsPVRTCDecodeToNextPow2)
+ .value("cDecodeFlagsTranscodeAlphaDataToOpaqueFormats", cDecodeFlagsTranscodeAlphaDataToOpaqueFormats)
+ .value("cDecodeFlagsBC1ForbidThreeColorBlocks", cDecodeFlagsBC1ForbidThreeColorBlocks)
+ .value("cDecodeFlagsOutputHasAlphaIndices", cDecodeFlagsOutputHasAlphaIndices)
+ .value("cDecodeFlagsHighQuality", cDecodeFlagsHighQuality)
;
-
+
// The low-level ETC1S transcoder is a class because it has persistent state (such as the endpoint/selector codebooks and Huffman tables, and transcoder state for video)
class_("LowLevelETC1SImageTranscoder")
- .constructor<>()
- .function("decodePalettes", &lowlevel_etc1s_image_transcoder::decode_palettes)
- .function("decodeTables", &lowlevel_etc1s_image_transcoder::decode_tables)
- .function("transcodeImage", &lowlevel_etc1s_image_transcoder::transcode_image)
- ;
+ .constructor<>()
+ .function("decodePalettes", &lowlevel_etc1s_image_transcoder::decode_palettes)
+ .function("decodeTables", &lowlevel_etc1s_image_transcoder::decode_tables)
+ .function("transcodeImage", &lowlevel_etc1s_image_transcoder::transcode_image)
+ ;
- // The low-level UASTC transcoder is a single function.
+ // The low-level UASTC transcoder is a single function.
function("transcodeUASTCImage", &transcode_uastc_image);
function("transcoderSupportsKTX2", &basisu_transcoder_supports_ktx2);
function("transcoderSupportsKTX2Zstd", &basisu_transcoder_supports_ktx2_zstd);
-
+
#if BASISD_SUPPORT_KTX2
// KTX2 enums/constants
enum_("ktx2_supercompression")
- .value("KTX2_SS_NONE", KTX2_SS_NONE)
- .value("KTX2_SS_BASISLZ", KTX2_SS_BASISLZ)
- .value("KTX2_SS_ZSTANDARD", KTX2_SS_ZSTANDARD)
- ;
+ .value("KTX2_SS_NONE", KTX2_SS_NONE)
+ .value("KTX2_SS_BASISLZ", KTX2_SS_BASISLZ)
+ .value("KTX2_SS_ZSTANDARD", KTX2_SS_ZSTANDARD)
+ ;
constant("KTX2_VK_FORMAT_UNDEFINED", KTX2_VK_FORMAT_UNDEFINED);
constant("KTX2_KDF_DF_MODEL_UASTC", KTX2_KDF_DF_MODEL_UASTC);
@@ -1558,404 +1670,432 @@ EMSCRIPTEN_BINDINGS(basis_codec) {
constant("KTX2_KHR_DF_TRANSFER_SRGB", KTX2_KHR_DF_TRANSFER_SRGB);
enum_("ktx2_df_channel_id")
- .value("KTX2_DF_CHANNEL_ETC1S_RGB", KTX2_DF_CHANNEL_ETC1S_RGB)
- .value("KTX2_DF_CHANNEL_ETC1S_RRR", KTX2_DF_CHANNEL_ETC1S_RRR)
- .value("KTX2_DF_CHANNEL_ETC1S_GGG", KTX2_DF_CHANNEL_ETC1S_GGG)
- .value("KTX2_DF_CHANNEL_ETC1S_AAA", KTX2_DF_CHANNEL_ETC1S_AAA)
- .value("KTX2_DF_CHANNEL_UASTC_DATA", KTX2_DF_CHANNEL_UASTC_DATA)
- .value("KTX2_DF_CHANNEL_UASTC_RGB", KTX2_DF_CHANNEL_UASTC_RGB)
- .value("KTX2_DF_CHANNEL_UASTC_RGBA", KTX2_DF_CHANNEL_UASTC_RGBA)
- .value("KTX2_DF_CHANNEL_UASTC_RRR", KTX2_DF_CHANNEL_UASTC_RRR)
- .value("KTX2_DF_CHANNEL_UASTC_RRRG", KTX2_DF_CHANNEL_UASTC_RRRG)
- .value("KTX2_DF_CHANNEL_UASTC_RG", KTX2_DF_CHANNEL_UASTC_RG)
- ;
+ .value("KTX2_DF_CHANNEL_ETC1S_RGB", KTX2_DF_CHANNEL_ETC1S_RGB)
+ .value("KTX2_DF_CHANNEL_ETC1S_RRR", KTX2_DF_CHANNEL_ETC1S_RRR)
+ .value("KTX2_DF_CHANNEL_ETC1S_GGG", KTX2_DF_CHANNEL_ETC1S_GGG)
+ .value("KTX2_DF_CHANNEL_ETC1S_AAA", KTX2_DF_CHANNEL_ETC1S_AAA)
+ .value("KTX2_DF_CHANNEL_UASTC_DATA", KTX2_DF_CHANNEL_UASTC_DATA)
+ .value("KTX2_DF_CHANNEL_UASTC_RGB", KTX2_DF_CHANNEL_UASTC_RGB)
+ .value("KTX2_DF_CHANNEL_UASTC_RGBA", KTX2_DF_CHANNEL_UASTC_RGBA)
+ .value("KTX2_DF_CHANNEL_UASTC_RRR", KTX2_DF_CHANNEL_UASTC_RRR)
+ .value("KTX2_DF_CHANNEL_UASTC_RRRG", KTX2_DF_CHANNEL_UASTC_RRRG)
+ .value("KTX2_DF_CHANNEL_UASTC_RG", KTX2_DF_CHANNEL_UASTC_RG)
+ ;
enum_("ktx2_df_color_primaries")
- .value("KTX2_DF_PRIMARIES_UNSPECIFIED", KTX2_DF_PRIMARIES_UNSPECIFIED)
- .value("KTX2_DF_PRIMARIES_BT709", KTX2_DF_PRIMARIES_BT709)
- .value("KTX2_DF_PRIMARIES_SRGB", KTX2_DF_PRIMARIES_SRGB)
- .value("KTX2_DF_PRIMARIES_BT601_EBU", KTX2_DF_PRIMARIES_BT601_EBU)
- .value("KTX2_DF_PRIMARIES_BT601_SMPTE", KTX2_DF_PRIMARIES_BT601_SMPTE)
- .value("KTX2_DF_PRIMARIES_BT2020", KTX2_DF_PRIMARIES_BT2020)
- .value("KTX2_DF_PRIMARIES_CIEXYZ", KTX2_DF_PRIMARIES_CIEXYZ)
- .value("KTX2_DF_PRIMARIES_ACES", KTX2_DF_PRIMARIES_ACES)
- .value("KTX2_DF_PRIMARIES_ACESCC", KTX2_DF_PRIMARIES_ACESCC)
- .value("KTX2_DF_PRIMARIES_NTSC1953", KTX2_DF_PRIMARIES_NTSC1953)
- .value("KTX2_DF_PRIMARIES_PAL525", KTX2_DF_PRIMARIES_PAL525)
- .value("KTX2_DF_PRIMARIES_DISPLAYP3", KTX2_DF_PRIMARIES_DISPLAYP3)
- .value("KTX2_DF_PRIMARIES_ADOBERGB", KTX2_DF_PRIMARIES_ADOBERGB)
- ;
+ .value("KTX2_DF_PRIMARIES_UNSPECIFIED", KTX2_DF_PRIMARIES_UNSPECIFIED)
+ .value("KTX2_DF_PRIMARIES_BT709", KTX2_DF_PRIMARIES_BT709)
+ .value("KTX2_DF_PRIMARIES_SRGB", KTX2_DF_PRIMARIES_SRGB)
+ .value("KTX2_DF_PRIMARIES_BT601_EBU", KTX2_DF_PRIMARIES_BT601_EBU)
+ .value("KTX2_DF_PRIMARIES_BT601_SMPTE", KTX2_DF_PRIMARIES_BT601_SMPTE)
+ .value("KTX2_DF_PRIMARIES_BT2020", KTX2_DF_PRIMARIES_BT2020)
+ .value("KTX2_DF_PRIMARIES_CIEXYZ", KTX2_DF_PRIMARIES_CIEXYZ)
+ .value("KTX2_DF_PRIMARIES_ACES", KTX2_DF_PRIMARIES_ACES)
+ .value("KTX2_DF_PRIMARIES_ACESCC", KTX2_DF_PRIMARIES_ACESCC)
+ .value("KTX2_DF_PRIMARIES_NTSC1953", KTX2_DF_PRIMARIES_NTSC1953)
+ .value("KTX2_DF_PRIMARIES_PAL525", KTX2_DF_PRIMARIES_PAL525)
+ .value("KTX2_DF_PRIMARIES_DISPLAYP3", KTX2_DF_PRIMARIES_DISPLAYP3)
+ .value("KTX2_DF_PRIMARIES_ADOBERGB", KTX2_DF_PRIMARIES_ADOBERGB)
+ ;
// Expose ktx2_image_level_info structure
value_object("KTX2ImageLevelInfo")
- .field("levelIndex", &ktx2_image_level_info::m_level_index)
- .field("layerIndex", &ktx2_image_level_info::m_layer_index)
- .field("faceIndex", &ktx2_image_level_info::m_face_index)
- .field("origWidth", &ktx2_image_level_info::m_orig_width)
- .field("origHeight", &ktx2_image_level_info::m_orig_height)
- .field("width", &ktx2_image_level_info::m_width)
- .field("height", &ktx2_image_level_info::m_height)
- .field("numBlocksX", &ktx2_image_level_info::m_num_blocks_x)
- .field("numBlocksY", &ktx2_image_level_info::m_num_blocks_y)
- .field("totalBlocks", &ktx2_image_level_info::m_total_blocks)
- .field("alphaFlag", &ktx2_image_level_info::m_alpha_flag)
- .field("iframeFlag", &ktx2_image_level_info::m_iframe_flag)
- ;
+ .field("levelIndex", &ktx2_image_level_info::m_level_index)
+ .field("layerIndex", &ktx2_image_level_info::m_layer_index)
+ .field("faceIndex", &ktx2_image_level_info::m_face_index)
+ .field("origWidth", &ktx2_image_level_info::m_orig_width)
+ .field("origHeight", &ktx2_image_level_info::m_orig_height)
+ .field("width", &ktx2_image_level_info::m_width)
+ .field("height", &ktx2_image_level_info::m_height)
+ .field("numBlocksX", &ktx2_image_level_info::m_num_blocks_x)
+ .field("numBlocksY", &ktx2_image_level_info::m_num_blocks_y)
+ .field("totalBlocks", &ktx2_image_level_info::m_total_blocks)
+ .field("alphaFlag", &ktx2_image_level_info::m_alpha_flag)
+ .field("iframeFlag", &ktx2_image_level_info::m_iframe_flag)
+ ;
// Expose the ktx2_header_js structure
value_object("KTX2Header")
- .field("vkFormat", &ktx2_header_js::m_vk_format)
- .field("typeSize", &ktx2_header_js::m_type_size)
- .field("pixelWidth", &ktx2_header_js::m_pixel_width)
- .field("pixelHeight", &ktx2_header_js::m_pixel_height)
- .field("pixelDepth", &ktx2_header_js::m_pixel_depth)
- .field("layerCount", &ktx2_header_js::m_layer_count)
- .field("faceCount", &ktx2_header_js::m_face_count)
- .field("levelCount", &ktx2_header_js::m_level_count)
- .field("supercompressionScheme", &ktx2_header_js::m_supercompression_scheme)
- .field("dfdByteOffset", &ktx2_header_js::m_dfd_byte_offset)
- .field("dfdByteLength", &ktx2_header_js::m_dfd_byte_length)
- .field("kvdByteOffset", &ktx2_header_js::m_kvd_byte_offset)
- .field("kvdByteLength", &ktx2_header_js::m_kvd_byte_length)
- .field("sgdByteOffset", &ktx2_header_js::m_sgd_byte_offset)
- .field("sgdByteLength", &ktx2_header_js::m_sgd_byte_length)
- ;
+ .field("vkFormat", &ktx2_header_js::m_vk_format)
+ .field("typeSize", &ktx2_header_js::m_type_size)
+ .field("pixelWidth", &ktx2_header_js::m_pixel_width)
+ .field("pixelHeight", &ktx2_header_js::m_pixel_height)
+ .field("pixelDepth", &ktx2_header_js::m_pixel_depth)
+ .field("layerCount", &ktx2_header_js::m_layer_count)
+ .field("faceCount", &ktx2_header_js::m_face_count)
+ .field("levelCount", &ktx2_header_js::m_level_count)
+ .field("supercompressionScheme", &ktx2_header_js::m_supercompression_scheme)
+ .field("dfdByteOffset", &ktx2_header_js::m_dfd_byte_offset)
+ .field("dfdByteLength", &ktx2_header_js::m_dfd_byte_length)
+ .field("kvdByteOffset", &ktx2_header_js::m_kvd_byte_offset)
+ .field("kvdByteLength", &ktx2_header_js::m_kvd_byte_length)
+ .field("sgdByteOffset", &ktx2_header_js::m_sgd_byte_offset)
+ .field("sgdByteLength", &ktx2_header_js::m_sgd_byte_length)
+ ;
// KTX2 transcoder class
class_("KTX2File")
- .constructor()
- .function("isValid", &ktx2_file::isValid)
- .function("close", &ktx2_file::close)
- .function("getDFDSize", &ktx2_file::getDFDSize)
- .function("getDFD", &ktx2_file::getDFD)
- .function("getHeader", &ktx2_file::getHeader)
- .function("hasKey", &ktx2_file::hasKey)
- .function("getTotalKeys", &ktx2_file::getTotalKeys)
- .function("getKey", &ktx2_file::getKey)
- .function("getKeyValueSize", &ktx2_file::getKeyValueSize)
- .function("getKeyValue", &ktx2_file::getKeyValue)
- .function("getWidth", &ktx2_file::getWidth)
- .function("getHeight", &ktx2_file::getHeight)
- .function("getFaces", &ktx2_file::getFaces)
- .function("getLayers", &ktx2_file::getLayers)
- .function("getLevels", &ktx2_file::getLevels)
- .function("getFormat", &ktx2_file::getFormat)
- .function("isUASTC", &ktx2_file::isUASTC)
- .function("isETC1S", &ktx2_file::isETC1S)
- .function("getHasAlpha", &ktx2_file::getHasAlpha)
- .function("getDFDColorModel", &ktx2_file::getDFDColorModel)
- .function("getDFDColorPrimaries", &ktx2_file::getDFDColorPrimaries)
- .function("getDFDTransferFunc", &ktx2_file::getDFDTransferFunc)
- .function("getDFDFlags", &ktx2_file::getDFDFlags)
- .function("getDFDTotalSamples", &ktx2_file::getDFDTotalSamples)
- .function("getDFDChannelID0", &ktx2_file::getDFDChannelID0)
- .function("getDFDChannelID1", &ktx2_file::getDFDChannelID1)
- .function("isVideo", &ktx2_file::isVideo)
- .function("getETC1SImageDescImageFlags", &ktx2_file::getETC1SImageDescImageFlags)
- .function("getImageLevelInfo", &ktx2_file::getImageLevelInfo)
- .function("getImageTranscodedSizeInBytes", &ktx2_file::getImageTranscodedSizeInBytes)
- .function("startTranscoding", &ktx2_file::startTranscoding)
- .function("transcodeImage", &ktx2_file::transcodeImage)
- ;
+ .constructor()
+ .function("isValid", &ktx2_file::isValid)
+ .function("close", &ktx2_file::close)
+ .function("getDFDSize", &ktx2_file::getDFDSize)
+ .function("getDFD", &ktx2_file::getDFD)
+ .function("getHeader", &ktx2_file::getHeader)
+ .function("hasKey", &ktx2_file::hasKey)
+ .function("getTotalKeys", &ktx2_file::getTotalKeys)
+ .function("getKey", &ktx2_file::getKey)
+ .function("getKeyValueSize", &ktx2_file::getKeyValueSize)
+ .function("getKeyValue", &ktx2_file::getKeyValue)
+ .function("getWidth", &ktx2_file::getWidth)
+ .function("getHeight", &ktx2_file::getHeight)
+ .function("getFaces", &ktx2_file::getFaces)
+ .function("getLayers", &ktx2_file::getLayers)
+ .function("getLevels", &ktx2_file::getLevels)
+ .function("getFormat", &ktx2_file::getFormat)
+ .function("isUASTC", &ktx2_file::isUASTC)
+ .function("isHDR", &ktx2_file::isHDR)
+ .function("isETC1S", &ktx2_file::isETC1S)
+ .function("getHasAlpha", &ktx2_file::getHasAlpha)
+ .function("getDFDColorModel", &ktx2_file::getDFDColorModel)
+ .function("getDFDColorPrimaries", &ktx2_file::getDFDColorPrimaries)
+ .function("getDFDTransferFunc", &ktx2_file::getDFDTransferFunc)
+ .function("getDFDFlags", &ktx2_file::getDFDFlags)
+ .function("getDFDTotalSamples", &ktx2_file::getDFDTotalSamples)
+ .function("getDFDChannelID0", &ktx2_file::getDFDChannelID0)
+ .function("getDFDChannelID1", &ktx2_file::getDFDChannelID1)
+ .function("isVideo", &ktx2_file::isVideo)
+ .function("getETC1SImageDescImageFlags", &ktx2_file::getETC1SImageDescImageFlags)
+ .function("getImageLevelInfo", &ktx2_file::getImageLevelInfo)
+ .function("getImageTranscodedSizeInBytes", &ktx2_file::getImageTranscodedSizeInBytes)
+ .function("startTranscoding", &ktx2_file::startTranscoding)
+ .function("transcodeImage", &ktx2_file::transcodeImage)
+ ;
#endif // BASISD_SUPPORT_KTX2
// Optional encoding/compression support of .basis and .KTX2 files (the same class encodes/compresses to either format).
-
+
#if BASISU_SUPPORT_ENCODING
- // Compressor Constants
+ // Compressor Constants
+
+ constant("BASISU_MAX_SUPPORTED_TEXTURE_DIMENSION", BASISU_MAX_SUPPORTED_TEXTURE_DIMENSION);
+ constant("BASISU_DEFAULT_ENDPOINT_RDO_THRESH", BASISU_DEFAULT_ENDPOINT_RDO_THRESH);
+ constant("BASISU_DEFAULT_SELECTOR_RDO_THRESH", BASISU_DEFAULT_SELECTOR_RDO_THRESH);
+ constant("BASISU_DEFAULT_QUALITY", BASISU_DEFAULT_QUALITY);
+ constant("BASISU_DEFAULT_HYBRID_SEL_CB_QUALITY_THRESH", BASISU_DEFAULT_HYBRID_SEL_CB_QUALITY_THRESH);
+ constant("BASISU_MAX_IMAGE_DIMENSION", BASISU_MAX_IMAGE_DIMENSION);
+ constant("BASISU_QUALITY_MIN", BASISU_QUALITY_MIN);
+ constant("BASISU_QUALITY_MAX", BASISU_QUALITY_MAX);
+ constant("BASISU_MAX_ENDPOINT_CLUSTERS", BASISU_MAX_ENDPOINT_CLUSTERS);
+ constant("BASISU_MAX_SELECTOR_CLUSTERS", BASISU_MAX_SELECTOR_CLUSTERS);
+ constant("BASISU_MAX_SLICES", BASISU_MAX_SLICES);
+ constant("BASISU_RDO_UASTC_DICT_SIZE_DEFAULT", BASISU_RDO_UASTC_DICT_SIZE_DEFAULT);
+ constant("BASISU_RDO_UASTC_DICT_SIZE_MIN", BASISU_RDO_UASTC_DICT_SIZE_MIN);
+ constant("BASISU_RDO_UASTC_DICT_SIZE_MAX", BASISU_RDO_UASTC_DICT_SIZE_MAX);
+ constant("BASISU_MAX_RESAMPLER_FILTERS", g_num_resample_filters);
+ constant("BASISU_DEFAULT_COMPRESSION_LEVEL", BASISU_DEFAULT_COMPRESSION_LEVEL);
+ constant("BASISU_MAX_COMPRESSION_LEVEL", BASISU_MAX_COMPRESSION_LEVEL);
+
+ // The maximum representable floating point value in a UASTC HDR texture (any larger values will get clamped and a warning issued).
+ constant("ASTC_HDR_MAX_VAL", basist::ASTC_HDR_MAX_VAL);
+
+ constant("cPackUASTCLevelFastest", cPackUASTCLevelFastest);
+ constant("cPackUASTCLevelFaster", cPackUASTCLevelFaster);
+ constant("cPackUASTCLevelDefault", cPackUASTCLevelDefault);
+ constant("cPackUASTCLevelSlower", cPackUASTCLevelSlower);
+ constant("cPackUASTCLevelVerySlow", cPackUASTCLevelVerySlow);
+ constant("cPackUASTCLevelMask", cPackUASTCLevelMask);
+ constant("cPackUASTCFavorUASTCError", cPackUASTCFavorUASTCError);
+ constant("cPackUASTCFavorBC7Error", cPackUASTCFavorBC7Error);
+ constant("cPackUASTCETC1FasterHints", cPackUASTCETC1FasterHints);
+ constant("cPackUASTCETC1FastestHints", cPackUASTCETC1FastestHints);
+ constant("cPackUASTCETC1DisableFlipAndIndividual", cPackUASTCETC1DisableFlipAndIndividual);
+
+ constant("UASTC_RDO_DEFAULT_MAX_ALLOWED_RMS_INCREASE_RATIO", UASTC_RDO_DEFAULT_MAX_ALLOWED_RMS_INCREASE_RATIO);
+ constant("UASTC_RDO_DEFAULT_SKIP_BLOCK_RMS_THRESH", UASTC_RDO_DEFAULT_SKIP_BLOCK_RMS_THRESH);
- constant("BASISU_MAX_SUPPORTED_TEXTURE_DIMENSION", BASISU_MAX_SUPPORTED_TEXTURE_DIMENSION);
- constant("BASISU_DEFAULT_ENDPOINT_RDO_THRESH", BASISU_DEFAULT_ENDPOINT_RDO_THRESH);
- constant("BASISU_DEFAULT_SELECTOR_RDO_THRESH", BASISU_DEFAULT_SELECTOR_RDO_THRESH);
- constant("BASISU_DEFAULT_QUALITY", BASISU_DEFAULT_QUALITY);
- constant("BASISU_DEFAULT_HYBRID_SEL_CB_QUALITY_THRESH", BASISU_DEFAULT_HYBRID_SEL_CB_QUALITY_THRESH);
- constant("BASISU_MAX_IMAGE_DIMENSION", BASISU_MAX_IMAGE_DIMENSION);
- constant("BASISU_QUALITY_MIN", BASISU_QUALITY_MIN);
- constant("BASISU_QUALITY_MAX", BASISU_QUALITY_MAX);
- constant("BASISU_MAX_ENDPOINT_CLUSTERS", BASISU_MAX_ENDPOINT_CLUSTERS);
- constant("BASISU_MAX_SELECTOR_CLUSTERS", BASISU_MAX_SELECTOR_CLUSTERS);
- constant("BASISU_MAX_SLICES", BASISU_MAX_SLICES);
- constant("BASISU_RDO_UASTC_DICT_SIZE_DEFAULT", BASISU_RDO_UASTC_DICT_SIZE_DEFAULT);
- constant("BASISU_RDO_UASTC_DICT_SIZE_MIN", BASISU_RDO_UASTC_DICT_SIZE_MIN);
- constant("BASISU_RDO_UASTC_DICT_SIZE_MAX", BASISU_RDO_UASTC_DICT_SIZE_MAX);
- constant("BASISU_MAX_RESAMPLER_FILTERS", g_num_resample_filters);
- constant("BASISU_DEFAULT_COMPRESSION_LEVEL", BASISU_DEFAULT_COMPRESSION_LEVEL);
- constant("BASISU_MAX_COMPRESSION_LEVEL", BASISU_MAX_COMPRESSION_LEVEL);
-
- constant("cPackUASTCLevelFastest", cPackUASTCLevelFastest);
- constant("cPackUASTCLevelFaster", cPackUASTCLevelFaster);
- constant("cPackUASTCLevelDefault", cPackUASTCLevelDefault);
- constant("cPackUASTCLevelSlower", cPackUASTCLevelSlower);
- constant("cPackUASTCLevelVerySlow", cPackUASTCLevelVerySlow);
- constant("cPackUASTCLevelMask", cPackUASTCLevelMask);
- constant("cPackUASTCFavorUASTCError", cPackUASTCFavorUASTCError);
- constant("cPackUASTCFavorBC7Error", cPackUASTCFavorBC7Error);
- constant("cPackUASTCETC1FasterHints", cPackUASTCETC1FasterHints);
- constant("cPackUASTCETC1FastestHints", cPackUASTCETC1FastestHints);
- constant("cPackUASTCETC1DisableFlipAndIndividual", cPackUASTCETC1DisableFlipAndIndividual);
-
- constant("UASTC_RDO_DEFAULT_MAX_ALLOWED_RMS_INCREASE_RATIO", UASTC_RDO_DEFAULT_MAX_ALLOWED_RMS_INCREASE_RATIO);
- constant("UASTC_RDO_DEFAULT_SKIP_BLOCK_RMS_THRESH", UASTC_RDO_DEFAULT_SKIP_BLOCK_RMS_THRESH);
-
+ enum_("hdr_image_type")
+ .value("cHITRGBAHalfFloat", hdr_image_type::cHITRGBAHalfFloat)
+ .value("cHITRGBAFloat", hdr_image_type::cHITRGBAFloat)
+ .value("cHITPNGImage", hdr_image_type::cHITPNGImage)
+ .value("cHITEXRImage", hdr_image_type::cHITEXRImage)
+ .value("cHITHDRImage", hdr_image_type::cHITHDRImage)
+ ;
+
// Compression/encoding object.
// You create this object, call the set() methods to fill in the parameters/source images/options, call encode(), and you get back a .basis or .KTX2 file.
// You can call .encode() multiple times, changing the parameters/options in between calls.
// By default this class encodes to .basis, but call setCreateKTX2File() with true to get .KTX2 files.
class_("BasisEncoder")
- .constructor<>()
+ .constructor<>()
- // Compresses the provided source slice(s) to an output .basis file.
- // At the minimum, you must provided at least 1 source slice by calling setSliceSourceImage() before calling this method.
- .function("encode", optional_override([](basis_encoder& self, const emscripten::val& dst_basis_file_js_val) {
- return self.encode(dst_basis_file_js_val);
- }))
+ // Compresses the provided source slice(s) to an output .basis file.
+ // At the minimum, you must provided at least 1 source slice by calling setSliceSourceImage() or setSliceSourceImageHDR() (for UASTC HDR) before calling this method.
+ .function("encode", optional_override([](basis_encoder& self, const emscripten::val& dst_basis_file_js_val) {
+ return self.encode(dst_basis_file_js_val);
+ }))
- // Sets the slice's source image, either from a PNG file or from a raw 32-bit RGBA raster image.
- // If the input is a raster image, the buffer must be width*height*4 bytes in size. The raster image is stored in top down scanline order.
- // The first texel is the top-left texel. The texel byte order in memory is R,G,B,A (R first at offset 0, A last at offset 3).
- // slice_index is the slice to change. Valid range is [0,BASISU_MAX_SLICES-1].
- .function("setSliceSourceImage", optional_override([](basis_encoder& self, uint32_t slice_index, const emscripten::val& src_image_js_val, uint32_t width, uint32_t height, bool src_image_is_png) {
- return self.set_slice_source_image(slice_index, src_image_js_val, width, height, src_image_is_png);
- }))
+ // Sets the slice's source image, either from a PNG file or from a raw 32-bit RGBA raster image.
+ // If the input is a raster image, the buffer must be width*height*4 bytes in size. The raster image is stored in top down scanline order.
+ // The first texel is the top-left texel. The texel byte order in memory is R,G,B,A (R first at offset 0, A last at offset 3).
+ // slice_index is the slice to change. Valid range is [0,BASISU_MAX_SLICES-1].
+ .function("setSliceSourceImage", optional_override([](basis_encoder& self, uint32_t slice_index, const emscripten::val& src_image_js_val, uint32_t width, uint32_t height, bool src_image_is_png) {
+ return self.set_slice_source_image(slice_index, src_image_js_val, width, height, src_image_is_png);
+ }))
+
+ .function("setSliceSourceImageHDR", optional_override([](basis_encoder& self, uint32_t slice_index, const emscripten::val& src_image_js_val, uint32_t width, uint32_t height, uint32_t img_type, bool ldr_srgb_to_linear_conversion) {
+ return self.set_slice_source_image_hdr(slice_index, src_image_js_val, width, height, (hdr_image_type)img_type, ldr_srgb_to_linear_conversion);
+ }))
- // If true, the encoder will output a UASTC texture, otherwise a ETC1S texture.
- .function("setUASTC", optional_override([](basis_encoder& self, bool uastc_flag) {
- self.m_params.m_uastc = uastc_flag;
- }))
+ // If true, the encoder will output a UASTC texture, otherwise a ETC1S texture.
+ .function("setUASTC", optional_override([](basis_encoder& self, bool uastc_flag) {
+ self.m_params.m_uastc = uastc_flag;
+ }))
+
+ // If true, the encoder will output a UASTC HDR texture, otherwise it works in the default LDR mode.
+ .function("setHDR", optional_override([](basis_encoder& self, bool hdr_flag) {
+ self.m_params.m_hdr = hdr_flag;
+ }))
- // If true the source images will be Y flipped before compression.
- .function("setYFlip", optional_override([](basis_encoder& self, bool y_flip_flag) {
- self.m_params.m_y_flip = y_flip_flag;
- }))
+ // Sets the quality vs. encoder performance tradeoff (0-4, default is 1). Higher=slower but better quality.
+ .function("setUASTCHDRQualityLevel", optional_override([](basis_encoder& self, int level) {
+ assert((level >= astc_hdr_codec_options::cMinLevel) && (level <= astc_hdr_codec_options::cMaxLevel));
+ self.m_params.m_uastc_hdr_options.set_quality_level(level);
+ }))
- // Enables debug output to stdout
- .function("setDebug", optional_override([](basis_encoder& self, bool debug_flag) {
- self.m_params.m_debug = debug_flag;
- g_debug_printf = debug_flag;
- }))
-
- // If true, the input is assumed to be in sRGB space. Be sure to set this correctly! (Examples: True on photos, albedo/spec maps, and false on normal maps.)
- .function("setPerceptual", optional_override([](basis_encoder& self, bool perceptual_flag) {
- self.m_params.m_perceptual = perceptual_flag;
- }))
-
- // Check source images for active/used alpha channels
- .function("setCheckForAlpha", optional_override([](basis_encoder& self, bool check_for_alpha_flag) {
- self.m_params.m_check_for_alpha = check_for_alpha_flag;
- }))
-
- // Fource output .basis file to have an alpha channel
- .function("setForceAlpha", optional_override([](basis_encoder& self, bool force_alpha_flag) {
- self.m_params.m_force_alpha = force_alpha_flag;
- }))
-
- // Set source image component swizzle.
- // r,g,b,a - valid range is [0,3]
- .function("setSwizzle", optional_override([](basis_encoder& self, uint32_t r, uint32_t g, uint32_t b, uint32_t a) {
- assert((r < 4) && (g < 4) && (b < 4) && (a < 4));
- self.m_params.m_swizzle[0] = (char)r;
- self.m_params.m_swizzle[1] = (char)g;
- self.m_params.m_swizzle[2] = (char)b;
- self.m_params.m_swizzle[3] = (char)a;
- }))
-
- // If true, the input is assumed to be a normal map, and all source texels will be renormalized before encoding.
- .function("setRenormalize", optional_override([](basis_encoder& self, bool renormalize_flag) {
- self.m_params.m_renormalize = renormalize_flag;
- }))
-
- // Sets the max # of endpoint clusters for ETC1S mode. Use instead of setQualityLevel.
- // Default is 512, range is [1,BASISU_MAX_ENDPOINT_CLUSTERS]
- .function("setMaxEndpointClusters", optional_override([](basis_encoder& self, uint32_t max_endpoint_clusters) {
- assert(max_endpoint_clusters <= BASISU_MAX_ENDPOINT_CLUSTERS);
- self.m_params.m_max_endpoint_clusters = max_endpoint_clusters;
- }))
-
- // Sets the max # of selectors clusters for ETC1S mode. Use instead of setQualityLevel.
- // Default is 512, range is [1,BASISU_MAX_ENDPOINT_CLUSTERS]
- .function("setMaxSelectorClusters", optional_override([](basis_encoder& self, uint32_t max_selector_clusters) {
- assert(max_selector_clusters <= BASISU_MAX_SELECTOR_CLUSTERS);
- self.m_params.m_max_selector_clusters = max_selector_clusters;
- }))
-
- // Sets the ETC1S encoder's quality level, which controls the file size vs. quality tradeoff.
- // Default is -1 (meaning unused - the compressor will use m_max_endpoint_clusters/m_max_selector_clusters instead to control the codebook sizes).
- // Range is [1,BASISU_QUALITY_MAX]
- .function("setQualityLevel", optional_override([](basis_encoder& self, int quality_level) {
- assert(quality_level >= -1 && quality_level <= BASISU_QUALITY_MAX);
- self.m_params.m_quality_level = quality_level;
- }))
+ // If true the source images will be Y flipped before compression.
+ .function("setYFlip", optional_override([](basis_encoder& self, bool y_flip_flag) {
+ self.m_params.m_y_flip = y_flip_flag;
+ }))
- // The compression_level parameter controls the encoder perf vs. file size tradeoff for ETC1S files.
- // It does not directly control file size vs. quality - see quality_level().
- // Default is BASISU_DEFAULT_COMPRESSION_LEVEL, range is [0,BASISU_MAX_COMPRESSION_LEVEL]
- .function("setCompressionLevel", optional_override([](basis_encoder& self, int comp_level) {
- assert(comp_level >= 0 && comp_level <= BASISU_MAX_COMPRESSION_LEVEL);
- self.m_params.m_compression_level = comp_level;
- }))
-
- // setNormalMapMode is the same as the basisu.exe "-normal_map" option. It tunes several codec parameters so compression works better on normal maps.
- .function("setNormalMap", optional_override([](basis_encoder& self) {
- self.m_params.m_perceptual = false;
- self.m_params.m_mip_srgb = false;
- self.m_params.m_no_selector_rdo = true;
- self.m_params.m_no_endpoint_rdo = true;
- }))
-
- // Sets selector RDO threshold
- // Default is BASISU_DEFAULT_SELECTOR_RDO_THRESH, range is [0,1e+10]
- .function("setSelectorRDOThresh", optional_override([](basis_encoder& self, float selector_rdo_thresh) {
- self.m_params.m_selector_rdo_thresh = selector_rdo_thresh;
- }))
-
- // Sets endpoint RDO threshold
- // Default is BASISU_DEFAULT_ENDPOINT_RDO_THRESH, range is [0,1e+10]
- .function("setEndpointRDOThresh", optional_override([](basis_encoder& self, float endpoint_rdo_thresh) {
- self.m_params.m_endpoint_rdo_thresh = endpoint_rdo_thresh;
- }))
+ // Enables debug output to stdout
+ .function("setDebug", optional_override([](basis_encoder& self, bool debug_flag) {
+ self.m_params.m_debug = debug_flag;
+ g_debug_printf = debug_flag;
+ }))
+
+ // If true, the input is assumed to be in sRGB space. Be sure to set this correctly! (Examples: True on photos, albedo/spec maps, and false on normal maps.)
+ // In HDR mode, if perceptual is true R and G are weighted higher (2.0, 3.0) than B (1.0). Otherwise the encoder uses equal weightings for each channel.
+ .function("setPerceptual", optional_override([](basis_encoder& self, bool perceptual_flag) {
+ self.m_params.m_perceptual = perceptual_flag;
+ }))
+
+ // Check source images for active/used alpha channels
+ .function("setCheckForAlpha", optional_override([](basis_encoder& self, bool check_for_alpha_flag) {
+ self.m_params.m_check_for_alpha = check_for_alpha_flag;
+ }))
+
+ // Fource output .basis/.ktx2 file to have an alpha channel
+ .function("setForceAlpha", optional_override([](basis_encoder& self, bool force_alpha_flag) {
+ self.m_params.m_force_alpha = force_alpha_flag;
+ }))
+
+ // Set source image component swizzle.
+ // r,g,b,a - valid range is [0,3]
+ .function("setSwizzle", optional_override([](basis_encoder& self, uint32_t r, uint32_t g, uint32_t b, uint32_t a) {
+ assert((r < 4) && (g < 4) && (b < 4) && (a < 4));
+ self.m_params.m_swizzle[0] = (char)r;
+ self.m_params.m_swizzle[1] = (char)g;
+ self.m_params.m_swizzle[2] = (char)b;
+ self.m_params.m_swizzle[3] = (char)a;
+ }))
+
+ // If true, the input is assumed to be a normal map, and all source texels will be renormalized before encoding.
+ .function("setRenormalize", optional_override([](basis_encoder& self, bool renormalize_flag) {
+ self.m_params.m_renormalize = renormalize_flag;
+ }))
+
+ // Sets the max # of endpoint clusters for ETC1S mode. Use instead of setQualityLevel.
+ // Default is 512, range is [1,BASISU_MAX_ENDPOINT_CLUSTERS]
+ .function("setMaxEndpointClusters", optional_override([](basis_encoder& self, uint32_t max_endpoint_clusters) {
+ assert(max_endpoint_clusters <= BASISU_MAX_ENDPOINT_CLUSTERS);
+ self.m_params.m_max_endpoint_clusters = max_endpoint_clusters;
+ }))
+
+ // Sets the max # of selectors clusters for ETC1S mode. Use instead of setQualityLevel.
+ // Default is 512, range is [1,BASISU_MAX_ENDPOINT_CLUSTERS]
+ .function("setMaxSelectorClusters", optional_override([](basis_encoder& self, uint32_t max_selector_clusters) {
+ assert(max_selector_clusters <= BASISU_MAX_SELECTOR_CLUSTERS);
+ self.m_params.m_max_selector_clusters = max_selector_clusters;
+ }))
+
+ // Sets the ETC1S encoder's quality level, which controls the file size vs. quality tradeoff.
+ // Default is -1 (meaning unused - the compressor will use m_max_endpoint_clusters/m_max_selector_clusters instead to control the codebook sizes).
+ // Range is [1,BASISU_QUALITY_MAX]
+ .function("setQualityLevel", optional_override([](basis_encoder& self, int quality_level) {
+ assert(quality_level >= -1 && quality_level <= BASISU_QUALITY_MAX);
+ self.m_params.m_quality_level = quality_level;
+ }))
+
+ // The compression_level parameter controls the encoder perf vs. file size tradeoff for ETC1S files.
+ // It does not directly control file size vs. quality - see quality_level().
+ // Default is BASISU_DEFAULT_COMPRESSION_LEVEL, range is [0,BASISU_MAX_COMPRESSION_LEVEL]
+ .function("setCompressionLevel", optional_override([](basis_encoder& self, int comp_level) {
+ assert(comp_level >= 0 && comp_level <= BASISU_MAX_COMPRESSION_LEVEL);
+ self.m_params.m_compression_level = comp_level;
+ }))
+
+ // setNormalMapMode is the same as the basisu.exe "-normal_map" option. It tunes several codec parameters so compression works better on normal maps.
+ .function("setNormalMap", optional_override([](basis_encoder& self) {
+ self.m_params.m_perceptual = false;
+ self.m_params.m_mip_srgb = false;
+ self.m_params.m_no_selector_rdo = true;
+ self.m_params.m_no_endpoint_rdo = true;
+ }))
+
+ // Sets selector RDO threshold
+ // Default is BASISU_DEFAULT_SELECTOR_RDO_THRESH, range is [0,1e+10]
+ .function("setSelectorRDOThresh", optional_override([](basis_encoder& self, float selector_rdo_thresh) {
+ self.m_params.m_selector_rdo_thresh = selector_rdo_thresh;
+ }))
+
+ // Sets endpoint RDO threshold
+ // Default is BASISU_DEFAULT_ENDPOINT_RDO_THRESH, range is [0,1e+10]
+ .function("setEndpointRDOThresh", optional_override([](basis_encoder& self, float endpoint_rdo_thresh) {
+ self.m_params.m_endpoint_rdo_thresh = endpoint_rdo_thresh;
+ }))
#if BASISD_SUPPORT_KTX2
- // --- KTX2 related options
- //
- // Create .KTX2 files instead of .basis files. By default this is FALSE.
- .function("setCreateKTX2File", optional_override([](basis_encoder& self, bool create_ktx2_file) {
- self.m_params.m_create_ktx2_file = create_ktx2_file;
- }))
+ // --- KTX2 related options
+ //
+ // Create .KTX2 files instead of .basis files. By default this is FALSE.
+ .function("setCreateKTX2File", optional_override([](basis_encoder& self, bool create_ktx2_file) {
+ self.m_params.m_create_ktx2_file = create_ktx2_file;
+ }))
- // KTX2: Use UASTC Zstandard supercompression. Defaults to disabled or KTX2_SS_NONE.
- .function("setKTX2UASTCSupercompression", optional_override([](basis_encoder& self, bool use_zstandard) {
- self.m_params.m_ktx2_uastc_supercompression = use_zstandard ? basist::KTX2_SS_ZSTANDARD : basist::KTX2_SS_NONE;
- }))
+ // KTX2: Use UASTC Zstandard supercompression. Defaults to disabled or KTX2_SS_NONE.
+ .function("setKTX2UASTCSupercompression", optional_override([](basis_encoder& self, bool use_zstandard) {
+ self.m_params.m_ktx2_uastc_supercompression = use_zstandard ? basist::KTX2_SS_ZSTANDARD : basist::KTX2_SS_NONE;
+ }))
- // KTX2: Use sRGB transfer func in the file's DFD. Default is FALSE. This should very probably match the "perceptual" setting.
- .function("setKTX2SRGBTransferFunc", optional_override([](basis_encoder& self, bool srgb_transfer_func) {
- self.m_params.m_ktx2_srgb_transfer_func = srgb_transfer_func;
- }))
+ // KTX2: Use sRGB transfer func in the file's DFD. Default is FALSE. This should very probably match the "perceptual" setting.
+ .function("setKTX2SRGBTransferFunc", optional_override([](basis_encoder& self, bool srgb_transfer_func) {
+ self.m_params.m_ktx2_srgb_transfer_func = srgb_transfer_func;
+ }))
- // TODO: Expose KTX2 key value array, other options to JavaScript. See encoder/basisu_comp.h.
+ // TODO: Expose KTX2 key value array, other options to JavaScript. See encoder/basisu_comp.h.
#endif
-
- // --- Mip-map options
-
- // If true mipmaps will be generated from the source images
- .function("setMipGen", optional_override([](basis_encoder& self, bool mip_gen_flag) {
- self.m_params.m_mip_gen = mip_gen_flag;
- }))
-
- // Set mipmap filter's scale factor
- // default is 1, range is [.000125, 4.0]
- .function("setMipScale", optional_override([](basis_encoder& self, float mip_scale) {
- self.m_params.m_mip_scale = mip_scale;
- }))
-
- // Sets the mipmap filter to apply
- // mip_filter must be < BASISU_MAX_RESAMPLER_FILTERS
- // See the end of basisu_resample_filters.cpp: g_resample_filters[]
- .function("setMipFilter", optional_override([](basis_encoder& self, uint32_t mip_filter) {
- assert(mip_filter < g_num_resample_filters);
- if (mip_filter < g_num_resample_filters)
- self.m_params.m_mip_filter = g_resample_filters[mip_filter].name;
- }))
-
- // If true mipmap filtering occurs in sRGB space - this generally should match the perceptual parameter.
- .function("setMipSRGB", optional_override([](basis_encoder& self, bool mip_srgb_flag) {
- self.m_params.m_mip_srgb = mip_srgb_flag;
- }))
-
- // If true, the input is assumed to be a normal map, and the texels of each mipmap will be renormalized before encoding.
- .function("setMipRenormalize", optional_override([](basis_encoder& self, bool mip_renormalize_flag) {
- self.m_params.m_mip_renormalize = mip_renormalize_flag;
- }))
-
- // If true the source texture will be sampled using wrap addressing during mipmap generation, otherwise clamp.
- .function("setMipWrapping", optional_override([](basis_encoder& self, bool mip_wrapping_flag) {
- self.m_params.m_mip_wrapping = mip_wrapping_flag;
- }))
- // Sets the mipmap generator's smallest allowed dimension.
- // default is 1, range is [1,16384]
- .function("setMipSmallestDimension", optional_override([](basis_encoder& self, int mip_smallest_dimension) {
- self.m_params.m_mip_smallest_dimension = mip_smallest_dimension;
- }))
+ // --- Mip-map options
- // Sets the .basis texture type.
- // cBASISTexTypeVideoFrames changes the encoder into video mode.
- // tex_type is enum basis_texture_type
- // default is cBASISTexType2D
- .function("setTexType", optional_override([](basis_encoder& self, uint32_t tex_type) {
- assert(tex_type < cBASISTexTypeTotal);
- self.m_params.m_tex_type = (basist::basis_texture_type)tex_type;
- }))
-
- .function("setUserData0", optional_override([](basis_encoder& self, uint32_t userdata0) {
- self.m_params.m_userdata0 = userdata0;
- }))
-
- .function("setUserData1", optional_override([](basis_encoder& self, uint32_t userdata1) {
- self.m_params.m_userdata1 = userdata1;
- }))
+ // If true mipmaps will be generated from the source images
+ .function("setMipGen", optional_override([](basis_encoder& self, bool mip_gen_flag) {
+ self.m_params.m_mip_gen = mip_gen_flag;
+ }))
- // UASTC specific flags.
+ // Set mipmap filter's scale factor
+ // default is 1, range is [.000125, 4.0]
+ .function("setMipScale", optional_override([](basis_encoder& self, float mip_scale) {
+ self.m_params.m_mip_scale = mip_scale;
+ }))
- // Sets the UASTC encoding performance vs. quality tradeoff, and other lesser used UASTC encoder flags.
- // This is a combination of flags. See cPackUASTCLevelDefault, etc.
- .function("setPackUASTCFlags", optional_override([](basis_encoder& self, uint32_t pack_uastc_flags) {
- assert((pack_uastc_flags & cPackUASTCLevelMask) >= cPackUASTCLevelFastest);
- assert((pack_uastc_flags & cPackUASTCLevelMask) <= cPackUASTCLevelVerySlow);
- self.m_params.m_pack_uastc_flags = pack_uastc_flags;
- }))
+ // Sets the mipmap filter to apply
+ // mip_filter must be < BASISU_MAX_RESAMPLER_FILTERS
+ // See the end of basisu_resample_filters.cpp: g_resample_filters[]
+ .function("setMipFilter", optional_override([](basis_encoder& self, uint32_t mip_filter) {
+ assert(mip_filter < g_num_resample_filters);
+ if (mip_filter < g_num_resample_filters)
+ self.m_params.m_mip_filter = g_resample_filters[mip_filter].name;
+ }))
- // If true, the RDO post-processor will be applied to the encoded UASTC texture data.
- .function("setRDOUASTC", optional_override([](basis_encoder& self, bool rdo_uastc) {
- self.m_params.m_rdo_uastc = rdo_uastc;
- }))
-
- // Default is 1.0 range is [0.001, 10.0]
- .function("setRDOUASTCQualityScalar", optional_override([](basis_encoder& self, float rdo_quality) {
- self.m_params.m_rdo_uastc_quality_scalar = rdo_quality;
- }))
+ // If true mipmap filtering occurs in sRGB space - this generally should match the perceptual parameter.
+ .function("setMipSRGB", optional_override([](basis_encoder& self, bool mip_srgb_flag) {
+ self.m_params.m_mip_srgb = mip_srgb_flag;
+ }))
+
+ // If true, the input is assumed to be a normal map, and the texels of each mipmap will be renormalized before encoding.
+ .function("setMipRenormalize", optional_override([](basis_encoder& self, bool mip_renormalize_flag) {
+ self.m_params.m_mip_renormalize = mip_renormalize_flag;
+ }))
+
+ // If true the source texture will be sampled using wrap addressing during mipmap generation, otherwise clamp.
+ .function("setMipWrapping", optional_override([](basis_encoder& self, bool mip_wrapping_flag) {
+ self.m_params.m_mip_wrapping = mip_wrapping_flag;
+ }))
+
+ // Sets the mipmap generator's smallest allowed dimension.
+ // default is 1, range is [1,16384]
+ .function("setMipSmallestDimension", optional_override([](basis_encoder& self, int mip_smallest_dimension) {
+ self.m_params.m_mip_smallest_dimension = mip_smallest_dimension;
+ }))
+
+ // Sets the .basis texture type.
+ // cBASISTexTypeVideoFrames changes the encoder into video mode.
+ // tex_type is enum basis_texture_type
+ // default is cBASISTexType2D
+ .function("setTexType", optional_override([](basis_encoder& self, uint32_t tex_type) {
+ assert(tex_type < cBASISTexTypeTotal);
+ self.m_params.m_tex_type = (basist::basis_texture_type)tex_type;
+ }))
+
+ .function("setUserData0", optional_override([](basis_encoder& self, uint32_t userdata0) {
+ self.m_params.m_userdata0 = userdata0;
+ }))
+
+ .function("setUserData1", optional_override([](basis_encoder& self, uint32_t userdata1) {
+ self.m_params.m_userdata1 = userdata1;
+ }))
+
+ // UASTC specific flags.
+
+ // Sets the UASTC encoding performance vs. quality tradeoff, and other lesser used UASTC encoder flags.
+ // This is a combination of flags. See cPackUASTCLevelDefault, etc.
+ .function("setPackUASTCFlags", optional_override([](basis_encoder& self, uint32_t pack_uastc_flags) {
+ assert((pack_uastc_flags & cPackUASTCLevelMask) >= cPackUASTCLevelFastest);
+ assert((pack_uastc_flags & cPackUASTCLevelMask) <= cPackUASTCLevelVerySlow);
+ self.m_params.m_pack_uastc_flags = pack_uastc_flags;
+ }))
+
+ // If true, the RDO post-processor will be applied to the encoded UASTC texture data.
+ .function("setRDOUASTC", optional_override([](basis_encoder& self, bool rdo_uastc) {
+ self.m_params.m_rdo_uastc = rdo_uastc;
+ }))
+
+ // Default is 1.0 range is [0.001, 10.0]
+ .function("setRDOUASTCQualityScalar", optional_override([](basis_encoder& self, float rdo_quality) {
+ self.m_params.m_rdo_uastc_quality_scalar = rdo_quality;
+ }))
// Default is BASISU_RDO_UASTC_DICT_SIZE_DEFAULT, range is [BASISU_RDO_UASTC_DICT_SIZE_MIN, BASISU_RDO_UASTC_DICT_SIZE_MAX]
- .function("setRDOUASTCDictSize", optional_override([](basis_encoder& self, int dict_size) {
- assert((dict_size >= BASISU_RDO_UASTC_DICT_SIZE_MIN) && (dict_size <= BASISU_RDO_UASTC_DICT_SIZE_MAX));
- self.m_params.m_rdo_uastc_dict_size = dict_size;
- }))
+ .function("setRDOUASTCDictSize", optional_override([](basis_encoder& self, int dict_size) {
+ assert((dict_size >= BASISU_RDO_UASTC_DICT_SIZE_MIN) && (dict_size <= BASISU_RDO_UASTC_DICT_SIZE_MAX));
+ self.m_params.m_rdo_uastc_dict_size = dict_size;
+ }))
// Default is UASTC_RDO_DEFAULT_MAX_ALLOWED_RMS_INCREASE_RATIO, range is [01, 100.0]
- .function("setRDOUASTCMaxAllowedRMSIncreaseRatio", optional_override([](basis_encoder& self, float rdo_uastc_max_allowed_rms_increase_ratio) {
- self.m_params.m_rdo_uastc_max_allowed_rms_increase_ratio = rdo_uastc_max_allowed_rms_increase_ratio;
- }))
+ .function("setRDOUASTCMaxAllowedRMSIncreaseRatio", optional_override([](basis_encoder& self, float rdo_uastc_max_allowed_rms_increase_ratio) {
+ self.m_params.m_rdo_uastc_max_allowed_rms_increase_ratio = rdo_uastc_max_allowed_rms_increase_ratio;
+ }))
- // Default is UASTC_RDO_DEFAULT_SKIP_BLOCK_RMS_THRESH, range is [.01f, 100.0f]
- .function("setRDOUASTCSkipBlockRMSThresh", optional_override([](basis_encoder& self, float rdo_uastc_skip_block_rms_thresh) {
- self.m_params.m_rdo_uastc_skip_block_rms_thresh = rdo_uastc_skip_block_rms_thresh;
- }))
-
- // --- Low level options
-
- // Disables selector RDO
- .function("setNoSelectorRDO", optional_override([](basis_encoder& self, bool no_selector_rdo_flag) {
- self.m_params.m_no_selector_rdo = no_selector_rdo_flag;
- }))
-
- // Disables endpoint RDO
- .function("setNoEndpointRDO", optional_override([](basis_encoder& self, bool no_endpoint_rdo_flag) {
- self.m_params.m_no_endpoint_rdo = no_endpoint_rdo_flag;
- }))
-
- // Display output PSNR statistics
- .function("setComputeStats", optional_override([](basis_encoder& self, bool compute_stats_flag) {
- self.m_params.m_compute_stats = compute_stats_flag;
- }))
+ // Default is UASTC_RDO_DEFAULT_SKIP_BLOCK_RMS_THRESH, range is [.01f, 100.0f]
+ .function("setRDOUASTCSkipBlockRMSThresh", optional_override([](basis_encoder& self, float rdo_uastc_skip_block_rms_thresh) {
+ self.m_params.m_rdo_uastc_skip_block_rms_thresh = rdo_uastc_skip_block_rms_thresh;
+ }))
- // Write output .PNG files for debugging
- .function("setDebugImages", optional_override([](basis_encoder& self, bool debug_images_flag) {
- self.m_params.m_debug_images = debug_images_flag;
- }))
+ // --- Low level options
+
+ // Disables selector RDO
+ .function("setNoSelectorRDO", optional_override([](basis_encoder& self, bool no_selector_rdo_flag) {
+ self.m_params.m_no_selector_rdo = no_selector_rdo_flag;
+ }))
+
+ // Disables endpoint RDO
+ .function("setNoEndpointRDO", optional_override([](basis_encoder& self, bool no_endpoint_rdo_flag) {
+ self.m_params.m_no_endpoint_rdo = no_endpoint_rdo_flag;
+ }))
+
+ // Display output PSNR statistics
+ .function("setComputeStats", optional_override([](basis_encoder& self, bool compute_stats_flag) {
+ self.m_params.m_compute_stats = compute_stats_flag;
+ }))
+
+ // Write output .PNG files for debugging
+ .function("setDebugImages", optional_override([](basis_encoder& self, bool debug_images_flag) {
+ self.m_params.m_debug_images = debug_images_flag;
+ }))
;
#endif // BASISU_SUPPORT_ENCODING
-
+
}
diff --git a/webgl/transcoder/build/basis_transcoder.js b/webgl/transcoder/build/basis_transcoder.js
index b42d977..6f02a4a 100644
--- a/webgl/transcoder/build/basis_transcoder.js
+++ b/webgl/transcoder/build/basis_transcoder.js
@@ -1,22 +1,19 @@
-var BASIS = (function() {
- var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
- if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename;
+var BASIS = (() => {
+ var _scriptName = typeof document != 'undefined' ? document.currentScript?.src : undefined;
+ if (typeof __filename != 'undefined') _scriptName ||= __filename;
return (
-function(BASIS) {
- BASIS = BASIS || {};
+function(moduleArg = {}) {
+ var moduleRtn;
-var Module=typeof BASIS!=="undefined"?BASIS:{};var readyPromiseResolve,readyPromiseReject;Module["ready"]=new Promise(function(resolve,reject){readyPromiseResolve=resolve;readyPromiseReject=reject});var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=require("path").dirname(scriptDirectory)+"/"}else{scriptDirectory=__dirname+"/"}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)}}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptDir){scriptDirectory=_scriptDir}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}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=function(value){tempRet0=value};var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected")}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":157,"maximum":157+0,"element":"anyfunc"});var ABORT=false;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}var UTF8Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(heap,idx,maxBytesToRead){var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heap[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.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 lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function UTF16ToString(ptr,maxBytesToRead){var endPtr=ptr;var idx=endPtr>>1;var maxIdx=idx+maxBytesToRead/2;while(!(idx>=maxIdx)&&HEAPU16[idx])++idx;endPtr=idx<<1;if(endPtr-ptr>32&&UTF16Decoder){return UTF16Decoder.decode(HEAPU8.subarray(ptr,endPtr))}else{var i=0;var str="";while(1){var codeUnit=HEAP16[ptr+i*2>>1];if(codeUnit==0||i==maxBytesToRead/2)return str;++i;str+=String.fromCharCode(codeUnit)}}}function stringToUTF16(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr}function lengthBytesUTF16(str){return str.length*2}function UTF32ToString(ptr,maxBytesToRead){var i=0;var str="";while(!(i>=maxBytesToRead/4)){var utf32=HEAP32[ptr+i*4>>2];if(utf32==0)break;++i;if(utf32>=65536){var ch=utf32-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}else{str+=String.fromCharCode(utf32)}}return str}function stringToUTF32(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i=55296&&codeUnit<=57343){var trailSurrogate=str.charCodeAt(++i);codeUnit=65536+((codeUnit&1023)<<10)|trailSurrogate&1023}HEAP32[outPtr>>2]=codeUnit;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr}function lengthBytesUTF32(str){var len=0;for(var i=0;i=55296&&codeUnit<=57343)++i;len+=4}return len}var WASM_PAGE_SIZE=65536;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}return x}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 DYNAMIC_BASE=5552064,DYNAMICTOP_PTR=309024;var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"]}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE,"maximum":2147483648/WASM_PAGE_SIZE})}if(wasmMemory){buffer=wasmMemory.buffer}INITIAL_INITIAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;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){Module["dynCall_v"](func)}else{Module["dynCall_vi"](func,callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];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 preMain(){callRuntimeCallbacks(__ATMAIN__)}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 addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var Math_ceil=Math.ceil;var Math_floor=Math.floor;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()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";out(what);err(what);ABORT=true;EXITSTATUS=1;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";throw new WebAssembly.RuntimeError(what)}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="basis_transcoder.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}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)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){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()})}return new Promise(function(resolve,reject){resolve(getBinary())})}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;removeRunDependency("wasm-instantiate")}addRunDependency("wasm-instantiate");function receiveInstantiatedSource(output){receiveInstance(output["instance"])}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource)})})}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}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();return{}}__ATINIT__.push({func:function(){___wasm_call_ctors()}});var structRegistrations={};function runDestructors(destructors){while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}}function simpleReadValueFromPointer(pointer){return this["fromWireType"](HEAPU32[pointer>>2])}var awaitingDependencies={};var registeredTypes={};var typeDependencies={};var char_0=48;var char_9=57;function makeLegalFunctionName(name){if(undefined===name){return"_unknown"}name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return"_"+name}else{return name}}function createNamedFunction(name,body){name=makeLegalFunctionName(name);return new Function("body","return function "+name+"() {\n"+' "use strict";'+" return body.apply(this, arguments);\n"+"};\n")(body)}function extendError(baseErrorType,errorName){var errorClass=createNamedFunction(errorName,function(message){this.name=errorName;this.message=message;var stack=new Error(message).stack;if(stack!==undefined){this.stack=this.toString()+"\n"+stack.replace(/^Error(:[^\n]*)?\n/,"")}});errorClass.prototype=Object.create(baseErrorType.prototype);errorClass.prototype.constructor=errorClass;errorClass.prototype.toString=function(){if(this.message===undefined){return this.name}else{return this.name+": "+this.message}};return errorClass}var InternalError=undefined;function throwInternalError(message){throw new InternalError(message)}function whenDependentTypesAreResolved(myTypes,dependentTypes,getTypeConverters){myTypes.forEach(function(type){typeDependencies[type]=dependentTypes});function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i>shift])},destructorFunction:null})}function ClassHandle_isAliasOf(other){if(!(this instanceof ClassHandle)){return false}if(!(other instanceof ClassHandle)){return false}var leftClass=this.$$.ptrType.registeredClass;var left=this.$$.ptr;var rightClass=other.$$.ptrType.registeredClass;var right=other.$$.ptr;while(leftClass.baseClass){left=leftClass.upcast(left);leftClass=leftClass.baseClass}while(rightClass.baseClass){right=rightClass.upcast(right);rightClass=rightClass.baseClass}return leftClass===rightClass&&left===right}function shallowCopyInternalPointer(o){return{count:o.count,deleteScheduled:o.deleteScheduled,preservePointerOnDelete:o.preservePointerOnDelete,ptr:o.ptr,ptrType:o.ptrType,smartPtr:o.smartPtr,smartPtrType:o.smartPtrType}}function throwInstanceAlreadyDeleted(obj){function getInstanceTypeName(handle){return handle.$$.ptrType.registeredClass.name}throwBindingError(getInstanceTypeName(obj)+" instance already deleted")}var finalizationGroup=false;function detachFinalizer(handle){}function runDestructor($$){if($$.smartPtr){$$.smartPtrType.rawDestructor($$.smartPtr)}else{$$.ptrType.registeredClass.rawDestructor($$.ptr)}}function releaseClassHandle($$){$$.count.value-=1;var toDelete=0===$$.count.value;if(toDelete){runDestructor($$)}}function attachFinalizer(handle){if("undefined"===typeof FinalizationGroup){attachFinalizer=function(handle){return handle};return handle}finalizationGroup=new FinalizationGroup(function(iter){for(var result=iter.next();!result.done;result=iter.next()){var $$=result.value;if(!$$.ptr){console.warn("object already deleted: "+$$.ptr)}else{releaseClassHandle($$)}}});attachFinalizer=function(handle){finalizationGroup.register(handle,handle.$$,handle.$$);return handle};detachFinalizer=function(handle){finalizationGroup.unregister(handle.$$)};return attachFinalizer(handle)}function ClassHandle_clone(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.preservePointerOnDelete){this.$$.count.value+=1;return this}else{var clone=attachFinalizer(Object.create(Object.getPrototypeOf(this),{$$:{value:shallowCopyInternalPointer(this.$$)}}));clone.$$.count.value+=1;clone.$$.deleteScheduled=false;return clone}}function ClassHandle_delete(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}detachFinalizer(this);releaseClassHandle(this.$$);if(!this.$$.preservePointerOnDelete){this.$$.smartPtr=undefined;this.$$.ptr=undefined}}function ClassHandle_isDeleted(){return!this.$$.ptr}var delayFunction=undefined;var deletionQueue=[];function flushPendingDeletes(){while(deletionQueue.length){var obj=deletionQueue.pop();obj.$$.deleteScheduled=false;obj["delete"]()}}function ClassHandle_deleteLater(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}deletionQueue.push(this);if(deletionQueue.length===1&&delayFunction){delayFunction(flushPendingDeletes)}this.$$.deleteScheduled=true;return this}function init_ClassHandle(){ClassHandle.prototype["isAliasOf"]=ClassHandle_isAliasOf;ClassHandle.prototype["clone"]=ClassHandle_clone;ClassHandle.prototype["delete"]=ClassHandle_delete;ClassHandle.prototype["isDeleted"]=ClassHandle_isDeleted;ClassHandle.prototype["deleteLater"]=ClassHandle_deleteLater}function ClassHandle(){}var registeredPointers={};function ensureOverloadTable(proto,methodName,humanName){if(undefined===proto[methodName].overloadTable){var prevFunc=proto[methodName];proto[methodName]=function(){if(!proto[methodName].overloadTable.hasOwnProperty(arguments.length)){throwBindingError("Function '"+humanName+"' called with an invalid number of arguments ("+arguments.length+") - expects one of ("+proto[methodName].overloadTable+")!")}return proto[methodName].overloadTable[arguments.length].apply(this,arguments)};proto[methodName].overloadTable=[];proto[methodName].overloadTable[prevFunc.argCount]=prevFunc}}function exposePublicSymbol(name,value,numArguments){if(Module.hasOwnProperty(name)){if(undefined===numArguments||undefined!==Module[name].overloadTable&&undefined!==Module[name].overloadTable[numArguments]){throwBindingError("Cannot register public name '"+name+"' twice")}ensureOverloadTable(Module,name,name);if(Module.hasOwnProperty(numArguments)){throwBindingError("Cannot register multiple overloads of a function with the same number of arguments ("+numArguments+")!")}Module[name].overloadTable[numArguments]=value}else{Module[name]=value;if(undefined!==numArguments){Module[name].numArguments=numArguments}}}function RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast){this.name=name;this.constructor=constructor;this.instancePrototype=instancePrototype;this.rawDestructor=rawDestructor;this.baseClass=baseClass;this.getActualType=getActualType;this.upcast=upcast;this.downcast=downcast;this.pureVirtualFunctions=[]}function upcastPointer(ptr,ptrClass,desiredClass){while(ptrClass!==desiredClass){if(!ptrClass.upcast){throwBindingError("Expected null or instance of "+desiredClass.name+", got an instance of "+ptrClass.name)}ptr=ptrClass.upcast(ptr);ptrClass=ptrClass.baseClass}return ptr}function constNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError("null is not a valid "+this.name)}return 0}if(!handle.$$){throwBindingError('Cannot pass "'+_embind_repr(handle)+'" as a '+this.name)}if(!handle.$$.ptr){throwBindingError("Cannot pass deleted object as a pointer of type "+this.name)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function genericPointerToWireType(destructors,handle){var ptr;if(handle===null){if(this.isReference){throwBindingError("null is not a valid "+this.name)}if(this.isSmartPointer){ptr=this.rawConstructor();if(destructors!==null){destructors.push(this.rawDestructor,ptr)}return ptr}else{return 0}}if(!handle.$$){throwBindingError('Cannot pass "'+_embind_repr(handle)+'" as a '+this.name)}if(!handle.$$.ptr){throwBindingError("Cannot pass deleted object as a pointer of type "+this.name)}if(!this.isConst&&handle.$$.ptrType.isConst){throwBindingError("Cannot convert argument of type "+(handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name)+" to parameter type "+this.name)}var handleClass=handle.$$.ptrType.registeredClass;ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);if(this.isSmartPointer){if(undefined===handle.$$.smartPtr){throwBindingError("Passing raw pointer to smart pointer is illegal")}switch(this.sharingPolicy){case 0:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{throwBindingError("Cannot convert argument of type "+(handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name)+" to parameter type "+this.name)}break;case 1:ptr=handle.$$.smartPtr;break;case 2:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{var clonedHandle=handle["clone"]();ptr=this.rawShare(ptr,__emval_register(function(){clonedHandle["delete"]()}));if(destructors!==null){destructors.push(this.rawDestructor,ptr)}}break;default:throwBindingError("Unsupporting sharing policy")}}return ptr}function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError("null is not a valid "+this.name)}return 0}if(!handle.$$){throwBindingError('Cannot pass "'+_embind_repr(handle)+'" as a '+this.name)}if(!handle.$$.ptr){throwBindingError("Cannot pass deleted object as a pointer of type "+this.name)}if(handle.$$.ptrType.isConst){throwBindingError("Cannot convert argument of type "+handle.$$.ptrType.name+" to parameter type "+this.name)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function RegisteredPointer_getPointee(ptr){if(this.rawGetPointee){ptr=this.rawGetPointee(ptr)}return ptr}function RegisteredPointer_destructor(ptr){if(this.rawDestructor){this.rawDestructor(ptr)}}function RegisteredPointer_deleteObject(handle){if(handle!==null){handle["delete"]()}}function downcastPointer(ptr,ptrClass,desiredClass){if(ptrClass===desiredClass){return ptr}if(undefined===desiredClass.baseClass){return null}var rv=downcastPointer(ptr,ptrClass,desiredClass.baseClass);if(rv===null){return null}return desiredClass.downcast(rv)}function getInheritedInstanceCount(){return Object.keys(registeredInstances).length}function getLiveInheritedInstances(){var rv=[];for(var k in registeredInstances){if(registeredInstances.hasOwnProperty(k)){rv.push(registeredInstances[k])}}return rv}function setDelayFunction(fn){delayFunction=fn;if(deletionQueue.length&&delayFunction){delayFunction(flushPendingDeletes)}}function init_embind(){Module["getInheritedInstanceCount"]=getInheritedInstanceCount;Module["getLiveInheritedInstances"]=getLiveInheritedInstances;Module["flushPendingDeletes"]=flushPendingDeletes;Module["setDelayFunction"]=setDelayFunction}var registeredInstances={};function getBasestPointer(class_,ptr){if(ptr===undefined){throwBindingError("ptr should not be undefined")}while(class_.baseClass){ptr=class_.upcast(ptr);class_=class_.baseClass}return ptr}function getInheritedInstance(class_,ptr){ptr=getBasestPointer(class_,ptr);return registeredInstances[ptr]}function makeClassHandle(prototype,record){if(!record.ptrType||!record.ptr){throwInternalError("makeClassHandle requires ptr and ptrType")}var hasSmartPtrType=!!record.smartPtrType;var hasSmartPtr=!!record.smartPtr;if(hasSmartPtrType!==hasSmartPtr){throwInternalError("Both smartPtrType and smartPtr must be specified")}record.count={value:1};return attachFinalizer(Object.create(prototype,{$$:{value:record}}))}function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPointee(ptr);if(!rawPointer){this.destructor(ptr);return null}var registeredInstance=getInheritedInstance(this.registeredClass,rawPointer);if(undefined!==registeredInstance){if(0===registeredInstance.$$.count.value){registeredInstance.$$.ptr=rawPointer;registeredInstance.$$.smartPtr=ptr;return registeredInstance["clone"]()}else{var rv=registeredInstance["clone"]();this.destructor(ptr);return rv}}function makeDefaultHandle(){if(this.isSmartPointer){return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:rawPointer,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this,ptr:ptr})}}var actualType=this.registeredClass.getActualType(rawPointer);var registeredPointerRecord=registeredPointers[actualType];if(!registeredPointerRecord){return makeDefaultHandle.call(this)}var toType;if(this.isConst){toType=registeredPointerRecord.constPointerType}else{toType=registeredPointerRecord.pointerType}var dp=downcastPointer(rawPointer,this.registeredClass,toType.registeredClass);if(dp===null){return makeDefaultHandle.call(this)}if(this.isSmartPointer){return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp})}}function init_RegisteredPointer(){RegisteredPointer.prototype.getPointee=RegisteredPointer_getPointee;RegisteredPointer.prototype.destructor=RegisteredPointer_destructor;RegisteredPointer.prototype["argPackAdvance"]=8;RegisteredPointer.prototype["readValueFromPointer"]=simpleReadValueFromPointer;RegisteredPointer.prototype["deleteObject"]=RegisteredPointer_deleteObject;RegisteredPointer.prototype["fromWireType"]=RegisteredPointer_fromWireType}function RegisteredPointer(name,registeredClass,isReference,isConst,isSmartPointer,pointeeType,sharingPolicy,rawGetPointee,rawConstructor,rawShare,rawDestructor){this.name=name;this.registeredClass=registeredClass;this.isReference=isReference;this.isConst=isConst;this.isSmartPointer=isSmartPointer;this.pointeeType=pointeeType;this.sharingPolicy=sharingPolicy;this.rawGetPointee=rawGetPointee;this.rawConstructor=rawConstructor;this.rawShare=rawShare;this.rawDestructor=rawDestructor;if(!isSmartPointer&®isteredClass.baseClass===undefined){if(isConst){this["toWireType"]=constNoSmartPtrRawPointerToWireType;this.destructorFunction=null}else{this["toWireType"]=nonConstNoSmartPtrRawPointerToWireType;this.destructorFunction=null}}else{this["toWireType"]=genericPointerToWireType}}function replacePublicSymbol(name,value,numArguments){if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistant public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}}function embind__requireFunction(signature,rawFunction){signature=readLatin1String(signature);function makeDynCaller(dynCall){var args=[];for(var i=1;i>2)+i])}return array}function __embind_register_class_constructor(rawClassType,argCount,rawArgTypesAddr,invokerSignature,invoker,rawConstructor){assert(argCount>0);var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);invoker=embind__requireFunction(invokerSignature,invoker);var args=[rawConstructor];var destructors=[];whenDependentTypesAreResolved([],[rawClassType],function(classType){classType=classType[0];var humanName="constructor "+classType.name;if(undefined===classType.registeredClass.constructor_body){classType.registeredClass.constructor_body=[]}if(undefined!==classType.registeredClass.constructor_body[argCount-1]){throw new BindingError("Cannot register multiple constructors with identical number of parameters ("+(argCount-1)+") for class '"+classType.name+"'! Overload resolution is currently only performed using the parameter count, not actual type info!")}classType.registeredClass.constructor_body[argCount-1]=function unboundTypeHandler(){throwUnboundTypeError("Cannot construct "+classType.name+" due to unbound types",rawArgTypes)};whenDependentTypesAreResolved([],rawArgTypes,function(argTypes){classType.registeredClass.constructor_body[argCount-1]=function constructor_body(){if(arguments.length!==argCount-1){throwBindingError(humanName+" called with "+arguments.length+" arguments, expected "+(argCount-1))}destructors.length=0;args.length=argCount;for(var i=1;i0?", ":"")+argsListWired}invokerFnBody+=(returns?"var rv = ":"")+"invoker(fn"+(argsListWired.length>0?", ":"")+argsListWired+");\n";if(needsDestructorStack){invokerFnBody+="runDestructors(destructors);\n"}else{for(var i=isClassMethodFunc?1:2;i4&&0===--emval_handle_array[handle].refcount){emval_handle_array[handle]=undefined;emval_free_list.push(handle)}}function count_emval_handles(){var count=0;for(var i=5;i>1])};case 2:return function(pointer){var heap=signed?HEAP32:HEAPU32;return this["fromWireType"](heap[pointer>>2])};default:throw new TypeError("Unknown integer type: "+name)}}function __embind_register_enum(rawType,name,size,isSigned){var shift=getShiftFromSize(size);name=readLatin1String(name);function ctor(){}ctor.values={};registerType(rawType,{name:name,constructor:ctor,"fromWireType":function(c){return this.constructor.values[c]},"toWireType":function(destructors,c){return c.value},"argPackAdvance":8,"readValueFromPointer":enumReadValueFromPointer(name,shift,isSigned),destructorFunction:null});exposePublicSymbol(name,ctor)}function requireRegisteredType(rawType,humanName){var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(humanName+" has unknown type "+getTypeName(rawType))}return impl}function __embind_register_enum_value(rawEnumType,name,enumValue){var enumType=requireRegisteredType(rawEnumType,"enum");name=readLatin1String(name);var Enum=enumType.constructor;var Value=Object.create(enumType.constructor.prototype,{value:{value:enumValue},constructor:{value:createNamedFunction(enumType.name+"_"+name,function(){})}});Enum.values[enumValue]=Value;Enum[name]=Value}function _embind_repr(v){if(v===null){return"null"}var t=typeof v;if(t==="object"||t==="array"||t==="function"){return v.toString()}else{return""+v}}function floatReadValueFromPointer(name,shift){switch(shift){case 2:return function(pointer){return this["fromWireType"](HEAPF32[pointer>>2])};case 3:return function(pointer){return this["fromWireType"](HEAPF64[pointer>>3])};default:throw new TypeError("Unknown float type: "+name)}}function __embind_register_float(rawType,name,size){var shift=getShiftFromSize(size);name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":function(value){return value},"toWireType":function(destructors,value){if(typeof value!=="number"&&typeof value!=="boolean"){throw new TypeError('Cannot convert "'+_embind_repr(value)+'" to '+this.name)}return value},"argPackAdvance":8,"readValueFromPointer":floatReadValueFromPointer(name,shift),destructorFunction:null})}function __embind_register_function(name,argCount,rawArgTypesAddr,signature,rawInvoker,fn){var argTypes=heap32VectorToArray(argCount,rawArgTypesAddr);name=readLatin1String(name);rawInvoker=embind__requireFunction(signature,rawInvoker);exposePublicSymbol(name,function(){throwUnboundTypeError("Cannot call "+name+" due to unbound types",argTypes)},argCount-1);whenDependentTypesAreResolved([],argTypes,function(argTypes){var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));replacePublicSymbol(name,craftInvokerFunction(name,invokerArgsArray,null,rawInvoker,fn),argCount-1);return[]})}function integerReadValueFromPointer(name,shift,signed){switch(shift){case 0:return signed?function readS8FromPointer(pointer){return HEAP8[pointer]}:function readU8FromPointer(pointer){return HEAPU8[pointer]};case 1:return signed?function readS16FromPointer(pointer){return HEAP16[pointer>>1]}:function readU16FromPointer(pointer){return HEAPU16[pointer>>1]};case 2:return signed?function readS32FromPointer(pointer){return HEAP32[pointer>>2]}:function readU32FromPointer(pointer){return HEAPU32[pointer>>2]};default:throw new TypeError("Unknown integer type: "+name)}}function __embind_register_integer(primitiveType,name,size,minRange,maxRange){name=readLatin1String(name);if(maxRange===-1){maxRange=4294967295}var shift=getShiftFromSize(size);var fromWireType=function(value){return value};if(minRange===0){var bitshift=32-8*size;fromWireType=function(value){return value<>>bitshift}}var isUnsignedType=name.indexOf("unsigned")!=-1;registerType(primitiveType,{name:name,"fromWireType":fromWireType,"toWireType":function(destructors,value){if(typeof value!=="number"&&typeof value!=="boolean"){throw new TypeError('Cannot convert "'+_embind_repr(value)+'" to '+this.name)}if(valuemaxRange){throw new TypeError('Passing a number "'+_embind_repr(value)+'" from JS side to C/C++ side to an argument of type "'+name+'", which is outside the valid range ['+minRange+", "+maxRange+"]!")}return isUnsignedType?value>>>0:value|0},"argPackAdvance":8,"readValueFromPointer":integerReadValueFromPointer(name,shift,minRange!==0),destructorFunction:null})}function __embind_register_memory_view(rawType,dataTypeIndex,name){var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){handle=handle>>2;var heap=HEAPU32;var size=heap[handle];var data=heap[handle+1];return new TA(buffer,data,size)}name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":decodeMemoryView,"argPackAdvance":8,"readValueFromPointer":decodeMemoryView},{ignoreDuplicateRegistrations:true})}function __embind_register_std_string(rawType,name){name=readLatin1String(name);var stdStringIsUTF8=name==="std::string";registerType(rawType,{name:name,"fromWireType":function(value){var length=HEAPU32[value>>2];var str;if(stdStringIsUTF8){var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i;if(HEAPU8[currentBytePtr]==0||i==length){var maxRead=currentBytePtr-decodeStartPtr;var stringSegment=UTF8ToString(decodeStartPtr,maxRead);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+1}}}else{var a=new Array(length);for(var i=0;i>2]=length;if(stdStringIsUTF8&&valueIsOfTypeString){stringToUTF8(value,ptr+4,length+1)}else{if(valueIsOfTypeString){for(var i=0;i255){_free(ptr);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}HEAPU8[ptr+4+i]=charCode}}else{for(var i=0;i>2];var HEAP=getHeap();var str;var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i*charSize;if(HEAP[currentBytePtr>>shift]==0||i==length){var maxReadBytes=currentBytePtr-decodeStartPtr;var stringSegment=decodeString(decodeStartPtr,maxReadBytes);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+charSize}}_free(value);return str},"toWireType":function(destructors,value){if(!(typeof value==="string")){throwBindingError("Cannot pass non-string to C++ string type "+name)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);HEAPU32[ptr>>2]=length>>shift;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},"argPackAdvance":8,"readValueFromPointer":simpleReadValueFromPointer,destructorFunction:function(ptr){_free(ptr)}})}function __embind_register_value_object(rawType,name,constructorSignature,rawConstructor,destructorSignature,rawDestructor){structRegistrations[rawType]={name:readLatin1String(name),rawConstructor:embind__requireFunction(constructorSignature,rawConstructor),rawDestructor:embind__requireFunction(destructorSignature,rawDestructor),fields:[]}}function __embind_register_value_object_field(structType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext){structRegistrations[structType].fields.push({fieldName:readLatin1String(fieldName),getterReturnType:getterReturnType,getter:embind__requireFunction(getterSignature,getter),getterContext:getterContext,setterArgumentType:setterArgumentType,setter:embind__requireFunction(setterSignature,setter),setterContext:setterContext})}function __embind_register_void(rawType,name){name=readLatin1String(name);registerType(rawType,{isVoid:true,name:name,"argPackAdvance":0,"fromWireType":function(){return undefined},"toWireType":function(destructors,o){return undefined}})}function requireHandle(handle){if(!handle){throwBindingError("Cannot use deleted val. handle = "+handle)}return emval_handle_array[handle].value}function __emval_as(handle,returnType,destructorsRef){handle=requireHandle(handle);returnType=requireRegisteredType(returnType,"emval::as");var destructors=[];var rd=__emval_register(destructors);HEAP32[destructorsRef>>2]=rd;return returnType["toWireType"](destructors,handle)}var emval_symbols={};function getStringOrSymbol(address){var symbol=emval_symbols[address];if(symbol===undefined){return readLatin1String(address)}else{return symbol}}var emval_methodCallers=[];function __emval_call_void_method(caller,handle,methodName,args){caller=emval_methodCallers[caller];handle=requireHandle(handle);methodName=getStringOrSymbol(methodName);caller(handle,methodName,null,args)}function emval_get_global(){if(typeof globalThis==="object"){return globalThis}return function(){return Function}()("return this")()}function __emval_get_global(name){if(name===0){return __emval_register(emval_get_global())}else{name=getStringOrSymbol(name);return __emval_register(emval_get_global()[name])}}function __emval_addMethodCaller(caller){var id=emval_methodCallers.length;emval_methodCallers.push(caller);return id}function __emval_lookupTypes(argCount,argTypes){var a=new Array(argCount);for(var i=0;i>2)+i],"parameter "+i)}return a}function __emval_get_method_caller(argCount,argTypes){var types=__emval_lookupTypes(argCount,argTypes);var retType=types[0];var signatureName=retType.name+"_$"+types.slice(1).map(function(t){return t.name}).join("_")+"$";var params=["retType"];var args=[retType];var argsList="";for(var i=0;i4){emval_handle_array[handle].refcount+=1}}function craftEmvalAllocator(argCount){var argsList="";for(var i=0;i>> 2) + "+i+'], "parameter '+i+'");\n'+"var arg"+i+" = argType"+i+".readValueFromPointer(args);\n"+"args += argType"+i+"['argPackAdvance'];\n"}functionBody+="var obj = new constructor("+argsList+");\n"+"return __emval_register(obj);\n"+"}\n";return new Function("requireRegisteredType","Module","__emval_register",functionBody)(requireRegisteredType,Module,__emval_register)}var emval_newers={};function __emval_new(handle,argCount,argTypes,args){handle=requireHandle(handle);var newer=emval_newers[argCount];if(!newer){newer=craftEmvalAllocator(argCount);emval_newers[argCount]=newer}return newer(handle,argTypes,args)}function __emval_new_cstring(v){return __emval_register(getStringOrSymbol(v))}function __emval_run_destructors(handle){var destructors=emval_handle_array[handle].value;runDestructors(destructors);__emval_decref(handle)}function _abort(){abort()}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num)}function _emscripten_get_heap_size(){return HEAPU8.length}function emscripten_realloc_buffer(size){try{wasmMemory.grow(size-buffer.byteLength+65535>>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();var PAGE_MULTIPLE=65536;var maxHeapSize=2147483648;if(requestedSize>maxHeapSize){return false}var minHeapSize=16777216;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(minHeapSize,requestedSize,overGrownHeapSize),PAGE_MULTIPLE));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}var PATH={splitPath:function(filename){var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:function(parts,allowAboveRoot){var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:function(path){var isAbsolute=path.charAt(0)==="/",trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(function(p){return!!p}),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:function(path){var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:function(path){if(path==="/")return"/";var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},extname:function(path){return PATH.splitPath(path)[3]},join:function(){var paths=Array.prototype.slice.call(arguments,0);return PATH.normalize(paths.join("/"))},join2:function(l,r){return PATH.normalize(l+"/"+r)}};var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0}else{buffer.push(curr)}},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},get64:function(low,high){return low}};function _fd_close(fd){return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}function _setTempRet0($i){setTempRet0($i|0)}InternalError=Module["InternalError"]=extendError(Error,"InternalError");embind_init_charCodes();BindingError=Module["BindingError"]=extendError(Error,"BindingError");init_ClassHandle();init_RegisteredPointer();init_embind();UnboundTypeError=Module["UnboundTypeError"]=extendError(Error,"UnboundTypeError");init_emval();var asmLibraryArg={"u":__embind_finalize_value_object,"J":__embind_register_bool,"y":__embind_register_class,"x":__embind_register_class_constructor,"d":__embind_register_class_function,"k":__embind_register_constant,"I":__embind_register_emval,"n":__embind_register_enum,"a":__embind_register_enum_value,"B":__embind_register_float,"i":__embind_register_function,"j":__embind_register_integer,"h":__embind_register_memory_view,"C":__embind_register_std_string,"w":__embind_register_std_wstring,"v":__embind_register_value_object,"c":__embind_register_value_object_field,"K":__embind_register_void,"m":__emval_as,"s":__emval_call_void_method,"b":__emval_decref,"z":__emval_get_global,"t":__emval_get_method_caller,"r":__emval_get_module_property,"e":__emval_get_property,"g":__emval_incref,"q":__emval_new,"f":__emval_new_cstring,"l":__emval_run_destructors,"p":_abort,"F":_emscripten_memcpy_big,"G":_emscripten_resize_heap,"H":_fd_close,"D":_fd_seek,"A":_fd_write,"memory":wasmMemory,"o":_roundf,"E":_setTempRet0,"table":wasmTable};var asm=createWasm();Module["asm"]=asm;var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return(___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["L"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return(_malloc=Module["_malloc"]=Module["asm"]["M"]).apply(null,arguments)};var _free=Module["_free"]=function(){return(_free=Module["_free"]=Module["asm"]["N"]).apply(null,arguments)};var ___getTypeName=Module["___getTypeName"]=function(){return(___getTypeName=Module["___getTypeName"]=Module["asm"]["O"]).apply(null,arguments)};var ___embind_register_native_and_builtin_types=Module["___embind_register_native_and_builtin_types"]=function(){return(___embind_register_native_and_builtin_types=Module["___embind_register_native_and_builtin_types"]=Module["asm"]["P"]).apply(null,arguments)};var dynCall_viii=Module["dynCall_viii"]=function(){return(dynCall_viii=Module["dynCall_viii"]=Module["asm"]["Q"]).apply(null,arguments)};var dynCall_vi=Module["dynCall_vi"]=function(){return(dynCall_vi=Module["dynCall_vi"]=Module["asm"]["R"]).apply(null,arguments)};var dynCall_v=Module["dynCall_v"]=function(){return(dynCall_v=Module["dynCall_v"]=Module["asm"]["S"]).apply(null,arguments)};var dynCall_i=Module["dynCall_i"]=function(){return(dynCall_i=Module["dynCall_i"]=Module["asm"]["T"]).apply(null,arguments)};var dynCall_iii=Module["dynCall_iii"]=function(){return(dynCall_iii=Module["dynCall_iii"]=Module["asm"]["U"]).apply(null,arguments)};var dynCall_ii=Module["dynCall_ii"]=function(){return(dynCall_ii=Module["dynCall_ii"]=Module["asm"]["V"]).apply(null,arguments)};var dynCall_vii=Module["dynCall_vii"]=function(){return(dynCall_vii=Module["dynCall_vii"]=Module["asm"]["W"]).apply(null,arguments)};var dynCall_iiii=Module["dynCall_iiii"]=function(){return(dynCall_iiii=Module["dynCall_iiii"]=Module["asm"]["X"]).apply(null,arguments)};var dynCall_iiiii=Module["dynCall_iiiii"]=function(){return(dynCall_iiiii=Module["dynCall_iiiii"]=Module["asm"]["Y"]).apply(null,arguments)};var dynCall_iiiiii=Module["dynCall_iiiiii"]=function(){return(dynCall_iiiiii=Module["dynCall_iiiiii"]=Module["asm"]["Z"]).apply(null,arguments)};var dynCall_iiiiiiii=Module["dynCall_iiiiiiii"]=function(){return(dynCall_iiiiiiii=Module["dynCall_iiiiiiii"]=Module["asm"]["_"]).apply(null,arguments)};var dynCall_iiiiiiiii=Module["dynCall_iiiiiiiii"]=function(){return(dynCall_iiiiiiiii=Module["dynCall_iiiiiiiii"]=Module["asm"]["$"]).apply(null,arguments)};var dynCall_viiii=Module["dynCall_viiii"]=function(){return(dynCall_viiii=Module["dynCall_viiii"]=Module["asm"]["aa"]).apply(null,arguments)};var dynCall_iiiiiii=Module["dynCall_iiiiiii"]=function(){return(dynCall_iiiiiii=Module["dynCall_iiiiiii"]=Module["asm"]["ba"]).apply(null,arguments)};var dynCall_iiiiiiiiiiiiiiiiiiii=Module["dynCall_iiiiiiiiiiiiiiiiiiii"]=function(){return(dynCall_iiiiiiiiiiiiiiiiiiii=Module["dynCall_iiiiiiiiiiiiiiiiiiii"]=Module["asm"]["ca"]).apply(null,arguments)};var dynCall_iiiiiiiiiiiiiiiiiiiii=Module["dynCall_iiiiiiiiiiiiiiiiiiiii"]=function(){return(dynCall_iiiiiiiiiiiiiiiiiiiii=Module["dynCall_iiiiiiiiiiiiiiiiiiiii"]=Module["asm"]["da"]).apply(null,arguments)};var dynCall_iiiiiiiiiiiiiiiiiii=Module["dynCall_iiiiiiiiiiiiiiiiiii"]=function(){return(dynCall_iiiiiiiiiiiiiiiiiii=Module["dynCall_iiiiiiiiiiiiiiiiiii"]=Module["asm"]["ea"]).apply(null,arguments)};var dynCall_viiiii=Module["dynCall_viiiii"]=function(){return(dynCall_viiiii=Module["dynCall_viiiii"]=Module["asm"]["fa"]).apply(null,arguments)};var dynCall_iiiiiiiiii=Module["dynCall_iiiiiiiiii"]=function(){return(dynCall_iiiiiiiiii=Module["dynCall_iiiiiiiiii"]=Module["asm"]["ga"]).apply(null,arguments)};var dynCall_iiiiiiiiiii=Module["dynCall_iiiiiiiiiii"]=function(){return(dynCall_iiiiiiiiiii=Module["dynCall_iiiiiiiiiii"]=Module["asm"]["ha"]).apply(null,arguments)};var dynCall_jiji=Module["dynCall_jiji"]=function(){return(dynCall_jiji=Module["dynCall_jiji"]=Module["asm"]["ia"]).apply(null,arguments)};var dynCall_viiiiii=Module["dynCall_viiiiii"]=function(){return(dynCall_viiiiii=Module["dynCall_viiiiii"]=Module["asm"]["ja"]).apply(null,arguments)};Module["asm"]=asm;var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}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();preMain();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()()}}noExitRuntime=true;run();
+var Module=moduleArg;var readyPromiseResolve,readyPromiseReject;var readyPromise=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject});var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof importScripts=="function";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";if(ENVIRONMENT_IS_NODE){}var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require("fs");var nodePath=require("path");scriptDirectory=__dirname+"/";readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);var ret=fs.readFileSync(filename);return ret};readAsync=(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);return new Promise((resolve,reject)=>{fs.readFile(filename,binary?undefined:"utf8",(err,data)=>{if(err)reject(err);else resolve(binary?data.buffer:data)})})};if(!Module["thisProgram"]&&process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else 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(_scriptName){scriptDirectory=_scriptName}if(scriptDirectory.startsWith("blob:")){scriptDirectory=""}else{scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}{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=>{if(isFileURI(url)){return new Promise((reject,resolve)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response)}reject(xhr.status)};xhr.onerror=reject;xhr.send(null)})}return fetch(url,{credentials:"same-origin"}).then(response=>{if(response.ok){return response.arrayBuffer()}return Promise.reject(new Error(response.status+" : "+response.url))})}}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.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 wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var wasmMemory;var ABORT=false;var EXITSTATUS;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b)}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++;Module["monitorRunDependencies"]?.(runDependencies)}function removeRunDependency(id){runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){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,";var isDataURI=filename=>filename.startsWith(dataURIPrefix);var isFileURI=filename=>filename.startsWith("file://");function findWasmBinary(){var f="basis_transcoder.wasm";if(!isDataURI(f)){return locateFile(f)}return f}var wasmBinaryFile;function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}function getBinaryPromise(binaryFile){if(!wasmBinary){return readAsync(binaryFile).then(response=>new Uint8Array(response),()=>getBinarySync(binaryFile))}return Promise.resolve().then(()=>getBinarySync(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>WebAssembly.instantiate(binary,imports)).then(receiver,reason=>{err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)})})}return instantiateArrayBuffer(binaryFile,imports,callback)}function getWasmImports(){return{a:wasmImports}}function createWasm(){var info=getWasmImports();function receiveInstance(instance,module){wasmExports=instance.exports;wasmMemory=wasmExports["L"];updateMemoryViews();wasmTable=wasmExports["P"];addOnInit(wasmExports["M"]);removeRunDependency("wasm-instantiate");return wasmExports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err(`Module.instantiateWasm callback failed with error: ${e}`);readyPromiseReject(e)}}if(!wasmBinaryFile)wasmBinaryFile=findWasmBinary();instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult).catch(readyPromiseReject);return{}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var noExitRuntime=Module["noExitRuntime"]||true;class ExceptionInfo{constructor(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24}set_type(type){HEAPU32[this.ptr+4>>2]=type}get_type(){return HEAPU32[this.ptr+4>>2]}set_destructor(destructor){HEAPU32[this.ptr+8>>2]=destructor}get_destructor(){return HEAPU32[this.ptr+8>>2]}set_caught(caught){caught=caught?1:0;HEAP8[this.ptr+12]=caught}get_caught(){return HEAP8[this.ptr+12]!=0}set_rethrown(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13]=rethrown}get_rethrown(){return HEAP8[this.ptr+13]!=0}init(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)}set_adjusted_ptr(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr}get_adjusted_ptr(){return HEAPU32[this.ptr+16>>2]}get_exception_ptr(){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}}var exceptionLast=0;var uncaughtExceptionCount=0;var ___cxa_throw=(ptr,type,destructor)=>{var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw exceptionLast};var __abort_js=()=>{abort("")};var structRegistrations={};var runDestructors=destructors=>{while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}};function readPointer(pointer){return this["fromWireType"](HEAPU32[pointer>>2])}var awaitingDependencies={};var registeredTypes={};var typeDependencies={};var InternalError;var throwInternalError=message=>{throw new InternalError(message)};var whenDependentTypesAreResolved=(myTypes,dependentTypes,getTypeConverters)=>{myTypes.forEach(function(type){typeDependencies[type]=dependentTypes});function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i{if(registeredTypes.hasOwnProperty(dt)){typeConverters[i]=registeredTypes[dt]}else{unregisteredTypes.push(dt);if(!awaitingDependencies.hasOwnProperty(dt)){awaitingDependencies[dt]=[]}awaitingDependencies[dt].push(()=>{typeConverters[i]=registeredTypes[dt];++registered;if(registered===unregisteredTypes.length){onComplete(typeConverters)}})}});if(0===unregisteredTypes.length){onComplete(typeConverters)}};var __embind_finalize_value_object=structType=>{var reg=structRegistrations[structType];delete structRegistrations[structType];var rawConstructor=reg.rawConstructor;var rawDestructor=reg.rawDestructor;var fieldRecords=reg.fields;var fieldTypes=fieldRecords.map(field=>field.getterReturnType).concat(fieldRecords.map(field=>field.setterArgumentType));whenDependentTypesAreResolved([structType],fieldTypes,fieldTypes=>{var fields={};fieldRecords.forEach((field,i)=>{var fieldName=field.fieldName;var getterReturnType=fieldTypes[i];var getter=field.getter;var getterContext=field.getterContext;var setterArgumentType=fieldTypes[i+fieldRecords.length];var setter=field.setter;var setterContext=field.setterContext;fields[fieldName]={read:ptr=>getterReturnType["fromWireType"](getter(getterContext,ptr)),write:(ptr,o)=>{var destructors=[];setter(setterContext,ptr,setterArgumentType["toWireType"](destructors,o));runDestructors(destructors)}}});return[{name:reg.name,fromWireType:ptr=>{var rv={};for(var i in fields){rv[i]=fields[i].read(ptr)}rawDestructor(ptr);return rv},toWireType:(destructors,o)=>{for(var fieldName in fields){if(!(fieldName in o)){throw new TypeError(`Missing field: "${fieldName}"`)}}var ptr=rawConstructor();for(fieldName in fields){fields[fieldName].write(ptr,o[fieldName])}if(destructors!==null){destructors.push(rawDestructor,ptr)}return ptr},argPackAdvance:GenericWireTypeSize,readValueFromPointer:readPointer,destructorFunction:rawDestructor}]})};var __embind_register_bigint=(primitiveType,name,size,minRange,maxRange)=>{};var embind_init_charCodes=()=>{var codes=new Array(256);for(var i=0;i<256;++i){codes[i]=String.fromCharCode(i)}embind_charCodes=codes};var embind_charCodes;var readLatin1String=ptr=>{var ret="";var c=ptr;while(HEAPU8[c]){ret+=embind_charCodes[HEAPU8[c++]]}return ret};var BindingError;var throwBindingError=message=>{throw new BindingError(message)};function sharedRegisterType(rawType,registeredInstance,options={}){var name=registeredInstance.name;if(!rawType){throwBindingError(`type "${name}" must have a positive integer typeid pointer`)}if(registeredTypes.hasOwnProperty(rawType)){if(options.ignoreDuplicateRegistrations){return}else{throwBindingError(`Cannot register type '${name}' twice`)}}registeredTypes[rawType]=registeredInstance;delete typeDependencies[rawType];if(awaitingDependencies.hasOwnProperty(rawType)){var callbacks=awaitingDependencies[rawType];delete awaitingDependencies[rawType];callbacks.forEach(cb=>cb())}}function registerType(rawType,registeredInstance,options={}){if(!("argPackAdvance"in registeredInstance)){throw new TypeError("registerType registeredInstance requires argPackAdvance")}return sharedRegisterType(rawType,registeredInstance,options)}var GenericWireTypeSize=8;var __embind_register_bool=(rawType,name,trueValue,falseValue)=>{name=readLatin1String(name);registerType(rawType,{name:name,fromWireType:function(wt){return!!wt},toWireType:function(destructors,o){return o?trueValue:falseValue},argPackAdvance:GenericWireTypeSize,readValueFromPointer:function(pointer){return this["fromWireType"](HEAPU8[pointer])},destructorFunction:null})};var shallowCopyInternalPointer=o=>({count:o.count,deleteScheduled:o.deleteScheduled,preservePointerOnDelete:o.preservePointerOnDelete,ptr:o.ptr,ptrType:o.ptrType,smartPtr:o.smartPtr,smartPtrType:o.smartPtrType});var throwInstanceAlreadyDeleted=obj=>{function getInstanceTypeName(handle){return handle.$$.ptrType.registeredClass.name}throwBindingError(getInstanceTypeName(obj)+" instance already deleted")};var finalizationRegistry=false;var detachFinalizer=handle=>{};var runDestructor=$$=>{if($$.smartPtr){$$.smartPtrType.rawDestructor($$.smartPtr)}else{$$.ptrType.registeredClass.rawDestructor($$.ptr)}};var releaseClassHandle=$$=>{$$.count.value-=1;var toDelete=0===$$.count.value;if(toDelete){runDestructor($$)}};var downcastPointer=(ptr,ptrClass,desiredClass)=>{if(ptrClass===desiredClass){return ptr}if(undefined===desiredClass.baseClass){return null}var rv=downcastPointer(ptr,ptrClass,desiredClass.baseClass);if(rv===null){return null}return desiredClass.downcast(rv)};var registeredPointers={};var getInheritedInstanceCount=()=>Object.keys(registeredInstances).length;var getLiveInheritedInstances=()=>{var rv=[];for(var k in registeredInstances){if(registeredInstances.hasOwnProperty(k)){rv.push(registeredInstances[k])}}return rv};var deletionQueue=[];var flushPendingDeletes=()=>{while(deletionQueue.length){var obj=deletionQueue.pop();obj.$$.deleteScheduled=false;obj["delete"]()}};var delayFunction;var setDelayFunction=fn=>{delayFunction=fn;if(deletionQueue.length&&delayFunction){delayFunction(flushPendingDeletes)}};var init_embind=()=>{Module["getInheritedInstanceCount"]=getInheritedInstanceCount;Module["getLiveInheritedInstances"]=getLiveInheritedInstances;Module["flushPendingDeletes"]=flushPendingDeletes;Module["setDelayFunction"]=setDelayFunction};var registeredInstances={};var getBasestPointer=(class_,ptr)=>{if(ptr===undefined){throwBindingError("ptr should not be undefined")}while(class_.baseClass){ptr=class_.upcast(ptr);class_=class_.baseClass}return ptr};var getInheritedInstance=(class_,ptr)=>{ptr=getBasestPointer(class_,ptr);return registeredInstances[ptr]};var makeClassHandle=(prototype,record)=>{if(!record.ptrType||!record.ptr){throwInternalError("makeClassHandle requires ptr and ptrType")}var hasSmartPtrType=!!record.smartPtrType;var hasSmartPtr=!!record.smartPtr;if(hasSmartPtrType!==hasSmartPtr){throwInternalError("Both smartPtrType and smartPtr must be specified")}record.count={value:1};return attachFinalizer(Object.create(prototype,{$$:{value:record,writable:true}}))};function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPointee(ptr);if(!rawPointer){this.destructor(ptr);return null}var registeredInstance=getInheritedInstance(this.registeredClass,rawPointer);if(undefined!==registeredInstance){if(0===registeredInstance.$$.count.value){registeredInstance.$$.ptr=rawPointer;registeredInstance.$$.smartPtr=ptr;return registeredInstance["clone"]()}else{var rv=registeredInstance["clone"]();this.destructor(ptr);return rv}}function makeDefaultHandle(){if(this.isSmartPointer){return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:rawPointer,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this,ptr:ptr})}}var actualType=this.registeredClass.getActualType(rawPointer);var registeredPointerRecord=registeredPointers[actualType];if(!registeredPointerRecord){return makeDefaultHandle.call(this)}var toType;if(this.isConst){toType=registeredPointerRecord.constPointerType}else{toType=registeredPointerRecord.pointerType}var dp=downcastPointer(rawPointer,this.registeredClass,toType.registeredClass);if(dp===null){return makeDefaultHandle.call(this)}if(this.isSmartPointer){return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp})}}var attachFinalizer=handle=>{if("undefined"===typeof FinalizationRegistry){attachFinalizer=handle=>handle;return handle}finalizationRegistry=new FinalizationRegistry(info=>{releaseClassHandle(info.$$)});attachFinalizer=handle=>{var $$=handle.$$;var hasSmartPtr=!!$$.smartPtr;if(hasSmartPtr){var info={$$:$$};finalizationRegistry.register(handle,info,handle)}return handle};detachFinalizer=handle=>finalizationRegistry.unregister(handle);return attachFinalizer(handle)};var init_ClassHandle=()=>{Object.assign(ClassHandle.prototype,{isAliasOf(other){if(!(this instanceof ClassHandle)){return false}if(!(other instanceof ClassHandle)){return false}var leftClass=this.$$.ptrType.registeredClass;var left=this.$$.ptr;other.$$=other.$$;var rightClass=other.$$.ptrType.registeredClass;var right=other.$$.ptr;while(leftClass.baseClass){left=leftClass.upcast(left);leftClass=leftClass.baseClass}while(rightClass.baseClass){right=rightClass.upcast(right);rightClass=rightClass.baseClass}return leftClass===rightClass&&left===right},clone(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.preservePointerOnDelete){this.$$.count.value+=1;return this}else{var clone=attachFinalizer(Object.create(Object.getPrototypeOf(this),{$$:{value:shallowCopyInternalPointer(this.$$)}}));clone.$$.count.value+=1;clone.$$.deleteScheduled=false;return clone}},delete(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}detachFinalizer(this);releaseClassHandle(this.$$);if(!this.$$.preservePointerOnDelete){this.$$.smartPtr=undefined;this.$$.ptr=undefined}},isDeleted(){return!this.$$.ptr},deleteLater(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}deletionQueue.push(this);if(deletionQueue.length===1&&delayFunction){delayFunction(flushPendingDeletes)}this.$$.deleteScheduled=true;return this}})};function ClassHandle(){}var createNamedFunction=(name,body)=>Object.defineProperty(body,"name",{value:name});var ensureOverloadTable=(proto,methodName,humanName)=>{if(undefined===proto[methodName].overloadTable){var prevFunc=proto[methodName];proto[methodName]=function(...args){if(!proto[methodName].overloadTable.hasOwnProperty(args.length)){throwBindingError(`Function '${humanName}' called with an invalid number of arguments (${args.length}) - expects one of (${proto[methodName].overloadTable})!`)}return proto[methodName].overloadTable[args.length].apply(this,args)};proto[methodName].overloadTable=[];proto[methodName].overloadTable[prevFunc.argCount]=prevFunc}};var exposePublicSymbol=(name,value,numArguments)=>{if(Module.hasOwnProperty(name)){if(undefined===numArguments||undefined!==Module[name].overloadTable&&undefined!==Module[name].overloadTable[numArguments]){throwBindingError(`Cannot register public name '${name}' twice`)}ensureOverloadTable(Module,name,name);if(Module.hasOwnProperty(numArguments)){throwBindingError(`Cannot register multiple overloads of a function with the same number of arguments (${numArguments})!`)}Module[name].overloadTable[numArguments]=value}else{Module[name]=value;if(undefined!==numArguments){Module[name].numArguments=numArguments}}};var char_0=48;var char_9=57;var makeLegalFunctionName=name=>{if(undefined===name){return"_unknown"}name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return`_${name}`}return name};function RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast){this.name=name;this.constructor=constructor;this.instancePrototype=instancePrototype;this.rawDestructor=rawDestructor;this.baseClass=baseClass;this.getActualType=getActualType;this.upcast=upcast;this.downcast=downcast;this.pureVirtualFunctions=[]}var upcastPointer=(ptr,ptrClass,desiredClass)=>{while(ptrClass!==desiredClass){if(!ptrClass.upcast){throwBindingError(`Expected null or instance of ${desiredClass.name}, got an instance of ${ptrClass.name}`)}ptr=ptrClass.upcast(ptr);ptrClass=ptrClass.baseClass}return ptr};function constNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function genericPointerToWireType(destructors,handle){var ptr;if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}if(this.isSmartPointer){ptr=this.rawConstructor();if(destructors!==null){destructors.push(this.rawDestructor,ptr)}return ptr}else{return 0}}if(!handle||!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(!this.isConst&&handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);if(this.isSmartPointer){if(undefined===handle.$$.smartPtr){throwBindingError("Passing raw pointer to smart pointer is illegal")}switch(this.sharingPolicy){case 0:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}break;case 1:ptr=handle.$$.smartPtr;break;case 2:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{var clonedHandle=handle["clone"]();ptr=this.rawShare(ptr,Emval.toHandle(()=>clonedHandle["delete"]()));if(destructors!==null){destructors.push(this.rawDestructor,ptr)}}break;default:throwBindingError("Unsupporting sharing policy")}}return ptr}function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}var init_RegisteredPointer=()=>{Object.assign(RegisteredPointer.prototype,{getPointee(ptr){if(this.rawGetPointee){ptr=this.rawGetPointee(ptr)}return ptr},destructor(ptr){this.rawDestructor?.(ptr)},argPackAdvance:GenericWireTypeSize,readValueFromPointer:readPointer,fromWireType:RegisteredPointer_fromWireType})};function RegisteredPointer(name,registeredClass,isReference,isConst,isSmartPointer,pointeeType,sharingPolicy,rawGetPointee,rawConstructor,rawShare,rawDestructor){this.name=name;this.registeredClass=registeredClass;this.isReference=isReference;this.isConst=isConst;this.isSmartPointer=isSmartPointer;this.pointeeType=pointeeType;this.sharingPolicy=sharingPolicy;this.rawGetPointee=rawGetPointee;this.rawConstructor=rawConstructor;this.rawShare=rawShare;this.rawDestructor=rawDestructor;if(!isSmartPointer&®isteredClass.baseClass===undefined){if(isConst){this["toWireType"]=constNoSmartPtrRawPointerToWireType;this.destructorFunction=null}else{this["toWireType"]=nonConstNoSmartPtrRawPointerToWireType;this.destructorFunction=null}}else{this["toWireType"]=genericPointerToWireType}}var replacePublicSymbol=(name,value,numArguments)=>{if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistent public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}};var dynCallLegacy=(sig,ptr,args)=>{sig=sig.replace(/p/g,"i");var f=Module["dynCall_"+sig];return f(ptr,...args)};var wasmTableMirror=[];var wasmTable;var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){if(funcPtr>=wasmTableMirror.length)wasmTableMirror.length=funcPtr+1;wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func};var dynCall=(sig,ptr,args=[])=>{if(sig.includes("j")){return dynCallLegacy(sig,ptr,args)}var rtn=getWasmTableEntry(ptr)(...args);return rtn};var getDynCaller=(sig,ptr)=>(...args)=>dynCall(sig,ptr,args);var embind__requireFunction=(signature,rawFunction)=>{signature=readLatin1String(signature);function makeDynCaller(){if(signature.includes("j")){return getDynCaller(signature,rawFunction)}return getWasmTableEntry(rawFunction)}var fp=makeDynCaller();if(typeof fp!="function"){throwBindingError(`unknown function pointer with signature ${signature}: ${rawFunction}`)}return fp};var extendError=(baseErrorType,errorName)=>{var errorClass=createNamedFunction(errorName,function(message){this.name=errorName;this.message=message;var stack=new Error(message).stack;if(stack!==undefined){this.stack=this.toString()+"\n"+stack.replace(/^Error(:[^\n]*)?\n/,"")}});errorClass.prototype=Object.create(baseErrorType.prototype);errorClass.prototype.constructor=errorClass;errorClass.prototype.toString=function(){if(this.message===undefined){return this.name}else{return`${this.name}: ${this.message}`}};return errorClass};var UnboundTypeError;var getTypeName=type=>{var ptr=___getTypeName(type);var rv=readLatin1String(ptr);_free(ptr);return rv};var throwUnboundTypeError=(message,types)=>{var unboundTypes=[];var seen={};function visit(type){if(seen[type]){return}if(registeredTypes[type]){return}if(typeDependencies[type]){typeDependencies[type].forEach(visit);return}unboundTypes.push(type);seen[type]=true}types.forEach(visit);throw new UnboundTypeError(`${message}: `+unboundTypes.map(getTypeName).join([", "]))};var __embind_register_class=(rawType,rawPointerType,rawConstPointerType,baseClassRawType,getActualTypeSignature,getActualType,upcastSignature,upcast,downcastSignature,downcast,name,destructorSignature,rawDestructor)=>{name=readLatin1String(name);getActualType=embind__requireFunction(getActualTypeSignature,getActualType);upcast&&=embind__requireFunction(upcastSignature,upcast);downcast&&=embind__requireFunction(downcastSignature,downcast);rawDestructor=embind__requireFunction(destructorSignature,rawDestructor);var legalFunctionName=makeLegalFunctionName(name);exposePublicSymbol(legalFunctionName,function(){throwUnboundTypeError(`Cannot construct ${name} due to unbound types`,[baseClassRawType])});whenDependentTypesAreResolved([rawType,rawPointerType,rawConstPointerType],baseClassRawType?[baseClassRawType]:[],base=>{base=base[0];var baseClass;var basePrototype;if(baseClassRawType){baseClass=base.registeredClass;basePrototype=baseClass.instancePrototype}else{basePrototype=ClassHandle.prototype}var constructor=createNamedFunction(name,function(...args){if(Object.getPrototypeOf(this)!==instancePrototype){throw new BindingError("Use 'new' to construct "+name)}if(undefined===registeredClass.constructor_body){throw new BindingError(name+" has no accessible constructor")}var body=registeredClass.constructor_body[args.length];if(undefined===body){throw new BindingError(`Tried to invoke ctor of ${name} with invalid number of parameters (${args.length}) - expected (${Object.keys(registeredClass.constructor_body).toString()}) parameters instead!`)}return body.apply(this,args)});var instancePrototype=Object.create(basePrototype,{constructor:{value:constructor}});constructor.prototype=instancePrototype;var registeredClass=new RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast);if(registeredClass.baseClass){registeredClass.baseClass.__derivedClasses??=[];registeredClass.baseClass.__derivedClasses.push(registeredClass)}var referenceConverter=new RegisteredPointer(name,registeredClass,true,false,false);var pointerConverter=new RegisteredPointer(name+"*",registeredClass,false,false,false);var constPointerConverter=new RegisteredPointer(name+" const*",registeredClass,false,true,false);registeredPointers[rawType]={pointerType:pointerConverter,constPointerType:constPointerConverter};replacePublicSymbol(legalFunctionName,constructor);return[referenceConverter,pointerConverter,constPointerConverter]})};var heap32VectorToArray=(count,firstElement)=>{var array=[];for(var i=0;i>2])}return array};function usesDestructorStack(argTypes){for(var i=1;i0?", ":"")+argsListWired}invokerFnBody+=(returns||isAsync?"var rv = ":"")+"invoker(fn"+(argsListWired.length>0?", ":"")+argsListWired+");\n";if(needsDestructorStack){invokerFnBody+="runDestructors(destructors);\n"}else{for(var i=isClassMethodFunc?1:2;i{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);invoker=embind__requireFunction(invokerSignature,invoker);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`constructor ${classType.name}`;if(undefined===classType.registeredClass.constructor_body){classType.registeredClass.constructor_body=[]}if(undefined!==classType.registeredClass.constructor_body[argCount-1]){throw new BindingError(`Cannot register multiple constructors with identical number of parameters (${argCount-1}) for class '${classType.name}'! Overload resolution is currently only performed using the parameter count, not actual type info!`)}classType.registeredClass.constructor_body[argCount-1]=()=>{throwUnboundTypeError(`Cannot construct ${classType.name} due to unbound types`,rawArgTypes)};whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{argTypes.splice(1,0,null);classType.registeredClass.constructor_body[argCount-1]=craftInvokerFunction(humanName,argTypes,null,invoker,rawConstructor);return[]});return[]})};var getFunctionName=signature=>{signature=signature.trim();const argsIndex=signature.indexOf("(");if(argsIndex!==-1){return signature.substr(0,argsIndex)}else{return signature}};var __embind_register_class_function=(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,context,isPureVirtual,isAsync)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=readLatin1String(methodName);methodName=getFunctionName(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`${classType.name}.${methodName}`;if(methodName.startsWith("@@")){methodName=Symbol[methodName.substring(2)]}if(isPureVirtual){classType.registeredClass.pureVirtualFunctions.push(methodName)}function unboundTypesHandler(){throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`,rawArgTypes)}var proto=classType.registeredClass.instancePrototype;var method=proto[methodName];if(undefined===method||undefined===method.overloadTable&&method.className!==classType.name&&method.argCount===argCount-2){unboundTypesHandler.argCount=argCount-2;unboundTypesHandler.className=classType.name;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-2]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{var memberFunction=craftInvokerFunction(humanName,argTypes,classType,rawInvoker,context,isAsync);if(undefined===proto[methodName].overloadTable){memberFunction.argCount=argCount-2;proto[methodName]=memberFunction}else{proto[methodName].overloadTable[argCount-2]=memberFunction}return[]});return[]})};var __embind_register_constant=(name,type,value)=>{name=readLatin1String(name);whenDependentTypesAreResolved([],[type],type=>{type=type[0];Module[name]=type["fromWireType"](value);return[]})};var emval_freelist=[];var emval_handles=[];var __emval_decref=handle=>{if(handle>9&&0===--emval_handles[handle+1]){emval_handles[handle]=undefined;emval_freelist.push(handle)}};var count_emval_handles=()=>emval_handles.length/2-5-emval_freelist.length;var init_emval=()=>{emval_handles.push(0,1,undefined,1,null,1,true,1,false,1);Module["count_emval_handles"]=count_emval_handles};var Emval={toValue:handle=>{if(!handle){throwBindingError("Cannot use deleted val. handle = "+handle)}return emval_handles[handle]},toHandle:value=>{switch(value){case undefined:return 2;case null:return 4;case true:return 6;case false:return 8;default:{const handle=emval_freelist.pop()||emval_handles.length;emval_handles[handle]=value;emval_handles[handle+1]=1;return handle}}}};var EmValType={name:"emscripten::val",fromWireType:handle=>{var rv=Emval.toValue(handle);__emval_decref(handle);return rv},toWireType:(destructors,value)=>Emval.toHandle(value),argPackAdvance:GenericWireTypeSize,readValueFromPointer:readPointer,destructorFunction:null};var __embind_register_emval=rawType=>registerType(rawType,EmValType);var enumReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?function(pointer){return this["fromWireType"](HEAP8[pointer])}:function(pointer){return this["fromWireType"](HEAPU8[pointer])};case 2:return signed?function(pointer){return this["fromWireType"](HEAP16[pointer>>1])}:function(pointer){return this["fromWireType"](HEAPU16[pointer>>1])};case 4:return signed?function(pointer){return this["fromWireType"](HEAP32[pointer>>2])}:function(pointer){return this["fromWireType"](HEAPU32[pointer>>2])};default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};var __embind_register_enum=(rawType,name,size,isSigned)=>{name=readLatin1String(name);function ctor(){}ctor.values={};registerType(rawType,{name:name,constructor:ctor,fromWireType:function(c){return this.constructor.values[c]},toWireType:(destructors,c)=>c.value,argPackAdvance:GenericWireTypeSize,readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,ctor)};var requireRegisteredType=(rawType,humanName)=>{var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(`${humanName} has unknown type ${getTypeName(rawType)}`)}return impl};var __embind_register_enum_value=(rawEnumType,name,enumValue)=>{var enumType=requireRegisteredType(rawEnumType,"enum");name=readLatin1String(name);var Enum=enumType.constructor;var Value=Object.create(enumType.constructor.prototype,{value:{value:enumValue},constructor:{value:createNamedFunction(`${enumType.name}_${name}`,function(){})}});Enum.values[enumValue]=Value;Enum[name]=Value};var embindRepr=v=>{if(v===null){return"null"}var t=typeof v;if(t==="object"||t==="array"||t==="function"){return v.toString()}else{return""+v}};var floatReadValueFromPointer=(name,width)=>{switch(width){case 4:return function(pointer){return this["fromWireType"](HEAPF32[pointer>>2])};case 8:return function(pointer){return this["fromWireType"](HEAPF64[pointer>>3])};default:throw new TypeError(`invalid float width (${width}): ${name}`)}};var __embind_register_float=(rawType,name,size)=>{name=readLatin1String(name);registerType(rawType,{name:name,fromWireType:value=>value,toWireType:(destructors,value)=>value,argPackAdvance:GenericWireTypeSize,readValueFromPointer:floatReadValueFromPointer(name,size),destructorFunction:null})};var __embind_register_function=(name,argCount,rawArgTypesAddr,signature,rawInvoker,fn,isAsync)=>{var argTypes=heap32VectorToArray(argCount,rawArgTypesAddr);name=readLatin1String(name);name=getFunctionName(name);rawInvoker=embind__requireFunction(signature,rawInvoker);exposePublicSymbol(name,function(){throwUnboundTypeError(`Cannot call ${name} due to unbound types`,argTypes)},argCount-1);whenDependentTypesAreResolved([],argTypes,argTypes=>{var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));replacePublicSymbol(name,craftInvokerFunction(name,invokerArgsArray,null,rawInvoker,fn,isAsync),argCount-1);return[]})};var integerReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?pointer=>HEAP8[pointer]:pointer=>HEAPU8[pointer];case 2:return signed?pointer=>HEAP16[pointer>>1]:pointer=>HEAPU16[pointer>>1];case 4:return signed?pointer=>HEAP32[pointer>>2]:pointer=>HEAPU32[pointer>>2];default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};var __embind_register_integer=(primitiveType,name,size,minRange,maxRange)=>{name=readLatin1String(name);if(maxRange===-1){maxRange=4294967295}var fromWireType=value=>value;if(minRange===0){var bitshift=32-8*size;fromWireType=value=>value<>>bitshift}var isUnsignedType=name.includes("unsigned");var checkAssertions=(value,toTypeName)=>{};var toWireType;if(isUnsignedType){toWireType=function(destructors,value){checkAssertions(value,this.name);return value>>>0}}else{toWireType=function(destructors,value){checkAssertions(value,this.name);return value}}registerType(primitiveType,{name:name,fromWireType:fromWireType,toWireType:toWireType,argPackAdvance:GenericWireTypeSize,readValueFromPointer:integerReadValueFromPointer(name,size,minRange!==0),destructorFunction:null})};var __embind_register_memory_view=(rawType,dataTypeIndex,name)=>{var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){var size=HEAPU32[handle>>2];var data=HEAPU32[handle+4>>2];return new TA(HEAP8.buffer,data,size)}name=readLatin1String(name);registerType(rawType,{name:name,fromWireType:decodeMemoryView,argPackAdvance:GenericWireTypeSize,readValueFromPointer:decodeMemoryView},{ignoreDuplicateRegistrations:true})};var 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};var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);var lengthBytesUTF8=str=>{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder:undefined;var UTF8ArrayToString=(heapOrArray,idx,maxBytesToRead)=>{var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var UTF8ToString=(ptr,maxBytesToRead)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):"";var __embind_register_std_string=(rawType,name)=>{name=readLatin1String(name);var stdStringIsUTF8=name==="std::string";registerType(rawType,{name:name,fromWireType(value){var length=HEAPU32[value>>2];var payload=value+4;var str;if(stdStringIsUTF8){var decodeStartPtr=payload;for(var i=0;i<=length;++i){var currentBytePtr=payload+i;if(i==length||HEAPU8[currentBytePtr]==0){var maxRead=currentBytePtr-decodeStartPtr;var stringSegment=UTF8ToString(decodeStartPtr,maxRead);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+1}}}else{var a=new Array(length);for(var i=0;i>2]=length;if(stdStringIsUTF8&&valueIsOfTypeString){stringToUTF8(value,ptr,length+1)}else{if(valueIsOfTypeString){for(var i=0;i255){_free(ptr);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}HEAPU8[ptr+i]=charCode}}else{for(var i=0;i{var endPtr=ptr;var idx=endPtr>>1;var maxIdx=idx+maxBytesToRead/2;while(!(idx>=maxIdx)&&HEAPU16[idx])++idx;endPtr=idx<<1;if(endPtr-ptr>32&&UTF16Decoder)return UTF16Decoder.decode(HEAPU8.subarray(ptr,endPtr));var str="";for(var i=0;!(i>=maxBytesToRead/2);++i){var codeUnit=HEAP16[ptr+i*2>>1];if(codeUnit==0)break;str+=String.fromCharCode(codeUnit)}return str};var stringToUTF16=(str,outPtr,maxBytesToWrite)=>{maxBytesToWrite??=2147483647;if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr};var lengthBytesUTF16=str=>str.length*2;var UTF32ToString=(ptr,maxBytesToRead)=>{var i=0;var str="";while(!(i>=maxBytesToRead/4)){var utf32=HEAP32[ptr+i*4>>2];if(utf32==0)break;++i;if(utf32>=65536){var ch=utf32-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}else{str+=String.fromCharCode(utf32)}}return str};var stringToUTF32=(str,outPtr,maxBytesToWrite)=>{maxBytesToWrite??=2147483647;if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i=55296&&codeUnit<=57343){var trailSurrogate=str.charCodeAt(++i);codeUnit=65536+((codeUnit&1023)<<10)|trailSurrogate&1023}HEAP32[outPtr>>2]=codeUnit;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr};var lengthBytesUTF32=str=>{var len=0;for(var i=0;i=55296&&codeUnit<=57343)++i;len+=4}return len};var __embind_register_std_wstring=(rawType,charSize,name)=>{name=readLatin1String(name);var decodeString,encodeString,readCharAt,lengthBytesUTF;if(charSize===2){decodeString=UTF16ToString;encodeString=stringToUTF16;lengthBytesUTF=lengthBytesUTF16;readCharAt=pointer=>HEAPU16[pointer>>1]}else if(charSize===4){decodeString=UTF32ToString;encodeString=stringToUTF32;lengthBytesUTF=lengthBytesUTF32;readCharAt=pointer=>HEAPU32[pointer>>2]}registerType(rawType,{name:name,fromWireType:value=>{var length=HEAPU32[value>>2];var str;var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i*charSize;if(i==length||readCharAt(currentBytePtr)==0){var maxReadBytes=currentBytePtr-decodeStartPtr;var stringSegment=decodeString(decodeStartPtr,maxReadBytes);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+charSize}}_free(value);return str},toWireType:(destructors,value)=>{if(!(typeof value=="string")){throwBindingError(`Cannot pass non-string to C++ string type ${name}`)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);HEAPU32[ptr>>2]=length/charSize;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},argPackAdvance:GenericWireTypeSize,readValueFromPointer:readPointer,destructorFunction(ptr){_free(ptr)}})};var __embind_register_value_object=(rawType,name,constructorSignature,rawConstructor,destructorSignature,rawDestructor)=>{structRegistrations[rawType]={name:readLatin1String(name),rawConstructor:embind__requireFunction(constructorSignature,rawConstructor),rawDestructor:embind__requireFunction(destructorSignature,rawDestructor),fields:[]}};var __embind_register_value_object_field=(structType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext)=>{structRegistrations[structType].fields.push({fieldName:readLatin1String(fieldName),getterReturnType:getterReturnType,getter:embind__requireFunction(getterSignature,getter),getterContext:getterContext,setterArgumentType:setterArgumentType,setter:embind__requireFunction(setterSignature,setter),setterContext:setterContext})};var __embind_register_void=(rawType,name)=>{name=readLatin1String(name);registerType(rawType,{isVoid:true,name:name,argPackAdvance:0,fromWireType:()=>undefined,toWireType:(destructors,o)=>undefined})};var __emscripten_memcpy_js=(dest,src,num)=>HEAPU8.copyWithin(dest,src,src+num);var emval_returnValue=(returnType,destructorsRef,handle)=>{var destructors=[];var result=returnType["toWireType"](destructors,handle);if(destructors.length){HEAPU32[destructorsRef>>2]=Emval.toHandle(destructors)}return result};var __emval_as=(handle,returnType,destructorsRef)=>{handle=Emval.toValue(handle);returnType=requireRegisteredType(returnType,"emval::as");return emval_returnValue(returnType,destructorsRef,handle)};var emval_methodCallers=[];var __emval_call=(caller,handle,destructorsRef,args)=>{caller=emval_methodCallers[caller];handle=Emval.toValue(handle);return caller(null,handle,destructorsRef,args)};var emval_symbols={};var getStringOrSymbol=address=>{var symbol=emval_symbols[address];if(symbol===undefined){return readLatin1String(address)}return symbol};var __emval_call_method=(caller,objHandle,methodName,destructorsRef,args)=>{caller=emval_methodCallers[caller];objHandle=Emval.toValue(objHandle);methodName=getStringOrSymbol(methodName);return caller(objHandle,objHandle[methodName],destructorsRef,args)};var emval_get_global=()=>{if(typeof globalThis=="object"){return globalThis}return function(){return Function}()("return this")()};var __emval_get_global=name=>{if(name===0){return Emval.toHandle(emval_get_global())}else{name=getStringOrSymbol(name);return Emval.toHandle(emval_get_global()[name])}};var emval_addMethodCaller=caller=>{var id=emval_methodCallers.length;emval_methodCallers.push(caller);return id};var emval_lookupTypes=(argCount,argTypes)=>{var a=new Array(argCount);for(var i=0;i>2],"parameter "+i)}return a};var reflectConstruct=Reflect.construct;var __emval_get_method_caller=(argCount,argTypes,kind)=>{var types=emval_lookupTypes(argCount,argTypes);var retType=types.shift();argCount--;var functionBody=`return function (obj, func, destructorsRef, args) {\n`;var offset=0;var argsList=[];if(kind===0){argsList.push("obj")}var params=["retType"];var args=[retType];for(var i=0;it.name).join(", ")}) => ${retType.name}>`;return emval_addMethodCaller(createNamedFunction(functionName,invokerFunction))};var __emval_get_module_property=name=>{name=getStringOrSymbol(name);return Emval.toHandle(Module[name])};var __emval_get_property=(handle,key)=>{handle=Emval.toValue(handle);key=Emval.toValue(key);return Emval.toHandle(handle[key])};var __emval_incref=handle=>{if(handle>9){emval_handles[handle+1]+=1}};var __emval_new_cstring=v=>Emval.toHandle(getStringOrSymbol(v));var __emval_run_destructors=handle=>{var destructors=Emval.toValue(handle);runDestructors(destructors);__emval_decref(handle)};var getHeapMax=()=>2147483648;var growMemory=size=>{var b=wasmMemory.buffer;var pages=(size-b.byteLength+65535)/65536;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}var 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=growMemory(newSize);if(replacement){return true}}return false};var _fd_close=fd=>52;var convertI32PairToI53Checked=(lo,hi)=>hi+2097152>>>0<4194305-!!lo?(lo>>>0)+hi*4294967296:NaN;function _fd_seek(fd,offset_low,offset_high,whence,newOffset){var offset=convertI32PairToI53Checked(offset_low,offset_high);return 70}var printCharBuffers=[null,[],[]];var 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)}};var _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};InternalError=Module["InternalError"]=class InternalError extends Error{constructor(message){super(message);this.name="InternalError"}};embind_init_charCodes();BindingError=Module["BindingError"]=class BindingError extends Error{constructor(message){super(message);this.name="BindingError"}};init_ClassHandle();init_embind();init_RegisteredPointer();UnboundTypeError=Module["UnboundTypeError"]=extendError(Error,"UnboundTypeError");init_emval();var wasmImports={K:___cxa_throw,G:__abort_js,s:__embind_finalize_value_object,C:__embind_register_bigint,I:__embind_register_bool,w:__embind_register_class,v:__embind_register_class_constructor,d:__embind_register_class_function,m:__embind_register_constant,H:__embind_register_emval,o:__embind_register_enum,a:__embind_register_enum_value,A:__embind_register_float,i:__embind_register_function,l:__embind_register_integer,f:__embind_register_memory_view,z:__embind_register_std_string,u:__embind_register_std_wstring,t:__embind_register_value_object,c:__embind_register_value_object_field,J:__embind_register_void,F:__emscripten_memcpy_js,n:__emval_as,q:__emval_call,p:__emval_call_method,b:__emval_decref,x:__emval_get_global,j:__emval_get_method_caller,r:__emval_get_module_property,g:__emval_get_property,k:__emval_incref,h:__emval_new_cstring,e:__emval_run_destructors,D:_emscripten_resize_heap,E:_fd_close,B:_fd_seek,y:_fd_write};var wasmExports=createWasm();var ___wasm_call_ctors=()=>(___wasm_call_ctors=wasmExports["M"])();var ___getTypeName=a0=>(___getTypeName=wasmExports["N"])(a0);var _malloc=a0=>(_malloc=wasmExports["O"])(a0);var _free=a0=>(_free=wasmExports["Q"])(a0);var ___cxa_is_pointer_type=a0=>(___cxa_is_pointer_type=wasmExports["R"])(a0);var dynCall_jiji=Module["dynCall_jiji"]=(a0,a1,a2,a3,a4)=>(dynCall_jiji=Module["dynCall_jiji"]=wasmExports["S"])(a0,a1,a2,a3,a4);var calledRun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(){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);Module["onRuntimeInitialized"]?.();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run();moduleRtn=readyPromise;
- return BASIS.ready
+ return moduleRtn;
}
);
})();
if (typeof exports === 'object' && typeof module === 'object')
- module.exports = BASIS;
- else if (typeof define === 'function' && define['amd'])
- define([], function() { return BASIS; });
- else if (typeof exports === 'object')
- exports["BASIS"] = BASIS;
-
\ No newline at end of file
+ module.exports = BASIS;
+else if (typeof define === 'function' && define['amd'])
+ define([], () => BASIS);
diff --git a/webgl/transcoder/build/basis_transcoder.wasm b/webgl/transcoder/build/basis_transcoder.wasm
index bc74770..bc64682 100644
Binary files a/webgl/transcoder/build/basis_transcoder.wasm and b/webgl/transcoder/build/basis_transcoder.wasm differ