@photivra/engine 2.21.0 → 2.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +118 -1
- package/CITATION.cff +1 -1
- package/README.md +6 -6
- package/SECURITY.md +1 -1
- package/THIRD_PARTY.md +11 -0
- package/dist/capture/c2pa-embed.d.ts +116 -0
- package/dist/capture/c2pa-embed.js +493 -0
- package/dist/capture/c2pa-embed.js.map +1 -0
- package/dist/capture/dng-import.d.ts +73 -8
- package/dist/capture/dng-import.js +315 -80
- package/dist/capture/dng-import.js.map +1 -1
- package/dist/capture/dng-opcodes.d.ts +96 -0
- package/dist/capture/dng-opcodes.js +391 -0
- package/dist/capture/dng-opcodes.js.map +1 -0
- package/dist/capture/dng-profile-maps.d.ts +99 -0
- package/dist/capture/dng-profile-maps.js +381 -0
- package/dist/capture/dng-profile-maps.js.map +1 -0
- package/dist/capture/dng-stage-image.d.ts +23 -0
- package/dist/capture/dng-stage-image.js +65 -0
- package/dist/capture/dng-stage-image.js.map +1 -0
- package/dist/capture/jpeg-xl-tiles.d.ts +22 -0
- package/dist/capture/jpeg-xl-tiles.js +151 -0
- package/dist/capture/jpeg-xl-tiles.js.map +1 -0
- package/dist/capture/lossy-jpeg.d.ts +17 -0
- package/dist/capture/lossy-jpeg.js +369 -0
- package/dist/capture/lossy-jpeg.js.map +1 -0
- package/dist/capture/native-raw-development.d.ts +2 -1
- package/dist/capture/native-raw-development.js.map +1 -1
- package/dist/color/neighbor-highlight-reconstruction.d.ts +66 -0
- package/dist/color/neighbor-highlight-reconstruction.js +234 -0
- package/dist/color/neighbor-highlight-reconstruction.js.map +1 -0
- package/dist/color/sensor-color-development.d.ts +5 -0
- package/dist/color/sensor-color-development.js +7 -1
- package/dist/color/sensor-color-development.js.map +1 -1
- package/dist/color/spectral-spikiness.d.ts +11 -0
- package/dist/color/spectral-spikiness.js +23 -0
- package/dist/color/spectral-spikiness.js.map +1 -0
- package/dist/core/execution-error.d.ts +21 -0
- package/dist/core/execution-error.js +12 -0
- package/dist/core/execution-error.js.map +1 -0
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.js +1 -1
- package/dist/core/version.js.map +1 -1
- package/dist/facade/catalogue-lens-signal.d.ts +26 -1
- package/dist/facade/catalogue-lens-signal.js +25 -7
- package/dist/facade/catalogue-lens-signal.js.map +1 -1
- package/dist/facade/diffraction-provider.d.ts +1 -1
- package/dist/facade/diffraction-provider.js +4 -4
- package/dist/facade/diffraction-provider.js.map +1 -1
- package/dist/facade/display-view-gpu-session.js +38 -6
- package/dist/facade/display-view-gpu-session.js.map +1 -1
- package/dist/facade/display-view-gpu.d.ts +13 -5
- package/dist/facade/display-view-gpu.js.map +1 -1
- package/dist/facade/display-view-normal.d.ts +15 -0
- package/dist/facade/display-view-normal.js +44 -0
- package/dist/facade/display-view-normal.js.map +1 -0
- package/dist/facade/display-view-rendering.d.ts +97 -0
- package/dist/facade/display-view-rendering.js +598 -0
- package/dist/facade/display-view-rendering.js.map +1 -0
- package/dist/facade/display-view.d.ts +37 -65
- package/dist/facade/display-view.js +147 -476
- package/dist/facade/display-view.js.map +1 -1
- package/dist/facade/expected-signal-setup.js +2 -2
- package/dist/facade/expected-signal-setup.js.map +1 -1
- package/dist/facade/fast-methods.d.ts +1 -1
- package/dist/facade/fast-methods.js +37 -8
- package/dist/facade/fast-methods.js.map +1 -1
- package/dist/facade/generic-lens-capture.d.ts +1 -1
- package/dist/facade/generic-lens-capture.js +1 -1
- package/dist/facade/generic-lens-capture.js.map +1 -1
- package/dist/facade/image-plane.js +41 -10
- package/dist/facade/image-plane.js.map +1 -1
- package/dist/facade/on-demand-kits.d.ts +14 -0
- package/dist/facade/on-demand-kits.js +36 -0
- package/dist/facade/on-demand-kits.js.map +1 -0
- package/dist/facade/opt-in-kit.d.ts +9 -0
- package/dist/facade/opt-in-kit.js +11 -0
- package/dist/facade/opt-in-kit.js.map +1 -0
- package/dist/facade/quality-kit.d.ts +21 -0
- package/dist/facade/quality-kit.js +23 -0
- package/dist/facade/quality-kit.js.map +1 -0
- package/dist/facade/quality-paths.d.ts +22 -0
- package/dist/facade/quality-paths.js +44 -0
- package/dist/facade/quality-paths.js.map +1 -0
- package/dist/facade/scene-radiance.d.ts +18 -2
- package/dist/facade/scene-radiance.js +6 -4
- package/dist/facade/scene-radiance.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +32 -13
- package/dist/facade/simulate-capture.js +162 -69
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/facade/simulate-display-view.d.ts +10 -12
- package/dist/facade/simulate-display-view.js +57 -48
- package/dist/facade/simulate-display-view.js.map +1 -1
- package/dist/gpu/display-view-gpu-renderer.d.ts +43 -0
- package/dist/gpu/display-view-gpu-renderer.js +134 -0
- package/dist/gpu/display-view-gpu-renderer.js.map +1 -0
- package/dist/gpu/display-view-image-material-module.d.ts +3 -2
- package/dist/gpu/display-view-image-material-module.js +25 -3
- package/dist/gpu/display-view-image-material-module.js.map +1 -1
- package/dist/gpu/display-view-image-quality.d.ts +43 -1
- package/dist/gpu/display-view-image-quality.js +256 -11
- package/dist/gpu/display-view-image-quality.js.map +1 -1
- package/dist/gpu/display-view-quality-gpu.d.ts +13 -64
- package/dist/gpu/display-view-quality-gpu.js +60 -249
- package/dist/gpu/display-view-quality-gpu.js.map +1 -1
- package/dist/gpu/display-view-speed-gpu.d.ts +16 -16
- package/dist/gpu/display-view-speed-gpu.js +50 -12
- package/dist/gpu/display-view-speed-gpu.js.map +1 -1
- package/dist/gpu/image-kernel-accelerator.js +3 -0
- package/dist/gpu/image-kernel-accelerator.js.map +1 -1
- package/dist/gpu/image-kernel-execution.d.ts +2 -13
- package/dist/gpu/image-kernel-execution.js +2 -10
- package/dist/gpu/image-kernel-execution.js.map +1 -1
- package/dist/gpu/wgsl-display-view-coupled-stub.d.ts +8 -0
- package/dist/gpu/wgsl-display-view-coupled-stub.js +21 -0
- package/dist/gpu/wgsl-display-view-coupled-stub.js.map +1 -0
- package/dist/gpu/wgsl-display-view-coupled.d.ts +88 -0
- package/dist/gpu/wgsl-display-view-coupled.js +353 -0
- package/dist/gpu/wgsl-display-view-coupled.js.map +1 -0
- package/dist/gpu/wgsl-display-view-quality-kernel.d.ts +4 -9
- package/dist/gpu/wgsl-display-view-quality-kernel.js +109 -111
- package/dist/gpu/wgsl-display-view-quality-kernel.js.map +1 -1
- package/dist/gpu/wgsl-display-view-speed-kernel.d.ts +1 -41
- package/dist/gpu/wgsl-display-view-speed-kernel.js +71 -8
- package/dist/gpu/wgsl-display-view-speed-kernel.js.map +1 -1
- package/dist/index.d.ts +11 -3
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/output/camera-channel-response.d.ts +50 -0
- package/dist/output/camera-channel-response.js +69 -0
- package/dist/output/camera-channel-response.js.map +1 -0
- package/dist/output/native-capture-sdr.js +5 -2
- package/dist/output/native-capture-sdr.js.map +1 -1
- package/dist/output/sdr-rendering.d.ts +18 -1
- package/dist/output/sdr-rendering.js +39 -2
- package/dist/output/sdr-rendering.js.map +1 -1
- package/dist/sensor/native-sensor-report.d.ts +10 -0
- package/dist/sensor/native-sensor-report.js +16 -0
- package/dist/sensor/native-sensor-report.js.map +1 -0
- package/dist/sensor/sensor-characteristics.d.ts +81 -13
- package/dist/sensor/sensor-characteristics.js +10 -6
- package/dist/sensor/sensor-characteristics.js.map +1 -1
- package/docs/API_REFERENCE.md +117 -4
- package/docs/QUICK_START.md +37 -8
- package/docs/USAGE.md +104 -22
- package/docs/api/capture-c2pa-embed.md +177 -0
- package/docs/api/capture-dng-import.md +86 -10
- package/docs/api/capture-dng-opcodes.md +93 -0
- package/docs/api/capture-dng-profile-maps.md +141 -0
- package/docs/api/capture-dng-stage-image.md +43 -0
- package/docs/api/capture-jpeg-xl-tiles.md +33 -0
- package/docs/api/capture-lossy-jpeg.md +41 -0
- package/docs/api/capture-native-raw-development.md +2 -1
- package/docs/api/core-execution-error.md +43 -0
- package/docs/api/core-version.md +1 -1
- package/docs/api/exports.json +255 -5
- package/docs/api/facade-display-view-gpu.md +5 -2
- package/docs/api/facade-display-view.md +11 -15
- package/docs/api/facade-fast-methods.md +38 -9
- package/docs/api/facade-quality-paths.md +24 -0
- package/docs/api/facade-scene-radiance.md +1 -1
- package/docs/api/facade-simulate-capture.md +24 -7
- package/docs/api/facade-simulate-display-view.md +10 -12
- package/docs/api/gpu-image-kernel-execution.md +0 -36
- package/docs/api/output-camera-channel-response.md +55 -0
- package/docs/api/output-sdr-rendering.md +6 -1
- package/docs/api/sensor-sensor-characteristics.md +54 -2
- package/llms.txt +1 -0
- package/package.json +6 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wgsl-display-view-speed-kernel.js","sourceRoot":"","sources":["../../src/gpu/wgsl-display-view-speed-kernel.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * WGSL kernel of the display view's Speed path on the GPU (#478): one invocation per display pixel of the exact\n * area mean (docs/DISPLAY_VIEW.md, \"Exact area mean\") without diffraction, with the bilinear demosaic and chart\n * materials. It evaluates `renderDisplayView`'s per-sample loop (facade/display-view.ts) for every real pixel of the\n * display pixel's footprint, in the reference's operation order where the order matters, in float32:\n *\n * 1. the real pixels the footprint covers and their overlap weights a_j = w_j / A (the host computes the 1-D overlaps\n * divided by the scale in float64; the kernel multiplies the two axes);\n * 2. for every native site the real pixels' demosaic reads (the footprint plus one site of reach), the expected\n * electrons: the scene material at the pixel aperture's query offsets (the material module, `material_at`), the\n * material's channel signal integrated in the kernel from its spectrum (Σ_λ A_c(λ)·L(λ), `material_signal`), or (#581) the image-plane\n * module's channel signal at the point (`scene_value`), summed over the offsets in the reference's order, plus the dark\n * electrons;\n * 3. the readout moments of each site (mean k·e, variance k²·e + c₀, third cumulant k³·e) and the clip at the white\n * level (the clipped-normal moments, in a cancellation-free standardized form);\n * 4. per real pixel the bilinear kernels, white balance and highlight clip, the colour matrix, the tone curve\n * (identity, or positive Reinhard by the reference's 4 × 16-point Gauss–Legendre rule) and the clip to [0, 1] with\n * the first-order skewness term;\n * 5. the display pixel's expected value Σ_j a_j·E[L_j], the linear (Stein) covariance Σ_c B_c·σ_c²·a_c·a_cᵀ with the\n * closed-form B_c of the footprint, and the independent residual Σ_j a_j²·r_j.\n *\n * It outputs, per display pixel, the three means, the three variances (linear plus residual), the three covariances\n * and two running error terms: the absolute error bound of the mean and of the variance that the clip steps\n * contribute (a fixed formula evaluated from the pixel's own float32 values; docs/WEBGPU.md, \"Display view (Speed)\").\n * #533: it also decides each real pixel's saturation probability where the float32 values leave no doubt: a site is\n * certainly unclipped or certainly clipped when its standardized distance from white, with the site's mean moved by twice\n * `DISPLAY_VIEW_SITE_RELATIVE_U`·E of itself, still exceeds twice the reference's 8.5 (where the reference's probability is\n * exactly 0 or 1), and a real pixel is certainly saturated (P = 1) when a site its demosaic reads is certainly clipped and\n * certainly not (P = 0) when all are certainly unclipped. Three flag words per display pixel: bit 0 of the first the\n * material flag, bit 1 a real pixel left undecided (the host computes the pixel's count with the reference); the other two\n * a bit per real pixel j·nx + i of the footprint with P = 1.\n * The host adds the output quantization term, draws the noise, encodes and rounds (`display-view-speed-gpu.ts`), so\n * the noise draw is the CPU's bit for bit.\n *\n * Precision: float32 with an a-priori bound per step from the WGSL accuracy table (+ − × within one float32 rounding in\n * either direction, E = 2^-23; division 2.5 ULP, sqrt 4.5 ULP, exp 3 + 2|x| ULP; no trigonometric built-in is used). Every quotient that is a constant of\n * the request (the overlaps over the scale, the axis sums over the squared scale, 1/Σw² of the demosaic kernels) is\n * computed on the host in float64 and uploaded. Data-dependent quotients (z = (t − m)/s, the Abramowitz–Stegun t,\n * the skewness) carry the 2.5 ULP bound.\n */\n\nexport const DISPLAY_VIEW_WORKGROUP_SIZE = 64;\n/** Largest footprint per axis (real pixels): the site window is (n + 2)² ≤ 64 entries of private storage. */\nexport const DISPLAY_VIEW_GPU_MAXIMUM_PIXELS_PER_AXIS = 6;\nexport const DISPLAY_VIEW_GPU_WINDOW_SIDE = DISPLAY_VIEW_GPU_MAXIMUM_PIXELS_PER_AXIS + 2;\n/** Largest number of query offsets (pixel-aperture nodes × filter spots) the aux table holds. */\nexport const DISPLAY_VIEW_GPU_MAXIMUM_OFFSETS = 16;\n/** Floats per display pixel in the output buffer: m0 m1 m2, v00 v11 v22 (linear + residual), c01 c02 c12, mean bound, variance bound. */\nexport const DISPLAY_VIEW_OUTPUT_FLOATS = 11;\n/** #533: flag words per display pixel: the flags (bit 0 material uncertain, bit 1 a highlight undecided), then the 36-bit saturated mask. */\nexport const DISPLAY_VIEW_FLAG_WORDS = 3;\n/**\n * #533: relative bound of a site's float32 mean and variance against the reference's float64, in units of E: the electrons'\n * sum of at most 16 offsets (each term a host-rounded weight and a material signal and one product), the dark electrons, and\n * the readout's products and sum carry at most 26 E with a host-rounded material signal (E/2). 2.21.0: the kernel integrates\n * the material signal Σ_n A_c(λ_n)·L_m(λ_n) itself from the host-rounded response and spectrum: each non-negative product\n * carries E/2 + E/2 for its operands and E for its rounding, and the products are summed in blocks of 16 nodes (at most 15\n * additions within a block and 16 across blocks for N ≤ 256 nodes): 33 E instead of E/2, so a site carries at most 58.5 E,\n * inside the unchanged 64.\n */\nexport const DISPLAY_VIEW_SITE_RELATIVE_U = 64;\n/** Most spectral nodes the Speed kernel integrates per site (DISPLAY_VIEW_SITE_RELATIVE_U: 16 blocks of 16). */\nexport const DISPLAY_VIEW_SPEED_MAXIMUM_NODES = 256;\n/** Floats per column or row record of the geometry buffer. */\nexport const DISPLAY_VIEW_GEOMETRY_STRIDE = 20;\n/** Layout of the aux table (float32 words). */\nexport const DISPLAY_VIEW_AUX = /* @__PURE__ */ Object.freeze({\n /** Per offset o: ou (0.5 + ox − W/2), ov (0.5 + oy − H/2), weight, 0. */\n offsets: 0,\n /** Per phase p, channel c, tap t: dx, dy, weight, 0 (4 taps; unused taps have weight 0). */\n taps: 64,\n /** Per phase p, channel c: 1 / Σ_t w_t² (host float64). */\n inverseW2: 256,\n /** 16 Gauss–Legendre nodes then 16 weights on [−1, 1]. */\n gaussLegendre: 272,\n size: 304\n});\n/** Uniform parameter words (see `Params` below): 40 words, 160 bytes. */\nexport const DISPLAY_VIEW_PARAM_WORDS = 40;\n/** The `E` of the bounds: one WGSL rounding of + − × in either direction, 2^-23 (W3C WGSL \"Floating Point Accuracy\"; #471, #487). */\nconst E_LITERAL = \"1.1920928955078125e-7\";\n/**\n * Clip-step constants of the running bound, in units of E (docs/WEBGPU.md, \"Display view (Speed)\", derivation): the\n * absolute error of the clipped-normal mean in units of the standard deviation (`CLIP_MEAN_U`) and of its variance in\n * units of the variance (`CLIP_VARIANCE_U`), for one clip side. The host doubles every bound (MARGIN).\n */\nexport const DISPLAY_VIEW_CLIP_MEAN_U = 1400;\nexport const DISPLAY_VIEW_CLIP_VARIANCE_U = 36000;\n/** The additional relative error of the Reinhard quadrature, in units of E, for the mean and the variance. */\nexport const DISPLAY_VIEW_REINHARD_MEAN_U = 256;\nexport const DISPLAY_VIEW_REINHARD_VARIANCE_U = 512;\n\nconst literal = (value: number): string => {\n const text = String(Math.fround(value));\n return /[.e]/u.test(text) ? text : `${text}.0`;\n};\n\n/**\n * The kernel's own WGSL, without the material module. `assembleDisplayViewSpeedWgsl` appends a module that defines\n * `fn material_at(p: vec2<f32>) -> u32` and `var<private> material_uncertain: bool` (set to true when the point's\n * classification is within its bound of a material boundary; the kernel then flags the display pixel for host\n * recomputation), and the adapter `scene_value(p, c) = material_signal(material_at(p), c)`. #581: a module may instead define\n * `fn scene_value(p: vec2<f32>, c: u32) -> f32` itself (the image-plane module: the print's channel signal at p) and then\n * declares how many roundings it adds (`DisplayViewGpuMaterialModule.extraSiteRoundings`). The module may declare bindings\n * in @group(1) and use the constants E and SLACK declared here.\n */\nexport const DISPLAY_VIEW_SPEED_KERNEL_WGSL = /* wgsl */ `\nconst E: f32 = ${E_LITERAL};\nconst SLACK: f32 = 1e-14;\nconst CLIP_REACH: f32 = 8.5;\nconst CLIP_MEAN_U: f32 = ${literal(DISPLAY_VIEW_CLIP_MEAN_U)};\nconst CLIP_VARIANCE_U: f32 = ${literal(DISPLAY_VIEW_CLIP_VARIANCE_U)};\nconst SITE_RELATIVE_U: f32 = ${literal(DISPLAY_VIEW_SITE_RELATIVE_U)};\nconst WINDOW: u32 = ${DISPLAY_VIEW_GPU_WINDOW_SIDE}u;\nconst STRIDE: u32 = ${DISPLAY_VIEW_GEOMETRY_STRIDE}u;\nstruct Params {\n count: u32, row0: u32, region_w: u32, region_x: u32,\n region_y: u32, margin: u32, native_w: u32, native_h: u32,\n columns: u32, tone: u32, offsets: u32, nodes: u32,\n k0: f32, k1: f32, k2: f32, reach2: f32,\n dark0: f32, dark1: f32, dark2: f32, clip_level: f32,\n c0_0: f32, c0_1: f32, c0_2: f32, pad1: f32,\n g0: f32, g1: f32, g2: f32, pad2: f32,\n m00: f32, m01: f32, m02: f32, m10: f32,\n m11: f32, m12: f32, m20: f32, m21: f32,\n m22: f32, scale_u: f32, scale_v: f32, pad3: f32,\n};\n@group(0) @binding(0) var<uniform> params: Params;\n@group(0) @binding(1) var<storage, read> aux: array<f32>;\n@group(0) @binding(2) var<storage, read> geometry: array<f32>;\n@group(0) @binding(3) var<storage, read> spectral_table: array<f32>;\n@group(0) @binding(4) var<storage, read_write> out: array<f32>;\n@group(0) @binding(5) var<storage, read_write> flags: array<u32>;\n\nvar<private> site_mean: array<f32, 64>;\nvar<private> site_var: array<f32, 64>;\nvar<private> site_third: array<f32, 64>;\nvar<private> site_bound: array<f32, 64>;\n// #533: 0 certainly below white, 1 certainly at or above it, 2 undecided.\nvar<private> site_clip: array<u32, 64>;\n\nfn k_of(c: u32) -> f32 { if (c == 0u) { return params.k0; } if (c == 1u) { return params.k1; } return params.k2; }\nfn dark_of(c: u32) -> f32 { if (c == 0u) { return params.dark0; } if (c == 1u) { return params.dark1; } return params.dark2; }\nfn c0_of(c: u32) -> f32 { if (c == 0u) { return params.c0_0; } if (c == 1u) { return params.c0_1; } return params.c0_2; }\nfn g_of(c: u32) -> f32 { if (c == 0u) { return params.g0; } if (c == 1u) { return params.g1; } return params.g2; }\nfn m_of(r: u32, c: u32) -> f32 {\n let i = r * 3u + c;\n switch (i) {\n case 0u: { return params.m00; } case 1u: { return params.m01; } case 2u: { return params.m02; }\n case 3u: { return params.m10; } case 4u: { return params.m11; } case 5u: { return params.m12; }\n case 6u: { return params.m20; } case 7u: { return params.m21; } default: { return params.m22; }\n }\n}\n// Standard normal density, as the reference forms it: 0.3989422804014327·exp(−0.5·z·z).\nfn phi(z: f32) -> f32 { return 0.3989422804014327 * exp(-0.5 * z * z); }\n// Abramowitz & Stegun 26.2.17: returns (Φ(z), 1 − Φ(z)), each formed from the tail q directly where it is small.\nfn pq(z: f32) -> vec2<f32> {\n let x = abs(z);\n let t = 1.0 / (1.0 + 0.2316419 * x);\n let q = phi(x) * t * (0.319381530 + t * (-0.356563782 + t * (1.781477937 + t * (-1.821255978 + t * 1.330274429))));\n if (z >= 0.0) { return vec2<f32>(1.0 - q, q); }\n return vec2<f32>(q, 1.0 - q);\n}\n// #533: whether a site with mean m (bound dm) and variance v (bound dv) is certainly below white (0), certainly at or above it\n// (1) or undecided (2): the reference's clip probability is exactly 0 or 1 beyond 8.5 standard deviations, and the decision here\n// asks for twice that distance (4·reach²) after moving the mean by twice its bound and the variance up by twice its bound.\nfn clip_state(m: f32, dm: f32, v: f32, dv: f32) -> u32 {\n let gap = 1.0 - m;\n let wide = 4.0 * params.reach2 * (v + 2.0 * dv);\n let below = gap - 2.0 * dm;\n let above = gap + 2.0 * dm;\n if (below > 0.0 && below * below > wide) { return 0u; }\n if (above < 0.0 && above * above > wide) { return 1u; }\n return 2u;\n}\n// Moments of min(Y, top) for Y ~ N(m, v): (mean, variance, slope P). The variance is v·(P − zφ + z²Q − δ²) with\n// δ = φ − zQ: algebraically E[min²] − E[min]² without the m² cancellation.\nfn upper_clip(m: f32, v: f32, top: f32) -> vec3<f32> {\n if (!(v > 0.0)) { return vec3<f32>(min(m, top), 0.0, select(0.0, 1.0, m < top)); }\n let s = sqrt(v);\n let z = (top - m) / s;\n if (z > CLIP_REACH) { return vec3<f32>(m, v, 1.0); }\n if (z < -CLIP_REACH) { return vec3<f32>(top, 0.0, 0.0); }\n let p = pq(z);\n let d = phi(z);\n let delta = d - z * p.y;\n let mean = m - s * delta;\n let ratio = p.x - z * d + z * z * p.y - delta * delta;\n return vec3<f32>(mean, v * max(0.0, ratio), p.x);\n}\n// Moments of clip(Y, 0, 1) for Y with mean m, variance v and standardized skewness γ (|γ| ≤ 1): (mean, variance, inside).\n// With Z standard normal, W = m + s·g(Z), g = clip(Z, a, b): E[g] = aΦa + φa − φb + bQb, E[g²] = a²Φa + (Φb − Φa) −\n// (bφb − aφa) + b²Qb; the mean adds the reference's Edgeworth term (s·γ/6)·(aφa − bφb).\nfn unit_clip(m: f32, v: f32, skewness: f32) -> vec3<f32> {\n if (!(v > 0.0)) { return vec3<f32>(clamp(m, 0.0, 1.0), 0.0, select(0.0, 1.0, m > 0.0 && m < 1.0)); }\n let s = sqrt(v);\n let a = -m / s;\n let b = (1.0 - m) / s;\n if (a < -CLIP_REACH && b > CLIP_REACH) { return vec3<f32>(m, v, 1.0); }\n var pa = 0.0; var da = 0.0;\n if (!(a < -CLIP_REACH)) { pa = pq(a).x; da = phi(a); }\n var pb = 1.0; var qb = 0.0; var db = 0.0;\n if (!(b > CLIP_REACH)) { let p = pq(b); pb = p.x; qb = p.y; db = phi(b); }\n let inside = pb - pa;\n let gamma = clamp(skewness, -1.0, 1.0);\n let aa = a * da;\n let bb = b * db;\n let eg = a * pa + (da - db) + b * qb;\n let eg2 = a * a * pa + inside - (bb - aa) + b * b * qb;\n let normal_mean = m + s * eg;\n var mean = normal_mean;\n var skew_shift = 0.0;\n if (gamma != 0.0) { skew_shift = s * gamma / 6.0 * (aa - bb); mean = normal_mean + skew_shift; }\n // The reference forms E[Y²] − (E[Y] + shift)², so the shift also enters its variance: −shift·(2·E[Y] + shift).\n return vec3<f32>(mean, max(0.0, v * (eg2 - eg * eg) - skew_shift * (2.0 * normal_mean + skew_shift)), inside);\n}\n// Positive Reinhard per channel then the clip to [0, 1]: h(x) = x/(1 + x) for x > 0, else 0. Composite 16-point\n// Gauss–Legendre over [max(0, m − 8.5s), m + 8.5s] in 4 panels, as the reference; the variance is formed about h(m).\nfn reinhard_moments(m: f32, v: f32) -> vec3<f32> {\n if (!(v > 0.0)) {\n if (m > 0.0) { return vec3<f32>(m / (1.0 + m), 0.0, 1.0 / ((1.0 + m) * (1.0 + m))); }\n return vec3<f32>(0.0, 0.0, 0.0);\n }\n let s = sqrt(v);\n // The reference's panels [max(0, m − 8.5s), m + 8.5s] in standardized units z = (x − m)/s, so the node's z is formed\n // without the cancellation x − m: zlo = max(−m/s, −8.5), weight = zhalf·w_k·φ(z_k) (= half·w_k·φ((x − m)/s)/s), x = m + s·z.\n let zlo = max(-m / s, -CLIP_REACH);\n if (!(CLIP_REACH > zlo)) { return vec3<f32>(0.0, 0.0, 0.0); }\n let hm = select(0.0, m / (1.0 + m), m > 0.0);\n var e1 = 0.0; var e2 = 0.0; var ed = 0.0;\n let zwidth = (CLIP_REACH - zlo) / 4.0;\n for (var p = 0u; p < 4u; p = p + 1u) {\n let zc = zlo + (f32(p) + 0.5) * zwidth;\n let zhalf = zwidth / 2.0;\n for (var k = 0u; k < 16u; k = k + 1u) {\n let z = zc + zhalf * aux[${DISPLAY_VIEW_AUX.gaussLegendre}u + k];\n let x = m + s * z;\n let weight = zhalf * aux[${DISPLAY_VIEW_AUX.gaussLegendre + 16}u + k] * phi(z);\n let h = x / (1.0 + x);\n e1 = e1 + weight * h;\n e2 = e2 + weight * (h - hm) * (h - hm);\n ed = ed + weight / ((1.0 + x) * (1.0 + x));\n }\n }\n let shifted = e1 - hm;\n return vec3<f32>(e1, max(0.0, e2 - shifted * shifted), ed);\n}\nfn reflect_x(x: i32) -> i32 { if (x < 0) { return -x; } if (x >= i32(params.native_w)) { return 2 * i32(params.native_w) - 2 - x; } return x; }\nfn reflect_y(y: i32) -> i32 { if (y < 0) { return -y; } if (y >= i32(params.native_h)) { return 2 * i32(params.native_h) - 2 - y; } return y; }\nfn channel_of(x: i32, y: i32) -> u32 {\n if ((y & 1) == 0) { return select(1u, 0u, (x & 1) == 0); }\n return select(2u, 1u, (x & 1) == 0);\n}\nfn material_signal(m: u32, c: u32) -> f32 {\n let n = params.nodes;\n var s = 0.0;\n var b = 0.0;\n for (var k = 0u; k < n; k = k + 1u) {\n b = b + spectral_table[c * n + k] * spectral_table[(3u + m) * n + k];\n if ((k & 15u) == 15u) { s = s + b; b = 0.0; }\n }\n return s + b;\n}\n// The expected photo electrons of native site (x, y): Σ_o w_o·scene_value(p_o, c) in offset order (directSite); with a material\n// module scene_value is S_c(m_o), integrated from the material's spectrum (material_signal).\nfn site_electrons(x: i32, y: i32, c: u32) -> f32 {\n var sum = 0.0;\n let fx = f32(x);\n let fy = f32(y);\n for (var o = 0u; o < params.offsets; o = o + 1u) {\n let base = ${DISPLAY_VIEW_AUX.offsets}u + 4u * o;\n let u = (fx + aux[base]) * params.scale_u;\n let v = (fy + aux[base + 1u]) * params.scale_v;\n sum = sum + aux[base + 2u] * scene_value(vec2<f32>(u, v), c);\n }\n return sum;\n}\n@compute @workgroup_size(${DISPLAY_VIEW_WORKGROUP_SIZE})\nfn main(@builtin(global_invocation_id) gid: vec3<u32>, @builtin(num_workgroups) groups: vec3<u32>) {\n let i = gid.x + gid.y * groups.x * ${DISPLAY_VIEW_WORKGROUP_SIZE}u;\n if (i >= params.count) { return; }\n material_uncertain = false;\n let rx = i % params.region_w;\n let ry = params.row0 + i / params.region_w;\n let col = rx * STRIDE;\n let row = (params.columns + ry) * STRIDE;\n let col_first = bitcast<i32>(geometry[col]);\n let nx = bitcast<u32>(geometry[col + 1u]);\n let row_first = bitcast<i32>(geometry[row]);\n let ny = bitcast<u32>(geometry[row + 1u]);\n let margin = i32(params.margin);\n // 2. and 3.: the sites of the footprint plus one site of reach, once each.\n let x0 = col_first + margin - 1;\n let y0 = row_first + margin - 1;\n let window_w = nx + 2u;\n for (var sj = 0u; sj < ny + 2u; sj = sj + 1u) {\n let sy = reflect_y(y0 + i32(sj));\n for (var si = 0u; si < window_w; si = si + 1u) {\n let sx = reflect_x(x0 + i32(si));\n let c = channel_of(sx, sy);\n let e = site_electrons(sx, sy, c) + dark_of(c);\n let kc = k_of(c);\n let mean = kc * e;\n let variance = kc * kc * e + c0_of(c);\n let gap = 1.0 - mean;\n let slot = sj * window_w + si;\n site_third[slot] = kc * kc * kc * e;\n site_clip[slot] = clip_state(mean, SITE_RELATIVE_U * E * mean, variance, SITE_RELATIVE_U * E * variance);\n if (gap > 0.0 && gap * gap > params.reach2 * variance) {\n site_mean[slot] = mean; site_var[slot] = variance; site_bound[slot] = 0.0;\n } else {\n let clipped = upper_clip(mean, variance, 1.0);\n site_mean[slot] = clipped.x; site_var[slot] = clipped.y; site_bound[slot] = sqrt(variance);\n }\n }\n }\n // B_c of the footprint from the host's axis sums (each over its scale squared): red, green, blue.\n let xb_even = geometry[col + 8u]; let xb_odd = geometry[col + 9u];\n let xpp_even = geometry[col + 10u]; let xpp_odd = geometry[col + 11u];\n let xqq_even = geometry[col + 12u]; let xqq_odd = geometry[col + 13u];\n let xpq_even = geometry[col + 14u]; let xpq_odd = geometry[col + 15u];\n let yb_even = geometry[row + 8u]; let yb_odd = geometry[row + 9u];\n let ypp_even = geometry[row + 10u]; let ypp_odd = geometry[row + 11u];\n let yqq_even = geometry[row + 12u]; let yqq_odd = geometry[row + 13u];\n let ypq_even = geometry[row + 14u]; let ypq_odd = geometry[row + 15u];\n let b0 = xb_even * yb_even;\n let b1 = (xpp_odd * ypp_even + xqq_odd * ypp_even + xpp_odd * yqq_even + 2.0 * xpq_odd * ypp_even + 2.0 * xpp_odd * ypq_even + 2.0 * xpq_odd * ypq_even) +\n (xpp_even * ypp_odd + xqq_even * ypp_odd + xpp_even * yqq_odd + 2.0 * xpq_even * ypp_odd + 2.0 * xpp_even * ypq_odd + 2.0 * xpq_even * ypq_odd);\n let b2 = xb_odd * yb_odd;\n let reinhard = params.tone == 1u;\n var s0 = 0.0; var s1 = 0.0; var s2 = 0.0;\n var c00 = 0.0; var c01 = 0.0; var c02 = 0.0; var c11 = 0.0; var c12 = 0.0; var c22 = 0.0;\n var r0 = 0.0; var r1 = 0.0; var r2 = 0.0;\n var bound_mean = 0.0; var bound_var = 0.0;\n // #533: the saturated real pixels (bit j·nx + i) and whether any real pixel is undecided.\n var mask0 = 0u; var mask1 = 0u; var undecided = false;\n // 4. and 5.: every real pixel of the footprint with its overlap weight.\n for (var j = 0u; j < ny; j = j + 1u) {\n let ay = geometry[row + 2u + j];\n for (var ii = 0u; ii < nx; ii = ii + 1u) {\n let aj = geometry[col + 2u + ii] * ay;\n let x = col_first + i32(ii) + margin;\n let y = row_first + i32(j) + margin;\n let phase = u32(y & 1) * 2u + u32(x & 1);\n var cm: array<f32, 3>; var cvv: array<f32, 3>; var cth: array<f32, 3>; var csv: array<f32, 3>; var cb: array<f32, 3>;\n var clipped = false; var near_white = false;\n for (var c = 0u; c < 3u; c = c + 1u) {\n var mean = 0.0; var variance = 0.0; var third = 0.0; var bnd = 0.0;\n let taps = ${DISPLAY_VIEW_AUX.taps}u + (phase * 3u + c) * 16u;\n for (var t = 0u; t < 4u; t = t + 1u) {\n let w = aux[taps + 4u * t + 2u];\n let slot = u32((i32(j) + 1 + i32(aux[taps + 4u * t + 1u])) * i32(window_w) + i32(ii) + 1 + i32(aux[taps + 4u * t]));\n mean = mean + w * site_mean[slot];\n variance = variance + w * w * site_var[slot];\n third = third + w * w * w * site_third[slot];\n bnd = max(bnd, select(0.0, site_bound[slot], w != 0.0));\n if (w != 0.0) { if (site_clip[slot] == 1u) { clipped = true; } else if (site_clip[slot] == 2u) { near_white = true; } }\n }\n cm[c] = mean; cvv[c] = variance; cth[c] = third; cb[c] = bnd;\n csv[c] = variance * aux[${DISPLAY_VIEW_AUX.inverseW2}u + phase * 3u + c];\n }\n if (clipped) {\n let bit = j * nx + ii;\n if (bit < 32u) { mask0 = mask0 | (1u << bit); } else { mask1 = mask1 | (1u << (bit - 32u)); }\n } else if (near_white) { undecided = true; }\n // White balance and the highlight clip at the smallest gain: bm, bv, bs (slope), with the clip's bound terms.\n var bm: array<f32, 3>; var bv: array<f32, 3>; var bs: array<f32, 3>; var bbm: array<f32, 3>; var bbv: array<f32, 3>;\n for (var c = 0u; c < 3u; c = c + 1u) {\n let gc = g_of(c);\n let um = gc * cm[c];\n let uv = gc * gc * cvv[c];\n let gap = params.clip_level - um;\n bbm[c] = gc * CLIP_MEAN_U * cb[c];\n bbv[c] = gc * gc * CLIP_VARIANCE_U * cb[c] * cb[c];\n if (gap > 0.0 && gap * gap > params.reach2 * uv) { bm[c] = um; bv[c] = uv; bs[c] = gc; }\n else {\n let clipped = upper_clip(um, uv, params.clip_level);\n bm[c] = clipped.x; bv[c] = clipped.y; bs[c] = gc * clipped.z;\n bbm[c] = bbm[c] + CLIP_MEAN_U * sqrt(uv);\n bbv[c] = bbv[c] + CLIP_VARIANCE_U * uv;\n }\n }\n // Colour matrix, then the rendering of each component (tone curve, clip to [0, 1]).\n var hm: array<f32, 3>; var hv: array<f32, 3>; var hs: array<f32, 3>; var hbm: array<f32, 3>; var hbv: array<f32, 3>;\n for (var comp = 0u; comp < 3u; comp = comp + 1u) {\n let r0m = m_of(comp, 0u); let r1m = m_of(comp, 1u); let r2m = m_of(comp, 2u);\n let mean = r0m * bm[0] + r1m * bm[1] + r2m * bm[2];\n let variance = r0m * r0m * bv[0] + r1m * r1m * bv[1] + r2m * r2m * bv[2];\n var bm_c = abs(r0m) * bbm[0] + abs(r1m) * bbm[1] + abs(r2m) * bbm[2];\n var bv_c = r0m * r0m * bbv[0] + r1m * r1m * bbv[1] + r2m * r2m * bbv[2];\n if (!reinhard && mean > 0.0 && mean < 1.0 && mean * mean > params.reach2 * variance && (1.0 - mean) * (1.0 - mean) > params.reach2 * variance) {\n hm[comp] = mean; hv[comp] = variance; hs[comp] = 1.0;\n } else if (reinhard) {\n let moments = reinhard_moments(mean, variance);\n hm[comp] = moments.x; hv[comp] = moments.y; hs[comp] = moments.z;\n bm_c = bm_c + 2.0 * CLIP_MEAN_U * sqrt(variance);\n bv_c = bv_c + 2.0 * CLIP_VARIANCE_U * variance;\n } else {\n // κ₃ of the component: Σ_c (M_comp,c·Γ_c)³·Σ_t w_t³·κ₃(site) (the sites of one channel share the coefficient).\n let k0 = r0m * bs[0]; let k1 = r1m * bs[1]; let k2 = r2m * bs[2];\n let third = k0 * k0 * k0 * cth[0] + k1 * k1 * k1 * cth[1] + k2 * k2 * k2 * cth[2];\n let skew = select(0.0, third / (variance * sqrt(variance)), variance > 0.0);\n let moments = unit_clip(mean, variance, skew);\n hm[comp] = moments.x; hv[comp] = moments.y; hs[comp] = moments.z;\n bm_c = bm_c + 2.0 * CLIP_MEAN_U * sqrt(variance);\n bv_c = bv_c + 2.0 * CLIP_VARIANCE_U * variance;\n }\n hbm[comp] = bm_c; hbv[comp] = bv_c;\n }\n s0 = s0 + aj * hm[0]; s1 = s1 + aj * hm[1]; s2 = s2 + aj * hm[2];\n // Linear (Stein) part with B_c·σ_c², and the pixel's own linear variance for the residual.\n var l0 = 0.0; var l1 = 0.0; var l2 = 0.0;\n var lb0 = 0.0; var lb1 = 0.0; var lb2 = 0.0;\n for (var c = 0u; c < 3u; c = c + 1u) {\n let a0 = hs[0] * m_of(0u, c) * bs[c];\n let a1 = hs[1] * m_of(1u, c) * bs[c];\n let a2 = hs[2] * m_of(2u, c) * bs[c];\n var bc = b0; if (c == 1u) { bc = b1; } if (c == 2u) { bc = b2; }\n let wgt = aj * bc * csv[c];\n c00 = c00 + wgt * a0 * a0; c01 = c01 + wgt * a0 * a1; c02 = c02 + wgt * a0 * a2;\n c11 = c11 + wgt * a1 * a1; c12 = c12 + wgt * a1 * a2; c22 = c22 + wgt * a2 * a2;\n l0 = l0 + a0 * a0 * cvv[c]; l1 = l1 + a1 * a1 * cvv[c]; l2 = l2 + a2 * a2 * cvv[c];\n // The clip bound of each channel's variance enters the covariance through a_j·B_c·(Δσ_c²/Σw²)·a_i·a_j and the\n // residual's linear prediction through a²·Δσ_c².\n lb0 = lb0 + (a0 * a0) * bbv[c]; lb1 = lb1 + (a1 * a1) * bbv[c]; lb2 = lb2 + (a2 * a2) * bbv[c];\n bound_var = bound_var + aj * bc * (bbv[c] * aux[${DISPLAY_VIEW_AUX.inverseW2}u + phase * 3u + c]) * max(a0 * a0, max(a1 * a1, a2 * a2));\n }\n r0 = r0 + aj * aj * max(0.0, hv[0] - l0);\n r1 = r1 + aj * aj * max(0.0, hv[1] - l1);\n r2 = r2 + aj * aj * max(0.0, hv[2] - l2);\n bound_mean = bound_mean + aj * max(hbm[0], max(hbm[1], hbm[2]));\n bound_var = bound_var + aj * aj * (max(hbv[0], max(hbv[1], hbv[2])) + max(lb0, max(lb1, lb2)));\n }\n }\n let o = i * ${DISPLAY_VIEW_OUTPUT_FLOATS}u;\n out[o] = s0; out[o + 1u] = s1; out[o + 2u] = s2;\n out[o + 3u] = c00 + r0; out[o + 4u] = c11 + r1; out[o + 5u] = c22 + r2;\n out[o + 6u] = c01; out[o + 7u] = c02; out[o + 8u] = c12;\n out[o + 9u] = bound_mean * E; out[o + 10u] = bound_var * E;\n flags[3u * i] = select(0u, 1u, material_uncertain) | select(0u, 2u, undecided);\n flags[3u * i + 1u] = mask0;\n flags[3u * i + 2u] = mask1;\n}\n`;\n\n/**\n * The channel signal of the material a material module's `material_at` gives (the kernel's `scene_value`), integrated from its\n * spectrum when it changes (2.21.0: signals are integrated from the material spectrum per site).\n */\nexport const DISPLAY_VIEW_MATERIAL_SCENE_VALUE_WGSL = /* wgsl */ `\nvar<private> scene_m: u32 = 0xffffffffu;\nvar<private> scene_c: u32 = 0u;\nvar<private> scene_s: f32 = 0.0;\nfn scene_value(p: vec2<f32>, c: u32) -> f32 {\n let m = material_at(p);\n if (m != scene_m || c != scene_c) { scene_s = material_signal(m, c); scene_m = m; scene_c = c; }\n return scene_s;\n}\n`;\n/** The full shader: the kernel plus a material module (see `DISPLAY_VIEW_SPEED_KERNEL_WGSL`), and the table adapter unless the module defines `scene_value`. */\nexport function assembleDisplayViewSpeedWgsl(materialModuleWgsl: string): string {\n const adapter = /\\bfn scene_value\\(/u.test(materialModuleWgsl) ? \"\" : DISPLAY_VIEW_MATERIAL_SCENE_VALUE_WGSL;\n return DISPLAY_VIEW_SPEED_KERNEL_WGSL + \"\\n\" + materialModuleWgsl + \"\\n\" + adapter;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"wgsl-display-view-speed-kernel.js","sourceRoot":"","sources":["../../src/gpu/wgsl-display-view-speed-kernel.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * WGSL kernel of the display view's Speed path on the GPU (#478): one invocation per display pixel of the exact\n * area mean (docs/DISPLAY_VIEW.md, \"Exact area mean\") without diffraction, with the bilinear demosaic and chart\n * materials. It evaluates `renderDisplayView`'s per-sample loop (facade/display-view.ts) for every real pixel of the\n * display pixel's footprint, in the reference's operation order where the order matters, in float32:\n *\n * 1. the real pixels the footprint covers and their overlap weights a_j = w_j / A (the host computes the 1-D overlaps\n * divided by the scale in float64; the kernel multiplies the two axes);\n * 2. for every native site the real pixels' demosaic reads (the footprint plus one site of reach), the expected\n * electrons: the scene material at the pixel aperture's query offsets (the material module, `material_at`), the\n * material's channel signal integrated in the kernel from its spectrum (Σ_λ A_c(λ)·L(λ), `material_signal`), or (#581) the image-plane\n * module's channel signal at the point (`scene_value`), summed over the offsets in the reference's order, plus the dark\n * electrons;\n * 3. the readout moments of each site (mean k·e, variance k²·e + c₀, third cumulant k³·e) and the clip at the white\n * level (the clipped-normal moments, in a cancellation-free standardized form);\n * 4. per real pixel the bilinear kernels, white balance and highlight clip, the colour matrix, the tone curve\n * (identity, or positive Reinhard by the reference's 4 × 16-point Gauss–Legendre rule) and the clip to [0, 1] with\n * the first-order skewness term;\n * 5. the display pixel's expected value Σ_j a_j·E[L_j], the linear (Stein) covariance Σ_c B_c·σ_c²·a_c·a_cᵀ with the\n * closed-form B_c of the footprint, and the independent residual Σ_j a_j²·r_j.\n *\n * It outputs, per display pixel, the three means, the three variances (linear plus residual), the three covariances\n * and two running error terms: the absolute error bound of the mean and of the variance that the clip steps\n * contribute (a fixed formula evaluated from the pixel's own float32 values; docs/WEBGPU.md, \"Display view (Speed)\").\n * #533: it also decides each real pixel's saturation probability where the float32 values leave no doubt: a site is\n * certainly unclipped or certainly clipped when its standardized distance from white, with the site's mean moved by twice\n * `DISPLAY_VIEW_SITE_RELATIVE_U`·E of itself, still exceeds twice the reference's 8.5 (where the reference's probability is\n * exactly 0 or 1), and a real pixel is certainly saturated (P = 1) when a site its demosaic reads is certainly clipped and\n * certainly not (P = 0) when all are certainly unclipped. Three flag words per display pixel: bit 0 of the first the\n * material flag, bit 1 a real pixel left undecided (the host computes the pixel's count with the reference); the other two\n * a bit per real pixel j·nx + i of the footprint with P = 1.\n * The host adds the output quantization term, draws the noise, encodes and rounds (`display-view-speed-gpu.ts`), so\n * the noise draw is the CPU's bit for bit.\n *\n * Precision: float32 with an a-priori bound per step from the WGSL accuracy table (+ − × within one float32 rounding in\n * either direction, E = 2^-23; division 2.5 ULP, sqrt 4.5 ULP, exp 3 + 2|x| ULP; no trigonometric built-in is used). Every quotient that is a constant of\n * the request (the overlaps over the scale, the axis sums over the squared scale, 1/Σw² of the demosaic kernels) is\n * computed on the host in float64 and uploaded. Data-dependent quotients (z = (t − m)/s, the Abramowitz–Stegun t,\n * the skewness) carry the 2.5 ULP bound.\n */\n\nimport { DISPLAY_VIEW_COUPLED_STUB_WGSL } from \"./wgsl-display-view-coupled-stub.js\";\n\nexport const DISPLAY_VIEW_WORKGROUP_SIZE = 64;\n/** Largest footprint per axis (real pixels): the site window is (n + 2)² ≤ 64 entries of private storage. */\nexport const DISPLAY_VIEW_GPU_MAXIMUM_PIXELS_PER_AXIS = 6;\nexport const DISPLAY_VIEW_GPU_WINDOW_SIDE = DISPLAY_VIEW_GPU_MAXIMUM_PIXELS_PER_AXIS + 2;\n/** Largest number of query offsets (pixel-aperture nodes × filter spots) the aux table holds. */\nexport const DISPLAY_VIEW_GPU_MAXIMUM_OFFSETS = 16;\n/** Floats per display pixel in the output buffer: m0 m1 m2, v00 v11 v22 (linear + residual), c01 c02 c12, mean bound, variance bound. */\nexport const DISPLAY_VIEW_OUTPUT_FLOATS = 11;\n/** #533: flag words per display pixel: the flags (bit 0 material uncertain, bit 1 a highlight undecided), then the 36-bit saturated mask. */\nexport const DISPLAY_VIEW_FLAG_WORDS = 3;\n/**\n * #533: relative bound of a site's float32 mean and variance against the reference's float64, in units of E: the electrons'\n * sum of at most 16 offsets (each term a host-rounded weight and a material signal and one product), the dark electrons, and\n * the readout's products and sum carry at most 26 E with a host-rounded material signal (E/2). 2.21.0: the kernel integrates\n * the material signal Σ_n A_c(λ_n)·L_m(λ_n) itself from the host-rounded response and spectrum: each non-negative product\n * carries E/2 + E/2 for its operands and E for its rounding, and the products are summed in blocks of 16 nodes (at most 15\n * additions within a block and 16 across blocks for N ≤ 256 nodes): 33 E instead of E/2, so a site carries at most 58.5 E,\n * inside the unchanged 64.\n */\nexport const DISPLAY_VIEW_SITE_RELATIVE_U = 64;\n/** Most spectral nodes the Speed kernel integrates per site (DISPLAY_VIEW_SITE_RELATIVE_U: 16 blocks of 16). */\nexport const DISPLAY_VIEW_SPEED_MAXIMUM_NODES = 256;\n/** Floats per column or row record of the geometry buffer. */\nexport const DISPLAY_VIEW_GEOMETRY_STRIDE = 20;\n/** Layout of the aux table (float32 words). */\nexport const DISPLAY_VIEW_AUX = /* @__PURE__ */ Object.freeze({\n /** Per offset o: ou (0.5 + ox − W/2), ov (0.5 + oy − H/2), weight, 0. */\n offsets: 0,\n /** Per phase p, channel c, tap t: dx, dy, weight, 0 (4 taps; unused taps have weight 0). */\n taps: 64,\n /** Per phase p, channel c: 1 / Σ_t w_t² (host float64). */\n inverseW2: 256,\n /** 16 Gauss–Legendre nodes then 16 weights on [−1, 1]. */\n gaussLegendre: 272,\n size: 304\n});\n\n/** Uniform parameter words (see `Params` below): 40 words, 160 bytes. */\nexport const DISPLAY_VIEW_PARAM_WORDS = 40;\n/** The `E` of the bounds: one WGSL rounding of + − × in either direction, 2^-23 (W3C WGSL \"Floating Point Accuracy\"; #471, #487). */\nconst E_LITERAL = \"1.1920928955078125e-7\";\n/**\n * Clip-step constants of the running bound, in units of E (docs/WEBGPU.md, \"Display view (Speed)\", derivation): the\n * absolute error of the clipped-normal mean in units of the standard deviation (`CLIP_MEAN_U`) and of its variance in\n * units of the variance (`CLIP_VARIANCE_U`), for one clip side. The host doubles every bound (MARGIN).\n */\nexport const DISPLAY_VIEW_CLIP_MEAN_U = 1400;\nexport const DISPLAY_VIEW_CLIP_VARIANCE_U = 36000;\n/** The additional relative error of the Reinhard quadrature, in units of E, for the mean and the variance. */\nexport const DISPLAY_VIEW_REINHARD_MEAN_U = 256;\nexport const DISPLAY_VIEW_REINHARD_VARIANCE_U = 512;\n\nconst literal = (value: number): string => {\n const text = String(Math.fround(value));\n return /[.e]/u.test(text) ? text : `${text}.0`;\n};\n\n/**\n * The kernel's own WGSL, without the material module. `assembleDisplayViewSpeedWgsl` appends a module that defines\n * `fn material_at(p: vec2<f32>) -> u32` and `var<private> material_uncertain: bool` (set to true when the point's\n * classification is within its bound of a material boundary; the kernel then flags the display pixel for host\n * recomputation), and the adapter `scene_value(p, c) = material_signal(material_at(p), c)`. #581: a module may instead define\n * `fn scene_value(p: vec2<f32>, c: u32) -> f32` itself (the image-plane module: the print's channel signal at p) and then\n * declares how many roundings it adds (`DisplayViewGpuMaterialModule.extraSiteRoundings`). The module may declare bindings\n * in @group(1) and use the constants E and SLACK declared here.\n */\n/*\n * 2.22.0: in the luminance branch the nested loops read the colour matrix rows from one local array (`mm`) instead of calling\n * `m_of` (a `switch`): SwiftShader's compiler ended the GPU process on the `switch` inside those loops (after about 44 s). The\n * values are the same (docs/WEBGPU.md, \"Coupled rendering steps\").\n */\nexport const DISPLAY_VIEW_SPEED_KERNEL_WGSL = /* wgsl */ `\nconst E: f32 = ${E_LITERAL};\nconst SLACK: f32 = 1e-14;\nconst CLIP_REACH: f32 = 8.5;\nconst CLIP_MEAN_U: f32 = ${literal(DISPLAY_VIEW_CLIP_MEAN_U)};\nconst CLIP_VARIANCE_U: f32 = ${literal(DISPLAY_VIEW_CLIP_VARIANCE_U)};\nconst SITE_RELATIVE_U: f32 = ${literal(DISPLAY_VIEW_SITE_RELATIVE_U)};\nconst WINDOW: u32 = ${DISPLAY_VIEW_GPU_WINDOW_SIDE}u;\nconst STRIDE: u32 = ${DISPLAY_VIEW_GEOMETRY_STRIDE}u;\nstruct Params {\n count: u32, row0: u32, region_w: u32, region_x: u32,\n region_y: u32, margin: u32, native_w: u32, native_h: u32,\n columns: u32, tone: u32, offsets: u32, nodes: u32,\n k0: f32, k1: f32, k2: f32, reach2: f32,\n dark0: f32, dark1: f32, dark2: f32, clip_level: f32,\n c0_0: f32, c0_1: f32, c0_2: f32, pad1: f32,\n g0: f32, g1: f32, g2: f32, pad2: f32,\n m00: f32, m01: f32, m02: f32, m10: f32,\n m11: f32, m12: f32, m20: f32, m21: f32,\n m22: f32, scale_u: f32, scale_v: f32, pad3: f32,\n};\n@group(0) @binding(0) var<uniform> params: Params;\n@group(0) @binding(1) var<storage, read> aux: array<f32>;\n@group(0) @binding(2) var<storage, read> geometry: array<f32>;\n@group(0) @binding(3) var<storage, read> spectral_table: array<f32>;\n@group(0) @binding(4) var<storage, read_write> out: array<f32>;\n@group(0) @binding(5) var<storage, read_write> flags: array<u32>;\n// #593, #601: the coupled rendering steps' constants, after the aux table's own entries (one zero word without them).\nfn cp_k(i: u32) -> f32 { return aux[${DISPLAY_VIEW_AUX.size}u + i]; }\n\nvar<private> site_mean: array<f32, 64>;\nvar<private> site_var: array<f32, 64>;\nvar<private> site_third: array<f32, 64>;\nvar<private> site_bound: array<f32, 64>;\n// #533: 0 certainly below white, 1 certainly at or above it, 2 undecided.\nvar<private> site_clip: array<u32, 64>;\n\nfn k_of(c: u32) -> f32 { if (c == 0u) { return params.k0; } if (c == 1u) { return params.k1; } return params.k2; }\nfn dark_of(c: u32) -> f32 { if (c == 0u) { return params.dark0; } if (c == 1u) { return params.dark1; } return params.dark2; }\nfn c0_of(c: u32) -> f32 { if (c == 0u) { return params.c0_0; } if (c == 1u) { return params.c0_1; } return params.c0_2; }\nfn g_of(c: u32) -> f32 { if (c == 0u) { return params.g0; } if (c == 1u) { return params.g1; } return params.g2; }\nfn m_of(r: u32, c: u32) -> f32 {\n let i = r * 3u + c;\n switch (i) {\n case 0u: { return params.m00; } case 1u: { return params.m01; } case 2u: { return params.m02; }\n case 3u: { return params.m10; } case 4u: { return params.m11; } case 5u: { return params.m12; }\n case 6u: { return params.m20; } case 7u: { return params.m21; } default: { return params.m22; }\n }\n}\n// Standard normal density, as the reference forms it: 0.3989422804014327·exp(−0.5·z·z).\nfn phi(z: f32) -> f32 { return 0.3989422804014327 * exp(-0.5 * z * z); }\n// Abramowitz & Stegun 26.2.17: returns (Φ(z), 1 − Φ(z)), each formed from the tail q directly where it is small.\nfn pq(z: f32) -> vec2<f32> {\n let x = abs(z);\n let t = 1.0 / (1.0 + 0.2316419 * x);\n let q = phi(x) * t * (0.319381530 + t * (-0.356563782 + t * (1.781477937 + t * (-1.821255978 + t * 1.330274429))));\n if (z >= 0.0) { return vec2<f32>(1.0 - q, q); }\n return vec2<f32>(q, 1.0 - q);\n}\n// #533: whether a site with mean m (bound dm) and variance v (bound dv) is certainly below white (0), certainly at or above it\n// (1) or undecided (2): the reference's clip probability is exactly 0 or 1 beyond 8.5 standard deviations, and the decision here\n// asks for twice that distance (4·reach²) after moving the mean by twice its bound and the variance up by twice its bound.\nfn clip_state(m: f32, dm: f32, v: f32, dv: f32) -> u32 {\n let gap = 1.0 - m;\n let wide = 4.0 * params.reach2 * (v + 2.0 * dv);\n let below = gap - 2.0 * dm;\n let above = gap + 2.0 * dm;\n if (below > 0.0 && below * below > wide) { return 0u; }\n if (above < 0.0 && above * above > wide) { return 1u; }\n return 2u;\n}\n// Moments of min(Y, top) for Y ~ N(m, v): (mean, variance, slope P). The variance is v·(P − zφ + z²Q − δ²) with\n// δ = φ − zQ: algebraically E[min²] − E[min]² without the m² cancellation.\nfn upper_clip(m: f32, v: f32, top: f32) -> vec3<f32> {\n if (!(v > 0.0)) { return vec3<f32>(min(m, top), 0.0, select(0.0, 1.0, m < top)); }\n let s = sqrt(v);\n let z = (top - m) / s;\n if (z > CLIP_REACH) { return vec3<f32>(m, v, 1.0); }\n if (z < -CLIP_REACH) { return vec3<f32>(top, 0.0, 0.0); }\n let p = pq(z);\n let d = phi(z);\n let delta = d - z * p.y;\n let mean = m - s * delta;\n let ratio = p.x - z * d + z * z * p.y - delta * delta;\n return vec3<f32>(mean, v * max(0.0, ratio), p.x);\n}\n// Moments of clip(Y, 0, 1) for Y with mean m, variance v and standardized skewness γ (|γ| ≤ 1): (mean, variance, inside).\n// With Z standard normal, W = m + s·g(Z), g = clip(Z, a, b): E[g] = aΦa + φa − φb + bQb, E[g²] = a²Φa + (Φb − Φa) −\n// (bφb − aφa) + b²Qb; the mean adds the reference's Edgeworth term (s·γ/6)·(aφa − bφb).\nfn unit_clip(m: f32, v: f32, skewness: f32) -> vec3<f32> {\n if (!(v > 0.0)) { return vec3<f32>(clamp(m, 0.0, 1.0), 0.0, select(0.0, 1.0, m > 0.0 && m < 1.0)); }\n let s = sqrt(v);\n let a = -m / s;\n let b = (1.0 - m) / s;\n if (a < -CLIP_REACH && b > CLIP_REACH) { return vec3<f32>(m, v, 1.0); }\n var pa = 0.0; var da = 0.0;\n if (!(a < -CLIP_REACH)) { pa = pq(a).x; da = phi(a); }\n var pb = 1.0; var qb = 0.0; var db = 0.0;\n if (!(b > CLIP_REACH)) { let p = pq(b); pb = p.x; qb = p.y; db = phi(b); }\n let inside = pb - pa;\n let gamma = clamp(skewness, -1.0, 1.0);\n let aa = a * da;\n let bb = b * db;\n let eg = a * pa + (da - db) + b * qb;\n let eg2 = a * a * pa + inside - (bb - aa) + b * b * qb;\n let normal_mean = m + s * eg;\n var mean = normal_mean;\n var skew_shift = 0.0;\n if (gamma != 0.0) { skew_shift = s * gamma / 6.0 * (aa - bb); mean = normal_mean + skew_shift; }\n // The reference forms E[Y²] − (E[Y] + shift)², so the shift also enters its variance: −shift·(2·E[Y] + shift).\n return vec3<f32>(mean, max(0.0, v * (eg2 - eg * eg) - skew_shift * (2.0 * normal_mean + skew_shift)), inside);\n}\n// Positive Reinhard per channel then the clip to [0, 1]: h(x) = x/(1 + x) for x > 0, else 0. Composite 16-point\n// Gauss–Legendre over [max(0, m − 8.5s), m + 8.5s] in 4 panels, as the reference; the variance is formed about h(m).\nfn reinhard_moments(m: f32, v: f32) -> vec3<f32> {\n if (!(v > 0.0)) {\n if (m > 0.0) { return vec3<f32>(m / (1.0 + m), 0.0, 1.0 / ((1.0 + m) * (1.0 + m))); }\n return vec3<f32>(0.0, 0.0, 0.0);\n }\n let s = sqrt(v);\n // The reference's panels [max(0, m − 8.5s), m + 8.5s] in standardized units z = (x − m)/s, so the node's z is formed\n // without the cancellation x − m: zlo = max(−m/s, −8.5), weight = zhalf·w_k·φ(z_k) (= half·w_k·φ((x − m)/s)/s), x = m + s·z.\n let zlo = max(-m / s, -CLIP_REACH);\n if (!(CLIP_REACH > zlo)) { return vec3<f32>(0.0, 0.0, 0.0); }\n let hm = select(0.0, m / (1.0 + m), m > 0.0);\n var e1 = 0.0; var e2 = 0.0; var ed = 0.0;\n let zwidth = (CLIP_REACH - zlo) / 4.0;\n for (var p = 0u; p < 4u; p = p + 1u) {\n let zc = zlo + (f32(p) + 0.5) * zwidth;\n let zhalf = zwidth / 2.0;\n for (var k = 0u; k < 16u; k = k + 1u) {\n let z = zc + zhalf * aux[${DISPLAY_VIEW_AUX.gaussLegendre}u + k];\n let x = m + s * z;\n let weight = zhalf * aux[${DISPLAY_VIEW_AUX.gaussLegendre + 16}u + k] * phi(z);\n let h = x / (1.0 + x);\n e1 = e1 + weight * h;\n e2 = e2 + weight * (h - hm) * (h - hm);\n ed = ed + weight / ((1.0 + x) * (1.0 + x));\n }\n }\n let shifted = e1 - hm;\n return vec3<f32>(e1, max(0.0, e2 - shifted * shifted), ed);\n}\n\nfn reflect_x(x: i32) -> i32 { if (x < 0) { return -x; } if (x >= i32(params.native_w)) { return 2 * i32(params.native_w) - 2 - x; } return x; }\nfn reflect_y(y: i32) -> i32 { if (y < 0) { return -y; } if (y >= i32(params.native_h)) { return 2 * i32(params.native_h) - 2 - y; } return y; }\nfn channel_of(x: i32, y: i32) -> u32 {\n if ((y & 1) == 0) { return select(1u, 0u, (x & 1) == 0); }\n return select(2u, 1u, (x & 1) == 0);\n}\nfn material_signal(m: u32, c: u32) -> f32 {\n let n = params.nodes;\n var s = 0.0;\n var b = 0.0;\n for (var k = 0u; k < n; k = k + 1u) {\n b = b + spectral_table[c * n + k] * spectral_table[(3u + m) * n + k];\n if ((k & 15u) == 15u) { s = s + b; b = 0.0; }\n }\n return s + b;\n}\n// The expected photo electrons of native site (x, y): Σ_o w_o·scene_value(p_o, c) in offset order (directSite); with a material\n// module scene_value is S_c(m_o), integrated from the material's spectrum (material_signal).\nfn site_electrons(x: i32, y: i32, c: u32) -> f32 {\n var sum = 0.0;\n let fx = f32(x);\n let fy = f32(y);\n for (var o = 0u; o < params.offsets; o = o + 1u) {\n let base = ${DISPLAY_VIEW_AUX.offsets}u + 4u * o;\n let u = (fx + aux[base]) * params.scale_u;\n let v = (fy + aux[base + 1u]) * params.scale_v;\n sum = sum + aux[base + 2u] * scene_value(vec2<f32>(u, v), c);\n }\n return sum;\n}\n@compute @workgroup_size(${DISPLAY_VIEW_WORKGROUP_SIZE})\nfn main(@builtin(global_invocation_id) gid: vec3<u32>, @builtin(num_workgroups) groups: vec3<u32>) {\n let i = gid.x + gid.y * groups.x * ${DISPLAY_VIEW_WORKGROUP_SIZE}u;\n if (i >= params.count) { return; }\n material_uncertain = false;\n let rx = i % params.region_w;\n let ry = params.row0 + i / params.region_w;\n let col = rx * STRIDE;\n let row = (params.columns + ry) * STRIDE;\n let col_first = bitcast<i32>(geometry[col]);\n let nx = bitcast<u32>(geometry[col + 1u]);\n let row_first = bitcast<i32>(geometry[row]);\n let ny = bitcast<u32>(geometry[row + 1u]);\n let margin = i32(params.margin);\n // 2. and 3.: the sites of the footprint plus one site of reach, once each.\n let x0 = col_first + margin - 1;\n let y0 = row_first + margin - 1;\n let window_w = nx + 2u;\n for (var sj = 0u; sj < ny + 2u; sj = sj + 1u) {\n let sy = reflect_y(y0 + i32(sj));\n for (var si = 0u; si < window_w; si = si + 1u) {\n let sx = reflect_x(x0 + i32(si));\n let c = channel_of(sx, sy);\n let e = site_electrons(sx, sy, c) + dark_of(c);\n let kc = k_of(c);\n let mean = kc * e;\n let variance = kc * kc * e + c0_of(c);\n let gap = 1.0 - mean;\n let slot = sj * window_w + si;\n site_third[slot] = kc * kc * kc * e;\n site_clip[slot] = clip_state(mean, SITE_RELATIVE_U * E * mean, variance, SITE_RELATIVE_U * E * variance);\n if (gap > 0.0 && gap * gap > params.reach2 * variance) {\n site_mean[slot] = mean; site_var[slot] = variance; site_bound[slot] = 0.0;\n } else {\n let clipped = upper_clip(mean, variance, 1.0);\n site_mean[slot] = clipped.x; site_var[slot] = clipped.y; site_bound[slot] = sqrt(variance);\n }\n }\n }\n // B_c of the footprint from the host's axis sums (each over its scale squared): red, green, blue.\n let xb_even = geometry[col + 8u]; let xb_odd = geometry[col + 9u];\n let xpp_even = geometry[col + 10u]; let xpp_odd = geometry[col + 11u];\n let xqq_even = geometry[col + 12u]; let xqq_odd = geometry[col + 13u];\n let xpq_even = geometry[col + 14u]; let xpq_odd = geometry[col + 15u];\n let yb_even = geometry[row + 8u]; let yb_odd = geometry[row + 9u];\n let ypp_even = geometry[row + 10u]; let ypp_odd = geometry[row + 11u];\n let yqq_even = geometry[row + 12u]; let yqq_odd = geometry[row + 13u];\n let ypq_even = geometry[row + 14u]; let ypq_odd = geometry[row + 15u];\n let b0 = xb_even * yb_even;\n let b1 = (xpp_odd * ypp_even + xqq_odd * ypp_even + xpp_odd * yqq_even + 2.0 * xpq_odd * ypp_even + 2.0 * xpp_odd * ypq_even + 2.0 * xpq_odd * ypq_even) +\n (xpp_even * ypp_odd + xqq_even * ypp_odd + xpp_even * yqq_odd + 2.0 * xpq_even * ypp_odd + 2.0 * xpp_even * ypq_odd + 2.0 * xpq_even * ypq_odd);\n let b2 = xb_odd * yb_odd;\n let reinhard = params.tone == 1u;\n var s0 = 0.0; var s1 = 0.0; var s2 = 0.0;\n var c00 = 0.0; var c01 = 0.0; var c02 = 0.0; var c11 = 0.0; var c12 = 0.0; var c22 = 0.0;\n var r0 = 0.0; var r1 = 0.0; var r2 = 0.0;\n var bound_mean = 0.0; var bound_var = 0.0;\n // #533: the saturated real pixels (bit j·nx + i) and whether any real pixel is undecided.\n var mask0 = 0u; var mask1 = 0u; var undecided = false;\n // 4. and 5.: every real pixel of the footprint with its overlap weight.\n for (var j = 0u; j < ny; j = j + 1u) {\n let ay = geometry[row + 2u + j];\n for (var ii = 0u; ii < nx; ii = ii + 1u) {\n let aj = geometry[col + 2u + ii] * ay;\n let x = col_first + i32(ii) + margin;\n let y = row_first + i32(j) + margin;\n let phase = u32(y & 1) * 2u + u32(x & 1);\n var cm: array<f32, 3>; var cvv: array<f32, 3>; var cth: array<f32, 3>; var csv: array<f32, 3>; var cb: array<f32, 3>;\n var clipped = false; var near_white = false;\n for (var c = 0u; c < 3u; c = c + 1u) {\n var mean = 0.0; var variance = 0.0; var third = 0.0; var bnd = 0.0;\n let taps = ${DISPLAY_VIEW_AUX.taps}u + (phase * 3u + c) * 16u;\n for (var t = 0u; t < 4u; t = t + 1u) {\n let w = aux[taps + 4u * t + 2u];\n let slot = u32((i32(j) + 1 + i32(aux[taps + 4u * t + 1u])) * i32(window_w) + i32(ii) + 1 + i32(aux[taps + 4u * t]));\n mean = mean + w * site_mean[slot];\n variance = variance + w * w * site_var[slot];\n third = third + w * w * w * site_third[slot];\n bnd = max(bnd, select(0.0, site_bound[slot], w != 0.0));\n if (w != 0.0) { if (site_clip[slot] == 1u) { clipped = true; } else if (site_clip[slot] == 2u) { near_white = true; } }\n }\n cm[c] = mean; cvv[c] = variance; cth[c] = third; cb[c] = bnd;\n csv[c] = variance * aux[${DISPLAY_VIEW_AUX.inverseW2}u + phase * 3u + c];\n }\n if (clipped) {\n let bit = j * nx + ii;\n if (bit < 32u) { mask0 = mask0 | (1u << bit); } else { mask1 = mask1 | (1u << (bit - 32u)); }\n } else if (near_white) { undecided = true; }\n // #593: reconstruct within the blend's reach integrates the whole chain below; out of its reach it is the unclipped white balance.\n var cp_chain_run = false;\n if (cp_on() && cp_reconstruct()) {\n let reach = cp_reconstruct_reach(vec3<f32>(cm[0], cm[1], cm[2]), vec3<f32>(cvv[0], cvv[1], cvv[2]));\n if (reach == 2u) { material_uncertain = true; }\n cp_chain_run = reach >= 1u;\n }\n let cp_unclipped = cp_on() && cp_reconstruct();\n // White balance and the highlight clip at the smallest gain: bm, bv, bs (slope), with the clip's bound terms.\n var bm: array<f32, 3>; var bv: array<f32, 3>; var bs: array<f32, 3>; var bbm: array<f32, 3>; var bbv: array<f32, 3>;\n for (var c = 0u; c < 3u; c = c + 1u) {\n let gc = g_of(c);\n let um = gc * cm[c];\n let uv = gc * gc * cvv[c];\n let gap = params.clip_level - um;\n bbm[c] = gc * CLIP_MEAN_U * cb[c];\n bbv[c] = gc * gc * CLIP_VARIANCE_U * cb[c] * cb[c];\n if (cp_unclipped || (gap > 0.0 && gap * gap > params.reach2 * uv)) { bm[c] = um; bv[c] = uv; bs[c] = gc; }\n else {\n let clipped = upper_clip(um, uv, params.clip_level);\n bm[c] = clipped.x; bv[c] = clipped.y; bs[c] = gc * clipped.z;\n bbm[c] = bbm[c] + CLIP_MEAN_U * sqrt(uv);\n bbv[c] = bbv[c] + CLIP_VARIANCE_U * uv;\n }\n }\n // Colour matrix, then the rendering of each component (tone curve, clip to [0, 1]).\n var hm: array<f32, 3>; var hv: array<f32, 3>; var hs: array<f32, 3>; var hbm: array<f32, 3>; var hbv: array<f32, 3>;\n for (var comp = 0u; comp < 3u; comp = comp + 1u) {\n let r0m = m_of(comp, 0u); let r1m = m_of(comp, 1u); let r2m = m_of(comp, 2u);\n let mean = r0m * bm[0] + r1m * bm[1] + r2m * bm[2];\n let variance = r0m * r0m * bv[0] + r1m * r1m * bv[1] + r2m * r2m * bv[2];\n var bm_c = abs(r0m) * bbm[0] + abs(r1m) * bbm[1] + abs(r2m) * bbm[2];\n var bv_c = r0m * r0m * bbv[0] + r1m * r1m * bbv[1] + r2m * r2m * bbv[2];\n if (!reinhard && mean > 0.0 && mean < 1.0 && mean * mean > params.reach2 * variance && (1.0 - mean) * (1.0 - mean) > params.reach2 * variance) {\n hm[comp] = mean; hv[comp] = variance; hs[comp] = 1.0;\n } else if (reinhard) {\n let moments = reinhard_moments(mean, variance);\n hm[comp] = moments.x; hv[comp] = moments.y; hs[comp] = moments.z;\n bm_c = bm_c + 2.0 * CLIP_MEAN_U * sqrt(variance);\n bv_c = bv_c + 2.0 * CLIP_VARIANCE_U * variance;\n } else {\n // κ₃ of the component: Σ_c (M_comp,c·Γ_c)³·Σ_t w_t³·κ₃(site) (the sites of one channel share the coefficient).\n let k0 = r0m * bs[0]; let k1 = r1m * bs[1]; let k2 = r2m * bs[2];\n let third = k0 * k0 * k0 * cth[0] + k1 * k1 * k1 * cth[1] + k2 * k2 * k2 * cth[2];\n let skew = select(0.0, third / (variance * sqrt(variance)), variance > 0.0);\n let moments = unit_clip(mean, variance, skew);\n hm[comp] = moments.x; hv[comp] = moments.y; hs[comp] = moments.z;\n bm_c = bm_c + 2.0 * CLIP_MEAN_U * sqrt(variance);\n bv_c = bv_c + 2.0 * CLIP_VARIANCE_U * variance;\n }\n hbm[comp] = bm_c; hbv[comp] = bv_c;\n }\n // #593, #601: the coupled steps (wgsl-display-view-coupled.ts): a luminance tone curve by conditioning on luminance, and the\n // chain's 3-D rule for reconstruct and the desaturation; their slopes ∂out/∂c (camera channels) replace the per-component ones.\n var jm = array<vec3<f32>, 3>(vec3<f32>(0.0), vec3<f32>(0.0), vec3<f32>(0.0));\n var ju = 0.0;\n var cp_used = false;\n if (cp_on()) {\n if (!cp_chain_run && cp_luminance()) {\n var mu = vec3<f32>(0.0); var dmu = vec3<f32>(0.0); var dsv = vec3<f32>(0.0);\n var srow = array<vec3<f32>, 3>(vec3<f32>(0.0), vec3<f32>(0.0), vec3<f32>(0.0));\n var mm = array<vec3<f32>, 3>(vec3<f32>(params.m00, params.m01, params.m02), vec3<f32>(params.m10, params.m11, params.m12), vec3<f32>(params.m20, params.m21, params.m22));\n for (var r = 0u; r < 3u; r = r + 1u) {\n mu[r] = mm[r][0] * bm[0] + mm[r][1] * bm[1] + mm[r][2] * bm[2];\n dmu[r] = (abs(mm[r][0]) * bbm[0] + abs(mm[r][1]) * bbm[1] + abs(mm[r][2]) * bbm[2]) * E;\n dsv[r] = (mm[r][0] * mm[r][0] * bbv[0] + mm[r][1] * mm[r][1] * bbv[1] + mm[r][2] * mm[r][2] * bbv[2]) * E;\n for (var q = 0u; q < 3u; q = q + 1u) { srow[r][q] = mm[r][0] * mm[q][0] * bv[0] + mm[r][1] * mm[q][1] * bv[1] + mm[r][2] * mm[q][2] * bv[2]; }\n }\n let t = cp_tone(mu, srow[0], srow[1], srow[2], dmu, dsv);\n if (t.flag) { material_uncertain = true; }\n if (cp_desaturate() && t.top) { cp_chain_run = true; }\n else {\n let rows = array<vec3<f32>, 3>(t.a0, t.a1, t.a2);\n for (var comp = 0u; comp < 3u; comp = comp + 1u) {\n hm[comp] = t.hm[comp]; hv[comp] = t.hv[comp]; hbm[comp] = t.bm[comp] / E; hbv[comp] = t.bv[comp] / E;\n for (var c = 0u; c < 3u; c = c + 1u) { jm[comp][c] = (rows[comp].x * m_of(0u, c) + rows[comp].y * m_of(1u, c) + rows[comp].z * m_of(2u, c)) * bs[c]; }\n }\n ju = t.ju / E; cp_used = true;\n }\n } else if (!cp_chain_run && cp_desaturate() && params.tone != 1u) {\n // A component reaching 1 within reach is desaturated with the others (the reference's test; undecided: recompute).\n for (var comp = 0u; comp < 3u; comp = comp + 1u) {\n let top = hm[comp] + CLIP_REACH * sqrt(hv[comp]);\n if (hm[comp] > 0.0 && top >= 0.999) { cp_chain_run = true; }\n if (hm[comp] > 0.0 && hm[comp] - 2.0 * hbm[comp] * E < 0.999 && abs(top - 0.999) <= 2.0 * (hbm[comp] * E + CLIP_REACH * min(sqrt(hbv[comp] * E), hbv[comp] * E / (2.0 * sqrt(hv[comp])))) + 64.0 * E) { material_uncertain = true; }\n }\n }\n if (cp_chain_run) {\n let dcm = vec3<f32>(CLIP_MEAN_U * cb[0], CLIP_MEAN_U * cb[1], CLIP_MEAN_U * cb[2]) * E;\n let dcv = vec3<f32>(CLIP_VARIANCE_U * cb[0] * cb[0], CLIP_VARIANCE_U * cb[1] * cb[1], CLIP_VARIANCE_U * cb[2] * cb[2]) * E;\n let t = cp_chain(vec3<f32>(cm[0], cm[1], cm[2]), cvv[0], 0.0, 0.0, cvv[1], 0.0, cvv[2], dcm, dcv);\n if (t.flag) { material_uncertain = true; }\n jm[0] = t.a0; jm[1] = t.a1; jm[2] = t.a2;\n for (var comp = 0u; comp < 3u; comp = comp + 1u) { hm[comp] = t.hm[comp]; hv[comp] = t.hv[comp]; hbm[comp] = t.bm[comp] / E; hbv[comp] = t.bv[comp] / E; }\n ju = t.ju / E; cp_used = true;\n }\n }\n s0 = s0 + aj * hm[0]; s1 = s1 + aj * hm[1]; s2 = s2 + aj * hm[2];\n // Linear (Stein) part with B_c·σ_c², and the pixel's own linear variance for the residual.\n var l0 = 0.0; var l1 = 0.0; var l2 = 0.0;\n var lb0 = 0.0; var lb1 = 0.0; var lb2 = 0.0;\n for (var c = 0u; c < 3u; c = c + 1u) {\n var a0 = hs[0] * m_of(0u, c) * bs[c];\n var a1 = hs[1] * m_of(1u, c) * bs[c];\n var a2 = hs[2] * m_of(2u, c) * bs[c];\n if (cp_used) { a0 = jm[0][c]; a1 = jm[1][c]; a2 = jm[2][c]; }\n var bc = b0; if (c == 1u) { bc = b1; } if (c == 2u) { bc = b2; }\n let wgt = aj * bc * csv[c];\n c00 = c00 + wgt * a0 * a0; c01 = c01 + wgt * a0 * a1; c02 = c02 + wgt * a0 * a2;\n c11 = c11 + wgt * a1 * a1; c12 = c12 + wgt * a1 * a2; c22 = c22 + wgt * a2 * a2;\n l0 = l0 + a0 * a0 * cvv[c]; l1 = l1 + a1 * a1 * cvv[c]; l2 = l2 + a2 * a2 * cvv[c];\n // The clip bound of each channel's variance enters the covariance through a_j·B_c·(Δσ_c²/Σw²)·a_i·a_j and the\n // residual's linear prediction through a²·Δσ_c².\n lb0 = lb0 + (a0 * a0) * (bbv[c] + 2.0 * ju * cvv[c]); lb1 = lb1 + (a1 * a1) * (bbv[c] + 2.0 * ju * cvv[c]); lb2 = lb2 + (a2 * a2) * (bbv[c] + 2.0 * ju * cvv[c]);\n bound_var = bound_var + aj * bc * ((bbv[c] + 2.0 * ju * cvv[c]) * aux[${DISPLAY_VIEW_AUX.inverseW2}u + phase * 3u + c]) * max(a0 * a0, max(a1 * a1, a2 * a2));\n }\n r0 = r0 + aj * aj * max(0.0, hv[0] - l0);\n r1 = r1 + aj * aj * max(0.0, hv[1] - l1);\n r2 = r2 + aj * aj * max(0.0, hv[2] - l2);\n bound_mean = bound_mean + aj * max(hbm[0], max(hbm[1], hbm[2]));\n bound_var = bound_var + aj * aj * (max(hbv[0], max(hbv[1], hbv[2])) + max(lb0, max(lb1, lb2)));\n }\n }\n let o = i * ${DISPLAY_VIEW_OUTPUT_FLOATS}u;\n out[o] = s0; out[o + 1u] = s1; out[o + 2u] = s2;\n out[o + 3u] = c00 + r0; out[o + 4u] = c11 + r1; out[o + 5u] = c22 + r2;\n out[o + 6u] = c01; out[o + 7u] = c02; out[o + 8u] = c12;\n out[o + 9u] = bound_mean * E; out[o + 10u] = bound_var * E;\n flags[3u * i] = select(0u, 1u, material_uncertain) | select(0u, 2u, undecided);\n flags[3u * i + 1u] = mask0;\n flags[3u * i + 2u] = mask1;\n}\n`;\n\n/**\n * The channel signal of the material a material module's `material_at` gives (the kernel's `scene_value`), integrated from its\n * spectrum when it changes (2.21.0: signals are integrated from the material spectrum per site).\n */\nexport const DISPLAY_VIEW_MATERIAL_SCENE_VALUE_WGSL = /* wgsl */ `\nvar<private> scene_m: u32 = 0xffffffffu;\nvar<private> scene_c: u32 = 0u;\nvar<private> scene_s: f32 = 0.0;\nfn scene_value(p: vec2<f32>, c: u32) -> f32 {\n let m = material_at(p);\n if (m != scene_m || c != scene_c) { scene_s = material_signal(m, c); scene_m = m; scene_c = c; }\n return scene_s;\n}\n`;\n/** The full shader: the kernel plus a material module (see `DISPLAY_VIEW_SPEED_KERNEL_WGSL`), and the table adapter unless the module defines `scene_value`. */\nexport function assembleDisplayViewSpeedWgsl(materialModuleWgsl: string, coupledWgsl: string = DISPLAY_VIEW_COUPLED_STUB_WGSL): string {\n const adapter = /\\bfn scene_value\\(/u.test(materialModuleWgsl) ? \"\" : DISPLAY_VIEW_MATERIAL_SCENE_VALUE_WGSL;\n return DISPLAY_VIEW_SPEED_KERNEL_WGSL + \"\\n\" + materialModuleWgsl + \"\\n\" + adapter + \"\\n\" + coupledWgsl;\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -212,7 +212,7 @@ export { calculateSensorApertureRays, type CalculateSensorApertureRaysInput, typ
|
|
|
212
212
|
export { SIMULATE_CAPTURE_FACADE_VERSION, SIMULATE_CAPTURE_DEFAULT_ILLUMINANCE_LUX, SIMULATE_CAPTURE_COST_OPTIONS, SIMULATE_CAPTURE_METERING_MODES, simulateCapture, type SimulateCaptureOptions, type SimulateCaptureResult, type SimulateCaptureAssumption, type SimulateCaptureProgress, type SimulateCaptureExposureMode, type SimulateCaptureMetering, type SimulateCaptureAutoIsoAfterMaximum, type SimulateCaptureAutoIsoReport, type SimulateCaptureAutomaticSlowestShutterOptions, type SimulateCaptureAutomaticSlowestShutterReport, type SimulateCaptureOutputFormat, type SimulateCaptureWhiteBalance, type SimulateCaptureColorEncoding, type SimulateCaptureDemosaic, type SimulateCaptureBorderHandling, type SimulateCaptureLensDistortion, type SimulateCaptureMotion, type SimulateCaptureSensorAntiAliasing, type SimulateCaptureCostOption, type SimulateCapturePixelAperture, SIMULATE_CAPTURE_BOX_APERTURE_DEFAULT_SAMPLES, SIMULATE_CAPTURE_FAST_OPTIONS, type SimulateCaptureFastOption, type SimulateCaptureFastReport, type SimulateCaptureDemosaicRecord, type SimulateCaptureLensCatalogueRecord, type SimulateCaptureSharpening, type SimulateCaptureDiffractionCorrection, type SimulateCaptureLensCorrections, type SimulateCaptureDetailDiagnostics, simulateIdealReference, type IdealReferenceResult, serializeSimulatedCaptureDngFromParts, type SimulateCaptureDngPart, type SimulateDisplayViewOptions, type DisplayViewResult, type DisplayViewHighlightDiagnostics, SIMULATE_DISPLAY_VIEW_DEFAULT_SAMPLES_PER_AXIS } from "./facade/simulate-capture.js";
|
|
213
213
|
export { simulateCaptureFromParts } from "./facade/develop-joined-parts.js";
|
|
214
214
|
export { EXPOSURE_BUILD_UP_MAXIMUM_FRACTIONS, EXPOSURE_BUILD_UP_STREAM_BASE, simulateExposureBuildUp, type SimulateExposureBuildUpFrame, type SimulateExposureBuildUpOptions, type SimulateExposureBuildUpResult } from "./facade/exposure-build-up.js";
|
|
215
|
-
export type { SimulateCaptureSensorCharacteristics, SimulateCaptureSensorReport, SimulateCaptureNoiseComponents } from "./sensor/sensor-characteristics.js";
|
|
215
|
+
export type { SimulateCaptureSensorCharacteristics, SimulateCaptureSensorReport, SimulateCaptureNoiseComponents, SimulateCaptureNativeSensorReport, SimulateCaptureMidGreyFigure } from "./sensor/sensor-characteristics.js";
|
|
216
216
|
export { SENSOR_PROFILES, SENSOR_PROFILE_IDS, resolveSensorProfile } from "./equipment/sensor-profiles.js";
|
|
217
217
|
export { SENSOR_PROFILE_ISO_ANCHOR, type SensorProfile, type SensorProfileValueKind } from "./equipment/sensor-profile-body.js";
|
|
218
218
|
export type { SimulateCaptureSubjectMotion } from "./motion/subject-motion.js";
|
|
@@ -223,6 +223,7 @@ export { GENERIC_THIRD_STOP_ISO_SETTINGS, GENERIC_THIRD_STOP_SHUTTER_SECONDS, GE
|
|
|
223
223
|
export { GENERIC_PRIME_EQUIVALENT_FOCAL_LENGTHS_MM, GENERIC_PRIME_THIRD_STOP_F_NUMBERS, GENERIC_PRIME_MINIMUM_FOCUS, resolveGenericPrimeLens, calculateGenericPrimeMinimumFocusDistanceM, type GenericPrimeLens, type GenericPrimeEquivalentFocalLengthMm } from "./equipment/generic-prime-lenses.js";
|
|
224
224
|
export { IDEAL_LENS_LIMITS } from "./equipment/ideal-lens.js";
|
|
225
225
|
export { GENERIC_LENS_CATALOGUE, GENERIC_LENS_IDS, GENERIC_LENS_SET_BASELINES, resolveGenericLens, simulateGenericLensFocusError, type GenericLensCatalogueEntry, type GenericLensSet, type GenericLensKind, type GenericLensCharacterValues, type GenericLensAdjustments, type GenericLensCharacter, type ResolvedGenericLens, type ResolveGenericLensInput, type SimulateGenericLensFocusErrorInput, type GenericLensFocusError } from "./equipment/generic-lens-catalogue.js";
|
|
226
|
+
export { calculateCameraChannelResponse, type CalculateCameraChannelResponseInput, type CameraChannelResponse } from "./output/camera-channel-response.js";
|
|
226
227
|
export { calculateChannelEffectiveDispersion, createGenericLensCorrectionProfile, GENERIC_LENS_CORRECTION_CHANNEL_WAVELENGTHS_NM, type CalculateChannelEffectiveDispersionInput, type ChannelDispersion, type CreateGenericLensCorrectionProfileInput } from "./output/generic-lens-corrections.js";
|
|
227
228
|
export { calculateLateralColorFringe, type CalculateLateralColorFringeInput, type LateralColorFringe, type LateralColorDisplacement } from "./optics/generic-lens-lateral-color.js";
|
|
228
229
|
export { calculateChartFraming, calculateSubjectDistanceForFraming, type CalculateChartFramingInput, type CalculateSubjectDistanceForFramingInput, type ChartFraming, type SubjectFraming, type SubjectFramingFit } from "./facade/subject-framing.js";
|
|
@@ -231,14 +232,21 @@ export { COLOR_PATCH_SET_ID, COLOR_PATCH_SET_VERSION, COLOR_PATCH_IDS, COLOR_PAT
|
|
|
231
232
|
export { REPRESENTATIVE_LIGHT_SOURCE_SET_ID, REPRESENTATIVE_LIGHT_SOURCE_SET_VERSION, REPRESENTATIVE_LIGHT_SOURCE_IDS, REPRESENTATIVE_LIGHT_SOURCE_WAVELENGTH_RANGE_NANOMETERS, getRepresentativeLightSourceSet, createRepresentativeLightSourceSpectrum, createRepresentativeLightSourceIlluminant, type RepresentativeLightSource, type RepresentativeLightSourceBand, type RepresentativeLightSourceId, type RepresentativeLightSourceSet } from "./facade/representative-light-sources.js";
|
|
232
233
|
export { PHOTOPIC_MAXIMUM_LUMINOUS_EFFICACY_LM_PER_W, resolveCaptureIlluminant, createPlanarSceneRadianceProvider, CHART_SIZE_DEFAULT_SURROUND_REFLECTANCE, CALLER_MATERIAL_SCENE_MAX_MATERIALS, type ChartSizeOption, type CaptureIlluminant, type ResolvedCaptureIlluminant, type CallerReflectanceScene, type CallerRadianceScene, type CallerMaterialScene, type ScenePlanePoint, type SceneMaterialPoint, type PlanarSceneRadianceProvider, type ImagePlaneScene, type ImagePlaneImage } from "./facade/scene-radiance.js";
|
|
233
234
|
export { prepareImagePlaneScenes } from "./facade/image-plane-enable.js";
|
|
235
|
+
export { prepareQualityPaths } from "./facade/quality-paths.js";
|
|
234
236
|
export type { MixedIllumination, MixedIlluminationBlend, MixedIlluminationPoint, MixedIlluminationPointSource, MixedIlluminationSource } from "./facade/mixed-illumination.js";
|
|
235
237
|
export { CHART_RADIANCE_BATCH_SCHEMA_VERSION, CHART_RADIANCE_BATCH_LIMITS, calculateChartRadianceBatchPlan, calculateChartRadianceBatch, mapEnvironmentDirectionsToChartPoints, type ChartRadianceBatchInput, type ChartRadianceBatchPlan } from "./facade/chart-radiance-batch.js";
|
|
236
238
|
export { resolveChartMaterialLayers, CHART_MASK_INDEX_GRAIN, CHART_MATERIAL_LAYER_LIMITS, type ChartMaterialLayerScene, type ChartMaskLayer, type ChartMaskShape, type ChartMaskPolygon, type ChartMaskAnnulus, type ResolvedChartMaterialLayers, type ResolvedChartMaskLayer, type ResolvedChartMaskShape } from "./facade/chart-material-layers.js";
|
|
237
239
|
export { EXPORT_JPEG_ENCODER_ID } from "./capture/export-jpeg.js";
|
|
238
|
-
export { DNG_IMPORT_SCHEMA_VERSION, DNG_IMPORT_LIMITS, parseDngRawImage } from "./capture/dng-import.js";
|
|
240
|
+
export { DNG_IMPORT_SCHEMA_VERSION, DNG_IMPORT_LIMITS, parseDngRawImage, importDngRawImage } from "./capture/dng-import.js";
|
|
241
|
+
export { createJxlOxideDngDecoder, type DngJpegXlDecoder, type JxlOxideModule } from "./capture/jpeg-xl-tiles.js";
|
|
242
|
+
export { parseDngOpcodeList, applyDngOpcodes, type DngOpcode, type DngOpcodeArea, type DngOpcodeParameters, type DngStageImage, type ApplyDngOpcodesOptions } from "./capture/dng-opcodes.js";
|
|
243
|
+
export { developDngStageImage, type DevelopDngStageImageOptions, type DngStageImageResult } from "./capture/dng-stage-image.js";
|
|
244
|
+
export { parseDngProfileGainTableMap, parseDngRgbTables, applyDngProfileGainTableMap, applyDngRgbTables, type DngProfileGainTableMap, type DngRgbTable, type DngRgbTables, type DngRgbImage, type ApplyDngProfileGainTableMapInput, type ApplyDngRgbTablesInput } from "./capture/dng-profile-maps.js";
|
|
245
|
+
export { C2PA_ALGORITHMIC_MEDIA_SOURCE_TYPE, C2PA_MANIFEST_STORE_MAXIMUM_BYTES, bindC2paManifestStore, setC2paManifestStore, calculateC2paDataHash, parseC2paManifestStore, type C2paFoundManifestStore, type ParseC2paManifestStoreInput, type C2paByteRange, type C2paHardBinding, type C2paBoundFile, type C2paDataHash, type BindC2paManifestStoreInput, type SetC2paManifestStoreInput, type CalculateC2paDataHashInput } from "./capture/c2pa-embed.js";
|
|
239
246
|
export { NATIVE_RAW_DNG_SCHEMA_VERSION, serializeNativeRawDng, type SerializeNativeRawDngInput, type NativeRawDng, type NativeRawDngChannelNoise } from "./capture/native-raw-dng.js";
|
|
240
|
-
export type { DngImportInput, ImportedDngRaw, ImportedDngCfa, ImportedDngBlackLevel, ImportedDngRect } from "./capture/dng-import.js";
|
|
247
|
+
export type { DngImportInput, DngImportAsyncInput, ImportedDngRaw, ImportedDngCfa, ImportedDngBlackLevel, ImportedDngRect, ImportedDngSemanticMask } from "./capture/dng-import.js";
|
|
241
248
|
export { parseLosslessJpeg, type LosslessJpegImage, type LosslessJpegLimits } from "./capture/lossless-jpeg.js";
|
|
249
|
+
export { parseLossyJpeg, type LossyJpegImage, type LossyJpegLimits } from "./capture/lossy-jpeg.js";
|
|
242
250
|
export { PNG_ENCODER_ID, PNG_ENCODER_LIMITS, serializePngImage } from "./output/png-encoder.js";
|
|
243
251
|
export type { PngEncodeInput, PngColourEncoding, PngCicpPrimaries, PngCicpTransfer, PngMasteringDisplay, PngContentLightLevel } from "./output/png-encoder.js";
|
|
244
252
|
export { SIMULATE_CAPTURE_FAST_METHODS, type SimulateCaptureFastMethod } from "./facade/fast-methods.js";
|
package/dist/index.js
CHANGED
|
@@ -197,6 +197,7 @@ export { GENERIC_THIRD_STOP_ISO_SETTINGS, GENERIC_THIRD_STOP_SHUTTER_SECONDS, GE
|
|
|
197
197
|
export { GENERIC_PRIME_EQUIVALENT_FOCAL_LENGTHS_MM, GENERIC_PRIME_THIRD_STOP_F_NUMBERS, GENERIC_PRIME_MINIMUM_FOCUS, resolveGenericPrimeLens, calculateGenericPrimeMinimumFocusDistanceM } from "./equipment/generic-prime-lenses.js";
|
|
198
198
|
export { IDEAL_LENS_LIMITS } from "./equipment/ideal-lens.js";
|
|
199
199
|
export { GENERIC_LENS_CATALOGUE, GENERIC_LENS_IDS, GENERIC_LENS_SET_BASELINES, resolveGenericLens, simulateGenericLensFocusError } from "./equipment/generic-lens-catalogue.js";
|
|
200
|
+
export { calculateCameraChannelResponse } from "./output/camera-channel-response.js";
|
|
200
201
|
export { calculateChannelEffectiveDispersion, createGenericLensCorrectionProfile, GENERIC_LENS_CORRECTION_CHANNEL_WAVELENGTHS_NM } from "./output/generic-lens-corrections.js";
|
|
201
202
|
export { calculateLateralColorFringe } from "./optics/generic-lens-lateral-color.js";
|
|
202
203
|
export { calculateChartFraming, calculateSubjectDistanceForFraming } from "./facade/subject-framing.js";
|
|
@@ -205,12 +206,19 @@ export { COLOR_PATCH_SET_ID, COLOR_PATCH_SET_VERSION, COLOR_PATCH_IDS, COLOR_PAT
|
|
|
205
206
|
export { REPRESENTATIVE_LIGHT_SOURCE_SET_ID, REPRESENTATIVE_LIGHT_SOURCE_SET_VERSION, REPRESENTATIVE_LIGHT_SOURCE_IDS, REPRESENTATIVE_LIGHT_SOURCE_WAVELENGTH_RANGE_NANOMETERS, getRepresentativeLightSourceSet, createRepresentativeLightSourceSpectrum, createRepresentativeLightSourceIlluminant } from "./facade/representative-light-sources.js";
|
|
206
207
|
export { PHOTOPIC_MAXIMUM_LUMINOUS_EFFICACY_LM_PER_W, resolveCaptureIlluminant, createPlanarSceneRadianceProvider, CHART_SIZE_DEFAULT_SURROUND_REFLECTANCE, CALLER_MATERIAL_SCENE_MAX_MATERIALS } from "./facade/scene-radiance.js";
|
|
207
208
|
export { prepareImagePlaneScenes } from "./facade/image-plane-enable.js";
|
|
209
|
+
export { prepareQualityPaths } from "./facade/quality-paths.js";
|
|
208
210
|
export { CHART_RADIANCE_BATCH_SCHEMA_VERSION, CHART_RADIANCE_BATCH_LIMITS, calculateChartRadianceBatchPlan, calculateChartRadianceBatch, mapEnvironmentDirectionsToChartPoints } from "./facade/chart-radiance-batch.js";
|
|
209
211
|
export { resolveChartMaterialLayers, CHART_MASK_INDEX_GRAIN, CHART_MATERIAL_LAYER_LIMITS } from "./facade/chart-material-layers.js";
|
|
210
212
|
export { EXPORT_JPEG_ENCODER_ID } from "./capture/export-jpeg.js";
|
|
211
|
-
export { DNG_IMPORT_SCHEMA_VERSION, DNG_IMPORT_LIMITS, parseDngRawImage } from "./capture/dng-import.js";
|
|
213
|
+
export { DNG_IMPORT_SCHEMA_VERSION, DNG_IMPORT_LIMITS, parseDngRawImage, importDngRawImage } from "./capture/dng-import.js";
|
|
214
|
+
export { createJxlOxideDngDecoder } from "./capture/jpeg-xl-tiles.js";
|
|
215
|
+
export { parseDngOpcodeList, applyDngOpcodes } from "./capture/dng-opcodes.js";
|
|
216
|
+
export { developDngStageImage } from "./capture/dng-stage-image.js";
|
|
217
|
+
export { parseDngProfileGainTableMap, parseDngRgbTables, applyDngProfileGainTableMap, applyDngRgbTables } from "./capture/dng-profile-maps.js";
|
|
218
|
+
export { C2PA_ALGORITHMIC_MEDIA_SOURCE_TYPE, C2PA_MANIFEST_STORE_MAXIMUM_BYTES, bindC2paManifestStore, setC2paManifestStore, calculateC2paDataHash, parseC2paManifestStore } from "./capture/c2pa-embed.js";
|
|
212
219
|
export { NATIVE_RAW_DNG_SCHEMA_VERSION, serializeNativeRawDng } from "./capture/native-raw-dng.js";
|
|
213
220
|
export { parseLosslessJpeg } from "./capture/lossless-jpeg.js";
|
|
221
|
+
export { parseLossyJpeg } from "./capture/lossy-jpeg.js";
|
|
214
222
|
export { PNG_ENCODER_ID, PNG_ENCODER_LIMITS, serializePngImage } from "./output/png-encoder.js";
|
|
215
223
|
export { SIMULATE_CAPTURE_FAST_METHODS } from "./facade/fast-methods.js";
|
|
216
224
|
export { DETAIL_LIMIT_LIMITS, calculateDetailLimit } from "./optics/detail-limit.js";
|