@photivra/engine 2.18.0 → 2.19.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 +68 -1
- package/CITATION.cff +1 -1
- package/README.md +6 -6
- package/SECURITY.md +1 -1
- package/dist/capture/focus-control.js +2 -75
- package/dist/capture/focus-control.js.map +1 -1
- package/dist/capture/native-environment-lean.d.ts +1 -0
- package/dist/capture/native-environment-lean.js +1 -1
- package/dist/capture/native-environment-lean.js.map +1 -1
- package/dist/capture/native-environment-optical-stage.d.ts +1 -0
- package/dist/capture/native-environment-optical-stage.js +2 -5
- package/dist/capture/native-environment-optical-stage.js.map +1 -1
- package/dist/capture/native-environment-raw.js +1 -5
- package/dist/capture/native-environment-raw.js.map +1 -1
- package/dist/capture/release-sequence.js +2 -47
- package/dist/capture/release-sequence.js.map +1 -1
- package/dist/color/white-balance.d.ts +2 -0
- package/dist/color/white-balance.js +3 -56
- package/dist/color/white-balance.js.map +1 -1
- package/dist/composition/image-formation-plan.d.ts +1 -0
- package/dist/composition/image-formation-plan.js +3 -49
- package/dist/composition/image-formation-plan.js.map +1 -1
- package/dist/core/evidence-provenance.js +1 -16
- package/dist/core/evidence-provenance.js.map +1 -1
- package/dist/core/record-validation.d.ts +54 -0
- package/dist/core/record-validation.js +176 -0
- package/dist/core/record-validation.js.map +1 -1
- package/dist/core/scientific-assurance.js +1 -18
- package/dist/core/scientific-assurance.js.map +1 -1
- package/dist/core/shared-helpers.d.ts +33 -0
- package/dist/core/shared-helpers.js +34 -0
- package/dist/core/shared-helpers.js.map +1 -0
- package/dist/core/spectral-composition.js +1 -36
- package/dist/core/spectral-composition.js.map +1 -1
- package/dist/core/spectral.js +1 -19
- package/dist/core/spectral.js.map +1 -1
- 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/equipment/exposure-capabilities.d.ts +1 -0
- package/dist/equipment/exposure-capabilities.js +2 -36
- package/dist/equipment/exposure-capabilities.js.map +1 -1
- package/dist/equipment/iso-capabilities.js +2 -49
- package/dist/equipment/iso-capabilities.js.map +1 -1
- package/dist/equipment/metering-capabilities.js +1 -26
- package/dist/equipment/metering-capabilities.js.map +1 -1
- package/dist/equipment/release-capabilities.js +1 -53
- package/dist/equipment/release-capabilities.js.map +1 -1
- package/dist/exposure/auto-iso-slowest-shutter.js +1 -7
- package/dist/exposure/auto-iso-slowest-shutter.js.map +1 -1
- package/dist/exposure/exposure-duration-control.js +1 -16
- package/dist/exposure/exposure-duration-control.js.map +1 -1
- package/dist/exposure/exposure-mode-resolver.js +1 -17
- package/dist/exposure/exposure-mode-resolver.js.map +1 -1
- package/dist/exposure/filtered-exposure-time.d.ts +93 -0
- package/dist/exposure/filtered-exposure-time.js +129 -0
- package/dist/exposure/filtered-exposure-time.js.map +1 -0
- package/dist/exposure/flash-ttl.d.ts +1 -0
- package/dist/exposure/flash-ttl.js +1 -1
- package/dist/exposure/flash-ttl.js.map +1 -1
- package/dist/exposure/flash.js +1 -49
- package/dist/exposure/flash.js.map +1 -1
- package/dist/exposure/metering-scene-radiance.js +1 -25
- package/dist/exposure/metering-scene-radiance.js.map +1 -1
- package/dist/exposure/metering-target.js +1 -30
- package/dist/exposure/metering-target.js.map +1 -1
- package/dist/exposure/metering-temporal.js +1 -8
- package/dist/exposure/metering-temporal.js.map +1 -1
- package/dist/exposure/metering.js +1 -72
- package/dist/exposure/metering.js.map +1 -1
- package/dist/exposure/program-line.js +1 -45
- package/dist/exposure/program-line.js.map +1 -1
- package/dist/facade/develop-joined-parts.d.ts +29 -0
- package/dist/facade/develop-joined-parts.js +33 -0
- package/dist/facade/develop-joined-parts.js.map +1 -0
- package/dist/facade/generic-lens-capture.d.ts +4 -2
- package/dist/facade/generic-lens-capture.js +4 -2
- package/dist/facade/generic-lens-capture.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +37 -5
- package/dist/facade/simulate-capture.js +153 -96
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/gpu/chart-composite-gpu.js +1 -3
- package/dist/gpu/chart-composite-gpu.js.map +1 -1
- package/dist/gpu/chart-radiance-gpu.js +1 -5
- package/dist/gpu/chart-radiance-gpu.js.map +1 -1
- package/dist/gpu/display-view-quality-gpu.d.ts +13 -1
- package/dist/gpu/display-view-quality-gpu.js +4 -8
- package/dist/gpu/display-view-quality-gpu.js.map +1 -1
- package/dist/gpu/display-view-speed-gpu.js +3 -25
- package/dist/gpu/display-view-speed-gpu.js.map +1 -1
- package/dist/gpu/sensor-stage-gpu.js +1 -5
- package/dist/gpu/sensor-stage-gpu.js.map +1 -1
- package/dist/gpu/webgpu-runtime.d.ts +2 -0
- package/dist/gpu/webgpu-runtime.js +3 -0
- package/dist/gpu/webgpu-runtime.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/motion/camera-rotation.js +1 -6
- package/dist/motion/camera-rotation.js.map +1 -1
- package/dist/motion/capture-rotation-inverse-mapping.d.ts +12 -0
- package/dist/motion/capture-rotation-inverse-mapping.js +2 -2
- package/dist/motion/capture-rotation-inverse-mapping.js.map +1 -1
- package/dist/motion/capture-rotation-temporal-quadrature.d.ts +1 -0
- package/dist/motion/capture-rotation-temporal-quadrature.js +1 -1
- package/dist/motion/capture-rotation-temporal-quadrature.js.map +1 -1
- package/dist/motion/capture-rotation-trajectory.js +2 -17
- package/dist/motion/capture-rotation-trajectory.js.map +1 -1
- package/dist/motion/capture-translation-parallax-temporal-quadrature.d.ts +1 -0
- package/dist/motion/capture-translation-parallax-temporal-quadrature.js +3 -14
- package/dist/motion/capture-translation-parallax-temporal-quadrature.js.map +1 -1
- package/dist/motion/extended-object-projection.js +5 -40
- package/dist/motion/extended-object-projection.js.map +1 -1
- package/dist/optics/atmospheric-haze.js +1 -7
- package/dist/optics/atmospheric-haze.js.map +1 -1
- package/dist/optics/brown-conrady-distortion.js +1 -7
- package/dist/optics/brown-conrady-distortion.js.map +1 -1
- package/dist/optics/complex-pupil-psf.d.ts +1 -0
- package/dist/optics/complex-pupil-psf.js +2 -84
- package/dist/optics/complex-pupil-psf.js.map +1 -1
- package/dist/optics/focus-state.js +1 -11
- package/dist/optics/focus-state.js.map +1 -1
- package/dist/optics/front-of-lens-filter.d.ts +5 -0
- package/dist/optics/front-of-lens-filter.js +3 -65
- package/dist/optics/front-of-lens-filter.js.map +1 -1
- package/dist/optics/generic-nd-filter-presets.d.ts +12 -0
- package/dist/optics/generic-nd-filter-presets.js +48 -0
- package/dist/optics/generic-nd-filter-presets.js.map +1 -0
- package/dist/optics/illumination-vignetting.js +1 -6
- package/dist/optics/illumination-vignetting.js.map +1 -1
- package/dist/optics/lens-psf-profile.d.ts +4 -1
- package/dist/optics/lens-psf-profile.js +12 -111
- package/dist/optics/lens-psf-profile.js.map +1 -1
- package/dist/optics/longitudinal-chromatic-aberration.js +1 -7
- package/dist/optics/longitudinal-chromatic-aberration.js.map +1 -1
- package/dist/optics/pupil-vignetting.js +1 -7
- package/dist/optics/pupil-vignetting.js.map +1 -1
- package/dist/optics/radial-distortion.js +1 -6
- package/dist/optics/radial-distortion.js.map +1 -1
- package/dist/optics/scene-to-sensor-irradiance.js +4 -96
- package/dist/optics/scene-to-sensor-irradiance.js.map +1 -1
- package/dist/optics/stray-light.d.ts +1 -0
- package/dist/optics/stray-light.js +1 -1
- package/dist/optics/stray-light.js.map +1 -1
- package/dist/optics/zernike-wavefront.js +1 -7
- package/dist/optics/zernike-wavefront.js.map +1 -1
- package/dist/output/capture-geometry.js +1 -8
- package/dist/output/capture-geometry.js.map +1 -1
- package/dist/output/developed-lens-corrections.d.ts +62 -0
- package/dist/output/developed-lens-corrections.js +135 -0
- package/dist/output/developed-lens-corrections.js.map +1 -0
- package/dist/output/generic-lens-corrections.d.ts +2 -6
- package/dist/output/generic-lens-corrections.js +3 -6
- package/dist/output/generic-lens-corrections.js.map +1 -1
- package/dist/output/geometric-transforms.js +1 -4
- package/dist/output/geometric-transforms.js.map +1 -1
- package/dist/output/native-capture-sdr.d.ts +2 -2
- package/dist/output/native-capture-sdr.js +3 -2
- package/dist/output/native-capture-sdr.js.map +1 -1
- package/dist/processing/development-detail.d.ts +29 -0
- package/dist/processing/development-detail.js +128 -107
- package/dist/processing/development-detail.js.map +1 -1
- package/dist/schema/illumination-temporal.js +3 -72
- package/dist/schema/illumination-temporal.js.map +1 -1
- package/dist/schema/illumination.d.ts +1 -0
- package/dist/schema/illumination.js +2 -65
- package/dist/schema/illumination.js.map +1 -1
- package/dist/schema/scene-radiance-temporal.js +2 -14
- package/dist/schema/scene-radiance-temporal.js.map +1 -1
- package/dist/schema/scene-radiance.js +2 -60
- package/dist/schema/scene-radiance.js.map +1 -1
- package/dist/schema/validation.d.ts +2 -0
- package/dist/schema/validation.js +2 -17
- package/dist/schema/validation.js.map +1 -1
- package/dist/sensor/accumulated-charge.js +2 -59
- package/dist/sensor/accumulated-charge.js.map +1 -1
- package/dist/sensor/architecture.js +1 -16
- package/dist/sensor/architecture.js.map +1 -1
- package/dist/sensor/camera-saturation-capacity.d.ts +1 -0
- package/dist/sensor/camera-saturation-capacity.js +3 -55
- package/dist/sensor/camera-saturation-capacity.js.map +1 -1
- package/dist/sensor/capture-color-sampling-binding.js +1 -26
- package/dist/sensor/capture-color-sampling-binding.js.map +1 -1
- package/dist/sensor/capture-mode-timing.js +1 -39
- package/dist/sensor/capture-mode-timing.js.map +1 -1
- package/dist/sensor/capture-mode.js +1 -23
- package/dist/sensor/capture-mode.js.map +1 -1
- package/dist/sensor/color-sampling.js +1 -26
- package/dist/sensor/color-sampling.js.map +1 -1
- package/dist/sensor/constant-rate-temporal-integration.js +2 -46
- package/dist/sensor/constant-rate-temporal-integration.js.map +1 -1
- package/dist/sensor/dark-current.js +2 -45
- package/dist/sensor/dark-current.js.map +1 -1
- package/dist/sensor/eqe-electron-rate.js +2 -35
- package/dist/sensor/eqe-electron-rate.js.map +1 -1
- package/dist/sensor/exposure-window.d.ts +5 -0
- package/dist/sensor/exposure-window.js +7 -22
- package/dist/sensor/exposure-window.js.map +1 -1
- package/dist/sensor/iso-gain.js +1 -7
- package/dist/sensor/iso-gain.js.map +1 -1
- package/dist/sensor/iso-signal-chain.js +1 -43
- package/dist/sensor/iso-signal-chain.js.map +1 -1
- package/dist/sensor/optical-stack.js +1 -25
- package/dist/sensor/optical-stack.js.map +1 -1
- package/dist/sensor/photon-energy.js +1 -26
- package/dist/sensor/photon-energy.js.map +1 -1
- package/dist/sensor/physical-charge-capacity.js +3 -77
- package/dist/sensor/physical-charge-capacity.js.map +1 -1
- package/dist/sensor/radiometry-readiness.js +2 -23
- package/dist/sensor/radiometry-readiness.js.map +1 -1
- package/dist/sensor/raw-readout.d.ts +3 -0
- package/dist/sensor/raw-readout.js +4 -66
- package/dist/sensor/raw-readout.js.map +1 -1
- package/dist/sensor/raw-reconstruction.js +2 -64
- package/dist/sensor/raw-reconstruction.js.map +1 -1
- package/dist/sensor/readout-exposure-linkage.js +1 -9
- package/dist/sensor/readout-exposure-linkage.js.map +1 -1
- package/dist/sensor/readout-timing.js +3 -57
- package/dist/sensor/readout-timing.js.map +1 -1
- package/dist/sensor/response-application-compatibility.d.ts +2 -0
- package/dist/sensor/response-application-compatibility.js +3 -29
- package/dist/sensor/response-application-compatibility.js.map +1 -1
- package/dist/sensor/response-operating-range.d.ts +1 -0
- package/dist/sensor/response-operating-range.js +3 -79
- package/dist/sensor/response-operating-range.js.map +1 -1
- package/dist/sensor/responsivity-photocurrent.js +4 -108
- package/dist/sensor/responsivity-photocurrent.js.map +1 -1
- package/dist/sensor/sampling-aperture.js +1 -25
- package/dist/sensor/sampling-aperture.js.map +1 -1
- package/dist/sensor/spatial-sample-reduction.js +2 -19
- package/dist/sensor/spatial-sample-reduction.js.map +1 -1
- package/dist/sensor/spatial-sampling-quadrature.js +1 -3
- package/dist/sensor/spatial-sampling-quadrature.js.map +1 -1
- package/dist/sensor/spatio-spectral-reduction.js +1 -18
- package/dist/sensor/spatio-spectral-reduction.js.map +1 -1
- package/dist/sensor/spectral-coverage.d.ts +10 -1
- package/dist/sensor/spectral-coverage.js +1 -1
- package/dist/sensor/spectral-coverage.js.map +1 -1
- package/dist/sensor/spectral-quadrature.js +2 -35
- package/dist/sensor/spectral-quadrature.js.map +1 -1
- package/dist/sensor/spectral-response.js +1 -47
- package/dist/sensor/spectral-response.js.map +1 -1
- package/dist/stabilization/camera-shake.js +1 -6
- package/dist/stabilization/camera-shake.js.map +1 -1
- package/dist/stabilization/system.js +2 -80
- package/dist/stabilization/system.js.map +1 -1
- package/docs/AGENT_GUIDE.md +1 -0
- package/docs/API_REFERENCE.md +41 -2
- package/docs/QUICK_START.md +90 -8
- package/docs/USAGE.md +47 -2
- package/docs/api/core-version.md +1 -1
- package/docs/api/exports.json +53 -3
- package/docs/api/exposure-filtered-exposure-time.md +105 -0
- package/docs/api/facade-develop-joined-parts.md +32 -0
- package/docs/api/facade-simulate-capture.md +36 -5
- package/docs/api/optics-generic-nd-filter-presets.md +34 -0
- package/docs/api/optics-lens-psf-profile.md +3 -1
- package/docs/api/output-developed-lens-corrections.md +12 -0
- package/docs/api/output-generic-lens-corrections.md +0 -9
- package/llms.txt +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-capture-sdr.js","sourceRoot":"","sources":["../../src/output/native-capture-sdr.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Native SDR rendering of large captures, tile by tile, within fixed memory limits. The engine\n * owns the task; the caller supplies the pixel tiles. See docs/NATIVE_CAPTURE_SDR.md.\n */\nimport { parseSimulatedCapture, type SimulatedCapture, type CaptureLinearPlane } from \"../capture/simulated-capture.js\";\nimport { LINEAR_CAPTURE_RGB_PROFILE, resolveCaptureColorModel } from \"../color/capture-color.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { requireAllowlistedRecord, requirePublicOpaqueId } from \"../core/record-validation.js\";\nimport { freezeOwnedData } from \"../core/owned-data.js\";\nimport { FULL_RESOLUTION_CEILING_PIXELS, resolveRaisedLimit } from \"../core/pixel-limits.js\";\nimport { encodeSrgbComponent } from \"../color/srgb-transfer.js\";\nimport { InvalidScientificResultError } from \"../core/validation.js\";\nimport { parseSdrRenderingProfile, prepareSdrPixelTone, type SdrPixelTone, type SdrRenderingProfile, type SdrRenderingResult } from \"./sdr-rendering.js\";\n\nexport const NATIVE_CAPTURE_SDR_SCHEMA_VERSION = \"0.1.0\" as const;\n/** `maximumPixels` is the default pixel limit; a request may raise it with its own `maximumPixels`, up to `ceilingPixels`. */\nexport const NATIVE_CAPTURE_SDR_LIMITS = /* @__PURE__ */ Object.freeze({ maximumPixels: 24_000_000, ceilingPixels: FULL_RESOLUTION_CEILING_PIXELS,\n maximumDimension: 16_384, tileWidth: 256, tileHeight: 32, maximumTileStorageSamples: 32_768 });\n/** Input. The capture holds only metadata; float samples are read from external storage. Samples must already have colour and white balance applied. */\nexport interface NativeCaptureSdrInput {\n capture: SimulatedCapture;\n sourcePlaneId: string;\n outputImageStateId: string;\n profile: SdrRenderingProfile;\n /** Limit on the size of the integer output. Checked before anything is allocated or any tile is read. */\n maximumOutputBytes: number;\n /**\n * Optional opt-in pixel limit for large captures: an integer from 1 to `NATIVE_CAPTURE_SDR_LIMITS.ceilingPixels`.\n * Default `NATIVE_CAPTURE_SDR_LIMITS.maximumPixels` (24 000 000). `maximumOutputBytes` still applies.\n */\n maximumPixels?: number;\n}\n/** Tile request. Coordinates are absolute in the selected plane's declared pixel grid, never relative to a crop. */\nexport interface NativeCaptureSdrTileRequest {\n captureId: string;\n sourcePlaneId: string;\n artifactId: string;\n sha256: string;\n x: number; y: number; width: number; height: number;\n}\n/** A tile returned by the provider. It belongs to this call alone; do not change or reuse it. Row padding is not image data. */\nexport interface NativeCaptureSdrTile extends NativeCaptureSdrTileRequest {\n rowStrideSamples: number;\n samples: Float32Array | Float64Array;\n}\n/** Supplies tiles, one call at a time. The caller must release decoder and GPU resources when the task aborts or finishes. */\nexport interface NativeCaptureSdrProvider {\n readTile(request: Readonly<NativeCaptureSdrTileRequest>, signal: AbortSignal): Promise<NativeCaptureSdrTile>;\n /** Must yield to the host event loop, so cancellation and input events can run between tiles. */\n yieldControl(signal: AbortSignal): Promise<void>;\n /**\n * Optional progress observer, called synchronously after each committed tile. It cannot change\n * output; an exception it throws fails the task like any other error.\n */\n onProgress?(progress: NativeTaskProgress): void;\n}\n/** Tile progress of a native task: `completedTileCount` of `totalTileCount` tiles are committed. */\nexport interface NativeTaskProgress { readonly completedTileCount: number; readonly totalTileCount: number }\nexport interface NativeCaptureSdrPlan {\n schemaVersion: typeof NATIVE_CAPTURE_SDR_SCHEMA_VERSION;\n capture: SimulatedCapture;\n sourcePlaneId: string;\n outputImageStateId: string;\n profile: SdrRenderingProfile;\n outputBytes: number;\n /** Upper bound on the bytes held in working arrays. It is not peak JavaScript heap, GPU or process memory, and does not show that a device can run the task. */\n maximumScratchPayloadBytes: number;\n tileCount: number;\n}\nexport interface NativeCaptureSdrOutput {\n plan: NativeCaptureSdrPlan;\n /** Packed RGB codes in row-major order, owned by the caller. 16-bit codes are numbers, not bytes in a particular byte order. */\n integerSamples: Uint8Array | Uint16Array;\n diagnostics: SdrRenderingResult[\"diagnostics\"];\n outputEncoding: SdrRenderingResult[\"outputEncoding\"];\n displayAdaptation: SdrRenderingResult[\"displayAdaptation\"];\n}\nexport type NativeCaptureSdrTaskState = \"ready\" | \"running\" | \"completed\" | \"cancelled\" | \"failed\" | \"disposed\" | \"transferred\";\n\n/** Validates the input and plans the task, including its limits, without reading samples or allocating an image. */\nexport function calculateNativeCaptureSdrPlan(input: NativeCaptureSdrInput): NativeCaptureSdrPlan {\n const r = requireAllowlistedRecord(input, [\"capture\", \"sourcePlaneId\", \"outputImageStateId\", \"profile\", \"maximumOutputBytes\", \"maximumPixels\"], \"Invalid native SDR input.\");\n const maximumPixels = resolveRaisedLimit(r.maximumPixels, NATIVE_CAPTURE_SDR_LIMITS.maximumPixels, NATIVE_CAPTURE_SDR_LIMITS.ceilingPixels,\n \"Native SDR maximumPixels must be an integer from 1 to \" + NATIVE_CAPTURE_SDR_LIMITS.ceilingPixels + \".\");\n // Only external-storage manifests are accepted, so unrelated inline sample buffers are never copied.\n const c = r.capture as SimulatedCapture | undefined;\n if (!c || !Array.isArray(c.planes) || c.planes.length > 32 || c.planes.some(p => !p || p.storage?.kind === \"inline-float64\")) {\n throw new InvalidConfigurationError(\"Native SDR requires external-only capture manifests.\");\n }\n const capture = parseSimulatedCapture(c);\n const sourcePlaneId = requirePublicOpaqueId(r.sourcePlaneId, \"Invalid native SDR plane ID.\");\n const outputImageStateId = requirePublicOpaqueId(r.outputImageStateId, \"Invalid native SDR output state ID.\");\n const plane = capture.planes.find(p => p.id === sourcePlaneId);\n const white = resolveCaptureColorModel().referenceWhiteXyz;\n if (!plane || plane.imageState !== \"color-transformed-linear-rgb\" ||\n plane.colorProfile?.id !== LINEAR_CAPTURE_RGB_PROFILE.id || plane.colorProfile.version !== LINEAR_CAPTURE_RGB_PROFILE.version ||\n plane.encodingReferenceWhiteXyz?.x !== white.x || plane.encodingReferenceWhiteXyz.y !== white.y || plane.encodingReferenceWhiteXyz.z !== white.z ||\n plane.whiteBalanceApplication === \"intent-only\" || (plane.whiteBalanceApplication === \"not-applicable\" && capture.whiteBalanceIntent !== null) ||\n capture.planes.some(p => p.imageStateId === outputImageStateId)) {\n throw new InvalidConfigurationError(\"Native SDR requires exact resolved linear-sRGB/D65 and a new output state ID.\");\n }\n const pixels = plane.pixelWidth * plane.pixelHeight, profile = parseSdrRenderingProfile(r.profile);\n const outputBytes = pixels * 3 * (profile.bitDepth / 8);\n const scale = 2 ** profile.renderingExposureEv / plane.referenceWhiteValue;\n if (!Number.isFinite(scale) || scale <= 0) throw new InvalidConfigurationError(\"Native SDR scale is unrepresentable.\");\n if (pixels > maximumPixels || plane.pixelWidth > NATIVE_CAPTURE_SDR_LIMITS.maximumDimension ||\n plane.pixelHeight > NATIVE_CAPTURE_SDR_LIMITS.maximumDimension || typeof r.maximumOutputBytes !== \"number\" ||\n !Number.isSafeInteger(r.maximumOutputBytes) || r.maximumOutputBytes < outputBytes) {\n throw new InvalidConfigurationError(\"Native SDR raster/output exceeds declared admission limits.\");\n }\n // A cautious declared bound, kept from the earlier executor that called the reference renderer: provider payload +\n // packed copy + reference parser copy + four reference output arrays. The typed kernel itself keeps only the provider payload.\n const maximumScratchPayloadBytes = NATIVE_CAPTURE_SDR_LIMITS.maximumTileStorageSamples * 8 +\n NATIVE_CAPTURE_SDR_LIMITS.tileWidth * NATIVE_CAPTURE_SDR_LIMITS.tileHeight * 3 * 8 * 6;\n return freezeOwnedData({ schemaVersion: NATIVE_CAPTURE_SDR_SCHEMA_VERSION, capture, sourcePlaneId, outputImageStateId, profile,\n outputBytes, maximumScratchPayloadBytes,\n tileCount: Math.ceil(plane.pixelWidth / NATIVE_CAPTURE_SDR_LIMITS.tileWidth) * Math.ceil(plane.pixelHeight / NATIVE_CAPTURE_SDR_LIMITS.tileHeight) });\n}\n\n/**\n * Tile checks shared by every native SDR backend: identity, precision, row stride, storage and valid\n * input values. Returns a view of the provider's samples (not a copy). Padding is not checked for\n * finite values. Not exported from the package.\n */\nexport function validateNativeCaptureSdrTile(tile: NativeCaptureSdrTile, request: NativeCaptureSdrTileRequest,\n plane: CaptureLinearPlane): { source: Float32Array | Float64Array; stride: number } {\n const r = requireAllowlistedRecord(tile, [\"captureId\", \"sourcePlaneId\", \"artifactId\", \"sha256\", \"x\", \"y\", \"width\", \"height\", \"rowStrideSamples\", \"samples\"], \"Invalid native SDR tile.\");\n for (const key of Object.keys(request) as (keyof NativeCaptureSdrTileRequest)[]) {\n if (r[key] !== request[key]) throw new InvalidConfigurationError(\"Native SDR tile identity/rectangle mismatch.\");\n }\n const samples = r.samples;\n const expectedType = plane.storage.kind === \"external-float32\" ? Float32Array : Float64Array;\n if (!(samples instanceof expectedType) || !(samples.buffer instanceof ArrayBuffer) ||\n samples.buffer.byteLength > NATIVE_CAPTURE_SDR_LIMITS.maximumTileStorageSamples * expectedType.BYTES_PER_ELEMENT ||\n typeof r.rowStrideSamples !== \"number\" || !Number.isSafeInteger(r.rowStrideSamples) || r.rowStrideSamples < request.width * 3 ||\n samples.length !== r.rowStrideSamples * request.height || samples.length > NATIVE_CAPTURE_SDR_LIMITS.maximumTileStorageSamples) {\n throw new InvalidConfigurationError(\"Native SDR tile precision/stride/storage mismatch.\");\n }\n const source: Float32Array | Float64Array = samples, stride = r.rowStrideSamples, rowLength = request.width * 3;\n // Check every image sample (not padding) against the reference renderer's input rules before any rendering.\n for (let y = 0; y < request.height; y++) {\n for (let i = y * stride, end = i + rowLength; i < end; i++) {\n if (!Number.isFinite(source[i]!)) throw new InvalidConfigurationError(\"Unsupported SDR input domain/raster.\");\n }\n }\n return { source, stride };\n}\n\ntype NativeSdrDiagnosticCounts = Omit<SdrRenderingResult[\"diagnostics\"], \"captureSaturation\">;\n/**\n * Fast tile kernel on typed arrays. It applies the same equations as the SDR reference renderer\n * (`calculateSdrRendering`), with the same floating-point operation order per sample and the same\n * error precedence, and writes integer codes straight into the packed output.\n *\n * Steps: input check → rendering exposure → tone → gamut → sRGB transfer → quantization (round to\n * nearest, ties up). `test/native-capture-sdr-kernel-parity.test.ts` shows that codes and diagnostics\n * match the unchanged reference exactly.\n */\nfunction renderTileInto(tile: NativeCaptureSdrTile, request: NativeCaptureSdrTileRequest, plane: CaptureLinearPlane,\n profile: SdrRenderingProfile, tone: SdrPixelTone, scale: number, maximum: number, codes: Uint8Array | Uint16Array, diagnostics: NativeSdrDiagnosticCounts): void {\n const { source, stride } = validateNativeCaptureSdrTile(tile, request, plane);\n // Tiling is safe because every supported rendering operation works on one pixel at a time.\n const outputRowStride = plane.pixelWidth * 3;\n const counts = { negative: 0, above: 0, changed: 0, low: 0, high: 0, outOfGamut: false }, scratch = new Float64Array(3);\n for (let y = 0; y < request.height; y++) {\n renderSdrRunInto(source, y * stride, request.width, profile, tone, scale, maximum, codes, (request.y + y) * outputRowStride + request.x * 3, scratch, counts);\n }\n if (counts.outOfGamut) throw new InvalidConfigurationError(\"Tone output exceeds the declared SDR gamut range.\");\n diagnostics.renderingNegativeSampleCount += counts.negative; diagnostics.renderingAboveReferenceSampleCount += counts.above;\n diagnostics.toneChangedSampleCount += counts.changed; diagnostics.gamutClippedLowSampleCount += counts.low; diagnostics.gamutClippedHighSampleCount += counts.high;\n}\n/** Reference 8-bit code of a linear sample in [0,1]: Math.round(encodeSrgbComponent(x)·255). */\nfunction referenceSrgb8(linear: number): number { return Math.round(encodeSrgbComponent(linear) * 255); }\n/** Exact 8-bit sRGB quantizer tables; see {@link srgb8Quantizer}. */\nexport interface Srgb8Quantizer {\n /** t[k]: smallest binary64 x in [0,1] with referenceSrgb8(x) ≥ k; t[256] = +∞ sentinel. */\n readonly thresholds: Float64Array;\n /** start[b]: reference code of b/4096, the first code of bucket [b/4096, (b+1)/4096). */\n readonly start: Uint8Array;\n}\nlet srgb8: Srgb8Quantizer | null | undefined;\n/**\n * Exact 8-bit sRGB quantization without evaluating the transfer curve for each sample.\n *\n * The code thresholds are found by bisection on this engine's own `encodeSrgbComponent`. Comparing\n * against them gives Math.round(encodeSrgbComponent(x)·255) for every x, provided that function never\n * decreases (true when pow is monotone). Construction checks every threshold and the 16 neighbouring\n * doubles on each side. If any check fails, the direct transfer is used instead, so output never\n * silently depends on that assumption.\n *\n * A 4097-entry bucket index (x·4096 is exact) gives the starting code. Even the steepest part of the\n * curve (slope 12.92·255) covers less than one code per bucket, so one or two comparisons finish.\n */\nfunction srgb8Quantizer(): Srgb8Quantizer | null {\n if (srgb8 !== undefined) return srgb8;\n const t = new Float64Array(257), bits = new Float64Array(1), word = new BigUint64Array(bits.buffer);\n const step = (x: number, n: number): number => { bits[0] = x; word[0] = word[0]! + BigInt(n); return bits[0]!; };\n for (let k = 1; k < 256; k++) {\n let lo = t[k - 1]!, hi = 1;\n for (;;) {\n const mid = lo + (hi - lo) / 2;\n if (mid === lo || mid === hi) break;\n if (referenceSrgb8(mid) >= k) hi = mid; else lo = mid;\n }\n t[k] = hi;\n }\n t[256] = Infinity;\n let valid = referenceSrgb8(0) === 0 && referenceSrgb8(1) === 255;\n for (let k = 1; valid && k < 256; k++) {\n const x = t[k]!;\n if (!(x > t[k - 1]!) || referenceSrgb8(x) !== k) valid = false;\n for (let n = 1; valid && n <= 16; n++) {\n const below = step(x, -n), above = step(x, n);\n if ((below >= 0 && referenceSrgb8(below) >= k) || (above <= 1 && referenceSrgb8(above) < k)) valid = false;\n }\n }\n const start = new Uint8Array(4097);\n for (let i = 0; valid && i <= 4096; i++) { start[i] = referenceSrgb8(i / 4096); if (i > 0 && start[i]! < start[i - 1]!) valid = false; }\n srgb8 = valid ? { thresholds: t, start } : null;\n return srgb8;\n}\n/** Largest k with t[k] ≤ x for x in [0,1]. */\nfunction quantizeSrgb8(q: Srgb8Quantizer, x: number): number {\n const t = q.thresholds;\n let k = q.start[(x * 4096) | 0]!;\n while (x >= t[k + 1]!) k++;\n return k;\n}\n/** Internal, for tests: the exact quantizer (null when its construction check failed). */\nexport function nativeSrgb8QuantizerForTest(): { quantizer: Srgb8Quantizer | null; quantize(x: number): number } {\n const quantizer = srgb8Quantizer();\n return { quantizer, quantize: (x) => quantizer ? quantizeSrgb8(quantizer, x) : referenceSrgb8(x) };\n}\n/** Per-tile counters for {@link renderSdrRunInto}. `outOfGamut` delays the rejection, as the reference does. */\nexport interface SdrPixelCounts { negative: number; above: number; changed: number; low: number; high: number; outOfGamut: boolean }\n/**\n * Internal SDR kernel on typed arrays, shared by native SDR and RAW development.\n *\n * For `pixelCount` interleaved linear-sRGB pixels starting at `source[start]`, it runs exactly the\n * reference (`calculateSdrRendering`) operations in the same order per pixel: -0 → +0 → rendering\n * exposure → shared tone operator → gamut → sRGB transfer → quantization (nearest, ties up) into\n * `codes[outOffset]`. A gamut rejection is delayed via `counts.outOfGamut`, because the reference\n * finishes the whole tone pass (and its exposure errors) first. `scratch` must hold at least 3\n * values. Not exported from the package.\n */\nexport function renderSdrRunInto(source: Float32Array | Float64Array, start: number, pixelCount: number, profile: SdrRenderingProfile,\n tone: SdrPixelTone, scale: number, maximum: number, codes: Uint8Array | Uint16Array, outOffset: number, scratch: Float64Array, counts: SdrPixelCounts): void {\n const reject = profile.gamutHandling === \"reject-out-of-range\", quantizer = maximum === 255 ? srgb8Quantizer() : null;\n let negative = 0, above = 0, changed = 0, low = 0, high = 0, outOfGamut = false;\n for (let p = 0, i = start, o = outOffset; p < pixelCount; p++, i += 3) {\n // The reference parser normalizes -0 to +0 before exposure.\n const red = source[i]!, green = source[i + 1]!, blue = source[i + 2]!;\n const er = (red === 0 ? 0 : red) * scale, eg = (green === 0 ? 0 : green) * scale, eb = (blue === 0 ? 0 : blue) * scale;\n if (!Number.isFinite(er) || !Number.isFinite(eg) || !Number.isFinite(eb)) throw new InvalidScientificResultError(\"Rendering exposure produced a non-finite sample.\");\n tone(er, eg, eb, scratch);\n for (let c = 0; c < 3; c++, o++) {\n const exposed = c === 0 ? er : c === 1 ? eg : eb;\n if (exposed < 0) negative++;\n if (exposed > 1) above++;\n let mapped = scratch[c]!;\n if (mapped !== exposed) changed++;\n if (mapped === 0) mapped = 0;\n let linear = mapped;\n if (mapped < 0 || mapped > 1) {\n if (reject) outOfGamut = true;\n else if (mapped < 0) { low++; linear = 0; }\n else { high++; linear = 1; }\n }\n // Encoded values are in [0,1]: Math.round is exact nearest-ties-up here.\n codes[o] = quantizer ? quantizeSrgb8(quantizer, linear) : Math.round(encodeSrgbComponent(linear) * maximum);\n }\n }\n counts.negative += negative; counts.above += above; counts.changed += changed; counts.low += low; counts.high += high;\n if (outOfGamut) counts.outOfGamut = true;\n}\n\n/** The reference's output-encoding declaration for the given code maximum. */\nexport function sdrOutputEncoding(maximum: number): SdrRenderingResult[\"outputEncoding\"] {\n return { imageState: \"output-referred-sdr\", colorSpace: \"srgb\", primariesXy: { red: [.64, .33], green: [.30, .60], blue: [.15, .06] },\n whitePointXy: [.3127, .3290], referenceWhiteLuminanceCdM2: 80, codeMinimum: 0, codeMaximum: maximum };\n}\n\n/** A single-use task. No partial output is ever returned, and cancel or dispose stops a late result from being published. */\nexport interface NativeCaptureSdrTask {\n readonly plan: NativeCaptureSdrPlan;\n readonly state: NativeCaptureSdrTaskState;\n readonly completedTileCount: number;\n run(): Promise<void>;\n cancel(): void;\n dispose(): void;\n /** Hands over the only copy of the output buffer, once. Dispose cannot take back a buffer already handed over. */\n takeOutput(): NativeCaptureSdrOutput;\n}\n/** Creates a single-use task. Limits are checked before any buffer is allocated or tile is read. */\nexport function createNativeCaptureSdrTask(input: NativeCaptureSdrInput, provider: NativeCaptureSdrProvider): NativeCaptureSdrTask {\n const plan = calculateNativeCaptureSdrPlan(input);\n if (!provider || typeof provider.readTile !== \"function\" || typeof provider.yieldControl !== \"function\") {\n throw new InvalidConfigurationError(\"Native SDR requires a tile reader and event-loop yield.\");\n }\n if (provider.onProgress !== undefined && typeof provider.onProgress !== \"function\") throw new InvalidConfigurationError(\"Native SDR onProgress must be a function.\");\n // Also capture the callback functions now, so later app changes cannot swap the reader mid-task.\n const readTile = provider.readTile.bind(provider), yieldControl = provider.yieldControl.bind(provider),\n onProgress = provider.onProgress?.bind(provider);\n const plane = plan.capture.planes.find(p => p.id === plan.sourcePlaneId)!;\n if (plane.storage.kind === \"inline-float64\") throw new InvalidConfigurationError(\"External native source required.\");\n const storage = plane.storage, abort = new AbortController();\n let state: NativeCaptureSdrTaskState = \"ready\", count = 0, output: NativeCaptureSdrOutput | null = null;\n let codes: Uint8Array | Uint16Array | null = null;\n function release(): void { codes?.fill(0); codes = null; output = null; }\n function checkActive(): void {\n if (abort.signal.aborted) throw new InvalidConfigurationError(\"Native SDR task cancelled/disposed; no output available.\");\n }\n return {\n plan,\n get state(): NativeCaptureSdrTaskState { return state; },\n get completedTileCount(): number { return count; },\n async run(): Promise<void> {\n if (state !== \"ready\") throw new InvalidConfigurationError(\"Native SDR task is single-use.\");\n state = \"running\";\n try {\n codes = plan.profile.bitDepth === 8 ? new Uint8Array(plan.outputBytes) : new Uint16Array(plan.outputBytes / 2);\n const diagnostics: SdrRenderingResult[\"diagnostics\"] = { renderingNegativeSampleCount: 0, renderingAboveReferenceSampleCount: 0,\n toneChangedSampleCount: 0, gamutClippedLowSampleCount: 0, gamutClippedHighSampleCount: 0, captureSaturation: \"not-consumed\" };\n // Same scale expression and code range as the reference. The plan already rejected a scale that cannot be represented.\n const scale = 2 ** plan.profile.renderingExposureEv / plane.referenceWhiteValue, maximum = 2 ** plan.profile.bitDepth - 1,\n tone = prepareSdrPixelTone(plan.profile);\n for (let y = 0; y < plane.pixelHeight; y += NATIVE_CAPTURE_SDR_LIMITS.tileHeight) {\n for (let x = 0; x < plane.pixelWidth; x += NATIVE_CAPTURE_SDR_LIMITS.tileWidth) {\n checkActive();\n const request = Object.freeze({ captureId: plan.capture.captureId, sourcePlaneId: plane.id,\n artifactId: storage.artifactId, sha256: storage.sha256, x, y,\n width: Math.min(NATIVE_CAPTURE_SDR_LIMITS.tileWidth, plane.pixelWidth - x),\n height: Math.min(NATIVE_CAPTURE_SDR_LIMITS.tileHeight, plane.pixelHeight - y) });\n {\n const tile = await readTile(request, abort.signal);\n checkActive();\n // Diagnostics are aggregated only after the whole tile renders.\n renderTileInto(tile, request, plane, plan.profile, tone, scale, maximum, codes!, diagnostics);\n count++;\n onProgress?.({ completedTileCount: count, totalTileCount: plan.tileCount });\n }\n // Do not keep tile or reference arrays past the next tile read or host yield.\n await yieldControl(abort.signal);\n checkActive();\n }\n }\n output = { plan, integerSamples: codes!, diagnostics, outputEncoding: sdrOutputEncoding(maximum),\n displayAdaptation: { kind: \"external-platform\", applied: false, displayCapabilities: \"unknown\" } };\n state = \"completed\";\n } catch (error) {\n release();\n if (!abort.signal.aborted) { state = \"failed\"; abort.abort(); }\n throw error;\n }\n },\n cancel(): void {\n if (state === \"ready\" || state === \"running\" || state === \"completed\") { state = \"cancelled\"; abort.abort(); release(); }\n },\n dispose(): void { if (state !== \"transferred\") { state = \"disposed\"; abort.abort(); release(); } },\n takeOutput(): NativeCaptureSdrOutput {\n if (state !== \"completed\" || !output) throw new InvalidConfigurationError(\"Native SDR output is unavailable.\");\n const result = output; output = null; codes = null; state = \"transferred\";\n return result;\n }\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"native-capture-sdr.js","sourceRoot":"","sources":["../../src/output/native-capture-sdr.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Native SDR rendering of large captures, tile by tile, within fixed memory limits. The engine\n * owns the task; the caller supplies the pixel tiles. See docs/NATIVE_CAPTURE_SDR.md.\n */\nimport { parseSimulatedCapture, type SimulatedCapture, type CaptureLinearPlane } from \"../capture/simulated-capture.js\";\nimport { LINEAR_CAPTURE_RGB_PROFILE, resolveCaptureColorModel } from \"../color/capture-color.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { requireAllowlistedRecord, requirePublicOpaqueId } from \"../core/record-validation.js\";\nimport { freezeOwnedData } from \"../core/owned-data.js\";\nimport { FULL_RESOLUTION_CEILING_PIXELS, resolveRaisedLimit } from \"../core/pixel-limits.js\";\nimport { encodeSrgbComponent } from \"../color/srgb-transfer.js\";\nimport { InvalidScientificResultError } from \"../core/validation.js\";\nimport { parseSdrRenderingProfile, prepareSdrPixelTone, type SdrPixelTone, type SdrRenderingProfile, type SdrRenderingResult } from \"./sdr-rendering.js\";\n\nexport const NATIVE_CAPTURE_SDR_SCHEMA_VERSION = \"0.1.0\" as const;\n/** `maximumPixels` is the default pixel limit; a request may raise it with its own `maximumPixels`, up to `ceilingPixels`. */\nexport const NATIVE_CAPTURE_SDR_LIMITS = /* @__PURE__ */ Object.freeze({ maximumPixels: 24_000_000, ceilingPixels: FULL_RESOLUTION_CEILING_PIXELS,\n maximumDimension: 16_384, tileWidth: 256, tileHeight: 32, maximumTileStorageSamples: 32_768 });\n/** Input. The capture holds only metadata; float samples are read from external storage. Samples must already have colour and white balance applied. */\nexport interface NativeCaptureSdrInput {\n capture: SimulatedCapture;\n sourcePlaneId: string;\n outputImageStateId: string;\n profile: SdrRenderingProfile;\n /** Limit on the size of the integer output. Checked before anything is allocated or any tile is read. */\n maximumOutputBytes: number;\n /**\n * Optional opt-in pixel limit for large captures: an integer from 1 to `NATIVE_CAPTURE_SDR_LIMITS.ceilingPixels`.\n * Default `NATIVE_CAPTURE_SDR_LIMITS.maximumPixels` (24 000 000). `maximumOutputBytes` still applies.\n */\n maximumPixels?: number;\n}\n/** Tile request. Coordinates are absolute in the selected plane's declared pixel grid, never relative to a crop. */\nexport interface NativeCaptureSdrTileRequest {\n captureId: string;\n sourcePlaneId: string;\n artifactId: string;\n sha256: string;\n x: number; y: number; width: number; height: number;\n}\n/** A tile returned by the provider. It belongs to this call alone; do not change or reuse it. Row padding is not image data. */\nexport interface NativeCaptureSdrTile extends NativeCaptureSdrTileRequest {\n rowStrideSamples: number;\n samples: Float32Array | Float64Array;\n}\n/** Supplies tiles, one call at a time. The caller must release decoder and GPU resources when the task aborts or finishes. */\nexport interface NativeCaptureSdrProvider {\n readTile(request: Readonly<NativeCaptureSdrTileRequest>, signal: AbortSignal): Promise<NativeCaptureSdrTile>;\n /** Must yield to the host event loop, so cancellation and input events can run between tiles. */\n yieldControl(signal: AbortSignal): Promise<void>;\n /**\n * Optional progress observer, called synchronously after each committed tile. It cannot change\n * output; an exception it throws fails the task like any other error.\n */\n onProgress?(progress: NativeTaskProgress): void;\n}\n/** Tile progress of a native task: `completedTileCount` of `totalTileCount` tiles are committed. */\nexport interface NativeTaskProgress { readonly completedTileCount: number; readonly totalTileCount: number }\nexport interface NativeCaptureSdrPlan {\n schemaVersion: typeof NATIVE_CAPTURE_SDR_SCHEMA_VERSION;\n capture: SimulatedCapture;\n sourcePlaneId: string;\n outputImageStateId: string;\n profile: SdrRenderingProfile;\n outputBytes: number;\n /** Upper bound on the bytes held in working arrays. It is not peak JavaScript heap, GPU or process memory, and does not show that a device can run the task. */\n maximumScratchPayloadBytes: number;\n tileCount: number;\n}\nexport interface NativeCaptureSdrOutput {\n plan: NativeCaptureSdrPlan;\n /** Packed RGB codes in row-major order, owned by the caller. 16-bit codes are numbers, not bytes in a particular byte order. */\n integerSamples: Uint8Array | Uint16Array;\n diagnostics: SdrRenderingResult[\"diagnostics\"];\n outputEncoding: SdrRenderingResult[\"outputEncoding\"];\n displayAdaptation: SdrRenderingResult[\"displayAdaptation\"];\n}\nexport type NativeCaptureSdrTaskState = \"ready\" | \"running\" | \"completed\" | \"cancelled\" | \"failed\" | \"disposed\" | \"transferred\";\n\n/** Validates the input and plans the task, including its limits, without reading samples or allocating an image. */\nexport function calculateNativeCaptureSdrPlan(input: NativeCaptureSdrInput): NativeCaptureSdrPlan {\n const r = requireAllowlistedRecord(input, [\"capture\", \"sourcePlaneId\", \"outputImageStateId\", \"profile\", \"maximumOutputBytes\", \"maximumPixels\"], \"Invalid native SDR input.\");\n const maximumPixels = resolveRaisedLimit(r.maximumPixels, NATIVE_CAPTURE_SDR_LIMITS.maximumPixels, NATIVE_CAPTURE_SDR_LIMITS.ceilingPixels,\n \"Native SDR maximumPixels must be an integer from 1 to \" + NATIVE_CAPTURE_SDR_LIMITS.ceilingPixels + \".\");\n // Only external-storage manifests are accepted, so unrelated inline sample buffers are never copied.\n const c = r.capture as SimulatedCapture | undefined;\n if (!c || !Array.isArray(c.planes) || c.planes.length > 32 || c.planes.some(p => !p || p.storage?.kind === \"inline-float64\")) {\n throw new InvalidConfigurationError(\"Native SDR requires external-only capture manifests.\");\n }\n const capture = parseSimulatedCapture(c);\n const sourcePlaneId = requirePublicOpaqueId(r.sourcePlaneId, \"Invalid native SDR plane ID.\");\n const outputImageStateId = requirePublicOpaqueId(r.outputImageStateId, \"Invalid native SDR output state ID.\");\n const plane = capture.planes.find(p => p.id === sourcePlaneId);\n const white = resolveCaptureColorModel().referenceWhiteXyz;\n if (!plane || plane.imageState !== \"color-transformed-linear-rgb\" ||\n plane.colorProfile?.id !== LINEAR_CAPTURE_RGB_PROFILE.id || plane.colorProfile.version !== LINEAR_CAPTURE_RGB_PROFILE.version ||\n plane.encodingReferenceWhiteXyz?.x !== white.x || plane.encodingReferenceWhiteXyz.y !== white.y || plane.encodingReferenceWhiteXyz.z !== white.z ||\n plane.whiteBalanceApplication === \"intent-only\" || (plane.whiteBalanceApplication === \"not-applicable\" && capture.whiteBalanceIntent !== null) ||\n capture.planes.some(p => p.imageStateId === outputImageStateId)) {\n throw new InvalidConfigurationError(\"Native SDR requires exact resolved linear-sRGB/D65 and a new output state ID.\");\n }\n const pixels = plane.pixelWidth * plane.pixelHeight, profile = parseSdrRenderingProfile(r.profile);\n const outputBytes = pixels * 3 * (profile.bitDepth / 8);\n const scale = 2 ** profile.renderingExposureEv / plane.referenceWhiteValue;\n if (!Number.isFinite(scale) || scale <= 0) throw new InvalidConfigurationError(\"Native SDR scale is unrepresentable.\");\n if (pixels > maximumPixels || plane.pixelWidth > NATIVE_CAPTURE_SDR_LIMITS.maximumDimension ||\n plane.pixelHeight > NATIVE_CAPTURE_SDR_LIMITS.maximumDimension || typeof r.maximumOutputBytes !== \"number\" ||\n !Number.isSafeInteger(r.maximumOutputBytes) || r.maximumOutputBytes < outputBytes) {\n throw new InvalidConfigurationError(\"Native SDR raster/output exceeds declared admission limits.\");\n }\n // A cautious declared bound, kept from the earlier executor that called the reference renderer: provider payload +\n // packed copy + reference parser copy + four reference output arrays. The typed kernel itself keeps only the provider payload.\n const maximumScratchPayloadBytes = NATIVE_CAPTURE_SDR_LIMITS.maximumTileStorageSamples * 8 +\n NATIVE_CAPTURE_SDR_LIMITS.tileWidth * NATIVE_CAPTURE_SDR_LIMITS.tileHeight * 3 * 8 * 6;\n return freezeOwnedData({ schemaVersion: NATIVE_CAPTURE_SDR_SCHEMA_VERSION, capture, sourcePlaneId, outputImageStateId, profile,\n outputBytes, maximumScratchPayloadBytes,\n tileCount: Math.ceil(plane.pixelWidth / NATIVE_CAPTURE_SDR_LIMITS.tileWidth) * Math.ceil(plane.pixelHeight / NATIVE_CAPTURE_SDR_LIMITS.tileHeight) });\n}\n\n/**\n * Tile checks shared by every native SDR backend: identity, precision, row stride, storage and valid\n * input values. Returns a view of the provider's samples (not a copy). Padding is not checked for\n * finite values. Not exported from the package.\n */\nexport function validateNativeCaptureSdrTile(tile: NativeCaptureSdrTile, request: NativeCaptureSdrTileRequest,\n plane: CaptureLinearPlane): { source: Float32Array | Float64Array; stride: number } {\n const r = requireAllowlistedRecord(tile, [\"captureId\", \"sourcePlaneId\", \"artifactId\", \"sha256\", \"x\", \"y\", \"width\", \"height\", \"rowStrideSamples\", \"samples\"], \"Invalid native SDR tile.\");\n for (const key of Object.keys(request) as (keyof NativeCaptureSdrTileRequest)[]) {\n if (r[key] !== request[key]) throw new InvalidConfigurationError(\"Native SDR tile identity/rectangle mismatch.\");\n }\n const samples = r.samples;\n const expectedType = plane.storage.kind === \"external-float32\" ? Float32Array : Float64Array;\n if (!(samples instanceof expectedType) || !(samples.buffer instanceof ArrayBuffer) ||\n samples.buffer.byteLength > NATIVE_CAPTURE_SDR_LIMITS.maximumTileStorageSamples * expectedType.BYTES_PER_ELEMENT ||\n typeof r.rowStrideSamples !== \"number\" || !Number.isSafeInteger(r.rowStrideSamples) || r.rowStrideSamples < request.width * 3 ||\n samples.length !== r.rowStrideSamples * request.height || samples.length > NATIVE_CAPTURE_SDR_LIMITS.maximumTileStorageSamples) {\n throw new InvalidConfigurationError(\"Native SDR tile precision/stride/storage mismatch.\");\n }\n const source: Float32Array | Float64Array = samples, stride = r.rowStrideSamples, rowLength = request.width * 3;\n // Check every image sample (not padding) against the reference renderer's input rules before any rendering.\n for (let y = 0; y < request.height; y++) {\n for (let i = y * stride, end = i + rowLength; i < end; i++) {\n if (!Number.isFinite(source[i]!)) throw new InvalidConfigurationError(\"Unsupported SDR input domain/raster.\");\n }\n }\n return { source, stride };\n}\n\ntype NativeSdrDiagnosticCounts = Omit<SdrRenderingResult[\"diagnostics\"], \"captureSaturation\">;\n/**\n * Fast tile kernel on typed arrays. It applies the same equations as the SDR reference renderer\n * (`calculateSdrRendering`), with the same floating-point operation order per sample and the same\n * error precedence, and writes integer codes straight into the packed output.\n *\n * Steps: input check → rendering exposure → tone → gamut → sRGB transfer → quantization (round to\n * nearest, ties up). `test/native-capture-sdr-kernel-parity.test.ts` shows that codes and diagnostics\n * match the unchanged reference exactly.\n */\nfunction renderTileInto(tile: NativeCaptureSdrTile, request: NativeCaptureSdrTileRequest, plane: CaptureLinearPlane,\n profile: SdrRenderingProfile, tone: SdrPixelTone, scale: number, maximum: number, codes: Uint8Array | Uint16Array, diagnostics: NativeSdrDiagnosticCounts): void {\n const { source, stride } = validateNativeCaptureSdrTile(tile, request, plane);\n // Tiling is safe because every supported rendering operation works on one pixel at a time.\n const outputRowStride = plane.pixelWidth * 3;\n const counts = { negative: 0, above: 0, changed: 0, low: 0, high: 0, outOfGamut: false }, scratch = new Float64Array(3);\n for (let y = 0; y < request.height; y++) {\n renderSdrRunInto(source, y * stride, request.width, profile, tone, scale, maximum, codes, (request.y + y) * outputRowStride + request.x * 3, scratch, counts);\n }\n if (counts.outOfGamut) throw new InvalidConfigurationError(\"Tone output exceeds the declared SDR gamut range.\");\n diagnostics.renderingNegativeSampleCount += counts.negative; diagnostics.renderingAboveReferenceSampleCount += counts.above;\n diagnostics.toneChangedSampleCount += counts.changed; diagnostics.gamutClippedLowSampleCount += counts.low; diagnostics.gamutClippedHighSampleCount += counts.high;\n}\n/** Reference 8-bit code of a linear sample in [0,1]: Math.round(encodeSrgbComponent(x)·255). */\nfunction referenceSrgb8(linear: number): number { return Math.round(encodeSrgbComponent(linear) * 255); }\n/** Exact 8-bit sRGB quantizer tables; see {@link srgb8Quantizer}. */\nexport interface Srgb8Quantizer {\n /** t[k]: smallest binary64 x in [0,1] with referenceSrgb8(x) ≥ k; t[256] = +∞ sentinel. */\n readonly thresholds: Float64Array;\n /** start[b]: reference code of b/4096, the first code of bucket [b/4096, (b+1)/4096). */\n readonly start: Uint8Array;\n}\nlet srgb8: Srgb8Quantizer | null | undefined;\n/**\n * Exact 8-bit sRGB quantization without evaluating the transfer curve for each sample.\n *\n * The code thresholds are found by bisection on this engine's own `encodeSrgbComponent`. Comparing\n * against them gives Math.round(encodeSrgbComponent(x)·255) for every x, provided that function never\n * decreases (true when pow is monotone). Construction checks every threshold and the 16 neighbouring\n * doubles on each side. If any check fails, the direct transfer is used instead, so output never\n * silently depends on that assumption.\n *\n * A 4097-entry bucket index (x·4096 is exact) gives the starting code. Even the steepest part of the\n * curve (slope 12.92·255) covers less than one code per bucket, so one or two comparisons finish.\n */\nfunction srgb8Quantizer(): Srgb8Quantizer | null {\n if (srgb8 !== undefined) return srgb8;\n const t = new Float64Array(257), bits = new Float64Array(1), word = new BigUint64Array(bits.buffer);\n const step = (x: number, n: number): number => { bits[0] = x; word[0] = word[0]! + BigInt(n); return bits[0]!; };\n for (let k = 1; k < 256; k++) {\n let lo = t[k - 1]!, hi = 1;\n for (;;) {\n const mid = lo + (hi - lo) / 2;\n if (mid === lo || mid === hi) break;\n if (referenceSrgb8(mid) >= k) hi = mid; else lo = mid;\n }\n t[k] = hi;\n }\n t[256] = Infinity;\n let valid = referenceSrgb8(0) === 0 && referenceSrgb8(1) === 255;\n for (let k = 1; valid && k < 256; k++) {\n const x = t[k]!;\n if (!(x > t[k - 1]!) || referenceSrgb8(x) !== k) valid = false;\n for (let n = 1; valid && n <= 16; n++) {\n const below = step(x, -n), above = step(x, n);\n if ((below >= 0 && referenceSrgb8(below) >= k) || (above <= 1 && referenceSrgb8(above) < k)) valid = false;\n }\n }\n const start = new Uint8Array(4097);\n for (let i = 0; valid && i <= 4096; i++) { start[i] = referenceSrgb8(i / 4096); if (i > 0 && start[i]! < start[i - 1]!) valid = false; }\n srgb8 = valid ? { thresholds: t, start } : null;\n return srgb8;\n}\n/** Largest k with t[k] ≤ x for x in [0,1]. */\nfunction quantizeSrgb8(q: Srgb8Quantizer, x: number): number {\n const t = q.thresholds;\n let k = q.start[(x * 4096) | 0]!;\n while (x >= t[k + 1]!) k++;\n return k;\n}\n/** Internal, for tests: the exact quantizer (null when its construction check failed). */\nexport function nativeSrgb8QuantizerForTest(): { quantizer: Srgb8Quantizer | null; quantize(x: number): number } {\n const quantizer = srgb8Quantizer();\n return { quantizer, quantize: (x) => quantizer ? quantizeSrgb8(quantizer, x) : referenceSrgb8(x) };\n}\n/** Per-tile counters for {@link renderSdrRunInto}. `outOfGamut` delays the rejection, as the reference does. */\nexport interface SdrPixelCounts { negative: number; above: number; changed: number; low: number; high: number; outOfGamut: boolean }\n/**\n * Internal SDR kernel on typed arrays, shared by native SDR and RAW development.\n *\n * For `pixelCount` interleaved linear-sRGB pixels starting at `source[start]`, it runs exactly the\n * reference (`calculateSdrRendering`) operations in the same order per pixel: -0 → +0 → rendering\n * exposure → shared tone operator → gamut → sRGB transfer → quantization (nearest, ties up) into\n * `codes[outOffset]` (with `maximum` 0, the encoded value unquantized). A gamut rejection is delayed via `counts.outOfGamut`, because the reference\n * finishes the whole tone pass (and its exposure errors) first. `scratch` must hold at least 3\n * values. Not exported from the package.\n */\nexport function renderSdrRunInto(source: Float32Array | Float64Array, start: number, pixelCount: number, profile: SdrRenderingProfile,\n tone: SdrPixelTone, scale: number, maximum: number, codes: Uint8Array | Uint16Array | Float64Array, outOffset: number, scratch: Float64Array, counts: SdrPixelCounts): void {\n const reject = profile.gamutHandling === \"reject-out-of-range\", quantizer = maximum === 255 ? srgb8Quantizer() : null;\n let negative = 0, above = 0, changed = 0, low = 0, high = 0, outOfGamut = false;\n for (let p = 0, i = start, o = outOffset; p < pixelCount; p++, i += 3) {\n // The reference parser normalizes -0 to +0 before exposure.\n const red = source[i]!, green = source[i + 1]!, blue = source[i + 2]!;\n const er = (red === 0 ? 0 : red) * scale, eg = (green === 0 ? 0 : green) * scale, eb = (blue === 0 ? 0 : blue) * scale;\n if (!Number.isFinite(er) || !Number.isFinite(eg) || !Number.isFinite(eb)) throw new InvalidScientificResultError(\"Rendering exposure produced a non-finite sample.\");\n tone(er, eg, eb, scratch);\n for (let c = 0; c < 3; c++, o++) {\n const exposed = c === 0 ? er : c === 1 ? eg : eb;\n if (exposed < 0) negative++;\n if (exposed > 1) above++;\n let mapped = scratch[c]!;\n if (mapped !== exposed) changed++;\n if (mapped === 0) mapped = 0;\n let linear = mapped;\n if (mapped < 0 || mapped > 1) {\n if (reject) outOfGamut = true;\n else if (mapped < 0) { low++; linear = 0; }\n else { high++; linear = 1; }\n }\n // Encoded values are in [0,1]: Math.round is exact nearest-ties-up here.\n // maximum 0 (#571): the encoded value itself, unquantized, into a Float64Array (the unsharp mask's input).\n codes[o] = quantizer ? quantizeSrgb8(quantizer, linear) : maximum === 0 ? encodeSrgbComponent(linear) : Math.round(encodeSrgbComponent(linear) * maximum);\n }\n }\n counts.negative += negative; counts.above += above; counts.changed += changed; counts.low += low; counts.high += high;\n if (outOfGamut) counts.outOfGamut = true;\n}\n\n/** The reference's output-encoding declaration for the given code maximum. */\nexport function sdrOutputEncoding(maximum: number): SdrRenderingResult[\"outputEncoding\"] {\n return { imageState: \"output-referred-sdr\", colorSpace: \"srgb\", primariesXy: { red: [.64, .33], green: [.30, .60], blue: [.15, .06] },\n whitePointXy: [.3127, .3290], referenceWhiteLuminanceCdM2: 80, codeMinimum: 0, codeMaximum: maximum };\n}\n\n/** A single-use task. No partial output is ever returned, and cancel or dispose stops a late result from being published. */\nexport interface NativeCaptureSdrTask {\n readonly plan: NativeCaptureSdrPlan;\n readonly state: NativeCaptureSdrTaskState;\n readonly completedTileCount: number;\n run(): Promise<void>;\n cancel(): void;\n dispose(): void;\n /** Hands over the only copy of the output buffer, once. Dispose cannot take back a buffer already handed over. */\n takeOutput(): NativeCaptureSdrOutput;\n}\n/** Creates a single-use task. Limits are checked before any buffer is allocated or tile is read. */\nexport function createNativeCaptureSdrTask(input: NativeCaptureSdrInput, provider: NativeCaptureSdrProvider): NativeCaptureSdrTask {\n const plan = calculateNativeCaptureSdrPlan(input);\n if (!provider || typeof provider.readTile !== \"function\" || typeof provider.yieldControl !== \"function\") {\n throw new InvalidConfigurationError(\"Native SDR requires a tile reader and event-loop yield.\");\n }\n if (provider.onProgress !== undefined && typeof provider.onProgress !== \"function\") throw new InvalidConfigurationError(\"Native SDR onProgress must be a function.\");\n // Also capture the callback functions now, so later app changes cannot swap the reader mid-task.\n const readTile = provider.readTile.bind(provider), yieldControl = provider.yieldControl.bind(provider),\n onProgress = provider.onProgress?.bind(provider);\n const plane = plan.capture.planes.find(p => p.id === plan.sourcePlaneId)!;\n if (plane.storage.kind === \"inline-float64\") throw new InvalidConfigurationError(\"External native source required.\");\n const storage = plane.storage, abort = new AbortController();\n let state: NativeCaptureSdrTaskState = \"ready\", count = 0, output: NativeCaptureSdrOutput | null = null;\n let codes: Uint8Array | Uint16Array | null = null;\n function release(): void { codes?.fill(0); codes = null; output = null; }\n function checkActive(): void {\n if (abort.signal.aborted) throw new InvalidConfigurationError(\"Native SDR task cancelled/disposed; no output available.\");\n }\n return {\n plan,\n get state(): NativeCaptureSdrTaskState { return state; },\n get completedTileCount(): number { return count; },\n async run(): Promise<void> {\n if (state !== \"ready\") throw new InvalidConfigurationError(\"Native SDR task is single-use.\");\n state = \"running\";\n try {\n codes = plan.profile.bitDepth === 8 ? new Uint8Array(plan.outputBytes) : new Uint16Array(plan.outputBytes / 2);\n const diagnostics: SdrRenderingResult[\"diagnostics\"] = { renderingNegativeSampleCount: 0, renderingAboveReferenceSampleCount: 0,\n toneChangedSampleCount: 0, gamutClippedLowSampleCount: 0, gamutClippedHighSampleCount: 0, captureSaturation: \"not-consumed\" };\n // Same scale expression and code range as the reference. The plan already rejected a scale that cannot be represented.\n const scale = 2 ** plan.profile.renderingExposureEv / plane.referenceWhiteValue, maximum = 2 ** plan.profile.bitDepth - 1,\n tone = prepareSdrPixelTone(plan.profile);\n for (let y = 0; y < plane.pixelHeight; y += NATIVE_CAPTURE_SDR_LIMITS.tileHeight) {\n for (let x = 0; x < plane.pixelWidth; x += NATIVE_CAPTURE_SDR_LIMITS.tileWidth) {\n checkActive();\n const request = Object.freeze({ captureId: plan.capture.captureId, sourcePlaneId: plane.id,\n artifactId: storage.artifactId, sha256: storage.sha256, x, y,\n width: Math.min(NATIVE_CAPTURE_SDR_LIMITS.tileWidth, plane.pixelWidth - x),\n height: Math.min(NATIVE_CAPTURE_SDR_LIMITS.tileHeight, plane.pixelHeight - y) });\n {\n const tile = await readTile(request, abort.signal);\n checkActive();\n // Diagnostics are aggregated only after the whole tile renders.\n renderTileInto(tile, request, plane, plan.profile, tone, scale, maximum, codes!, diagnostics);\n count++;\n onProgress?.({ completedTileCount: count, totalTileCount: plan.tileCount });\n }\n // Do not keep tile or reference arrays past the next tile read or host yield.\n await yieldControl(abort.signal);\n checkActive();\n }\n }\n output = { plan, integerSamples: codes!, diagnostics, outputEncoding: sdrOutputEncoding(maximum),\n displayAdaptation: { kind: \"external-platform\", applied: false, displayCapabilities: \"unknown\" } };\n state = \"completed\";\n } catch (error) {\n release();\n if (!abort.signal.aborted) { state = \"failed\"; abort.abort(); }\n throw error;\n }\n },\n cancel(): void {\n if (state === \"ready\" || state === \"running\" || state === \"completed\") { state = \"cancelled\"; abort.abort(); release(); }\n },\n dispose(): void { if (state !== \"transferred\") { state = \"disposed\"; abort.abort(); release(); } },\n takeOutput(): NativeCaptureSdrOutput {\n if (state !== \"completed\" || !output) throw new InvalidConfigurationError(\"Native SDR output is unavailable.\");\n const result = output; output = null; codes = null; state = \"transferred\";\n return result;\n }\n };\n}\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type SdrPixelCounts } from "../output/native-capture-sdr.js";
|
|
1
2
|
import { type SdrRenderingProfile } from "../output/sdr-rendering.js";
|
|
2
3
|
/** Version of the `development-detail` model (diffraction correction and unsharp mask). */
|
|
3
4
|
export declare const DEVELOPMENT_DETAIL_MODEL_VERSION: "0.1.0";
|
|
@@ -86,6 +87,15 @@ export declare function applyDiffractionCorrection(rgb: Float64Array, width: num
|
|
|
86
87
|
samples: Float64Array;
|
|
87
88
|
diagnostics: DiffractionCorrectionDiagnostics;
|
|
88
89
|
};
|
|
90
|
+
/** Runs a row-by-row detail stage to its end and returns its result. */
|
|
91
|
+
export declare function drainDetailRows<T>(rows: Generator<number, T, void>): T;
|
|
92
|
+
/**
|
|
93
|
+
* `applyDiffractionCorrection` in place, one output row per step (#571); each step yields the number of rows done. Output row y
|
|
94
|
+
* reads input rows y − R … y + R, so it waits in a ring of R + 1 rows and replaces input row y once row y + R is done. Every sample
|
|
95
|
+
* is the same sum in the same order as in a separate output image, so the result is bit-identical, with one image in memory
|
|
96
|
+
* instead of two. `rgb` must hold width × height pixels.
|
|
97
|
+
*/
|
|
98
|
+
export declare function correctDiffractionInPlace(rgb: Float64Array, width: number, height: number, filter: Pick<DiffractionCorrectionFilter, "weights" | "settings">): Generator<number, DiffractionCorrectionDiagnostics, void>;
|
|
89
99
|
/** Normalized Gaussian weights exp(−i²/(2σ²)), i = −r..r with r = ⌈3σ⌉. */
|
|
90
100
|
export declare function unsharpMaskKernel(radiusPixels: number): Float64Array;
|
|
91
101
|
/** What the unsharp mask did. Counts are samples (one per channel). */
|
|
@@ -112,6 +122,15 @@ export declare function applyUnsharpMask(encoded: Float64Array, width: number, h
|
|
|
112
122
|
samples: Float64Array;
|
|
113
123
|
diagnostics: UnsharpMaskDiagnostics;
|
|
114
124
|
};
|
|
125
|
+
/**
|
|
126
|
+
* The unsharp mask one output row per step (#571); each step yields the number of rows done. The horizontal Gaussian pass of
|
|
127
|
+
* each input row is kept in a ring of 2r + 1 rows, and `prepareRow(y)`, when given, runs once on input row y before it is
|
|
128
|
+
* first read (`renderSdrWithUnsharpMaskInPlace` encodes the row there). Output row y goes to `out`: the clipped value, or
|
|
129
|
+
* Math.round(value · scale) with a `scale`. Every sum is the same, in the same order, as in whole-image passes, so the
|
|
130
|
+
* result is bit-identical, with 2r + 1 rows of working memory instead of three images. `settings` must be parsed and the
|
|
131
|
+
* raster sizes must match.
|
|
132
|
+
*/
|
|
133
|
+
export declare function unsharpMaskRows(encoded: Float64Array, width: number, height: number, settings: UnsharpMaskSettings, out: Float64Array | Uint8Array | Uint16Array, scale?: number, prepareRow?: (y: number) => void): Generator<number, UnsharpMaskDiagnostics, void>;
|
|
115
134
|
/** SDR counters in the shape of the SDR rendering diagnostics. */
|
|
116
135
|
export interface DetailSdrCounts {
|
|
117
136
|
negative: number;
|
|
@@ -130,3 +149,13 @@ export declare function renderSdrWithUnsharpMask(rgb: Float64Array, width: numbe
|
|
|
130
149
|
counts: DetailSdrCounts;
|
|
131
150
|
sharpening: UnsharpMaskDiagnostics;
|
|
132
151
|
};
|
|
152
|
+
/**
|
|
153
|
+
* `renderSdrWithUnsharpMask` one output row per step (#571), encoding each row of `rgb` in place just before the mask first reads
|
|
154
|
+
* it (`rgb` then holds the encoded values). Bit-identical to the whole-image function, with no second image in memory. `settings`
|
|
155
|
+
* must be parsed and `rgb` must hold width × height pixels.
|
|
156
|
+
*/
|
|
157
|
+
export declare function renderSdrWithUnsharpMaskInPlace(rgb: Float64Array, width: number, height: number, profile: SdrRenderingProfile, settings: UnsharpMaskSettings): Generator<number, {
|
|
158
|
+
codes: Uint8Array | Uint16Array;
|
|
159
|
+
counts: SdrPixelCounts;
|
|
160
|
+
sharpening: UnsharpMaskDiagnostics;
|
|
161
|
+
}, void>;
|
|
@@ -12,12 +12,13 @@
|
|
|
12
12
|
* Development order with these stages: (exposure gain) → demosaic → colour and white balance → diffraction correction
|
|
13
13
|
* (linear) → rendering exposure and tone curve → gamut handling → sRGB transfer → unsharp mask → quantization (encode).
|
|
14
14
|
*
|
|
15
|
-
* Image edges are handled by clamping (edge pixels repeated). Both stages
|
|
15
|
+
* Image edges are handled by clamping (edge pixels repeated). Both stages need the whole image; since #571 they also run row by
|
|
16
|
+
* row in place (`correctDiffractionInPlace`, `renderSdrWithUnsharpMaskInPlace`), with the same sums in the same order.
|
|
16
17
|
* @see docs/DIGITAL_OPTICS_FOUNDATION.md for the equations, sources, trade-offs and limits.
|
|
17
18
|
*/
|
|
18
|
-
import { encodeSrgbComponent } from "../color/srgb-transfer.js";
|
|
19
19
|
import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
20
20
|
import { InvalidScientificResultError } from "../core/validation.js";
|
|
21
|
+
import { renderSdrRunInto } from "../output/native-capture-sdr.js";
|
|
21
22
|
import { prepareSdrPixelTone } from "../output/sdr-rendering.js";
|
|
22
23
|
/** Version of the `development-detail` model (diffraction correction and unsharp mask). */
|
|
23
24
|
export const DEVELOPMENT_DETAIL_MODEL_VERSION = "0.1.0";
|
|
@@ -158,38 +159,62 @@ export function evaluateDiffractionCorrectionResponse(weights, radius, fx, fy) {
|
|
|
158
159
|
export function applyDiffractionCorrection(rgb, width, height, filter) {
|
|
159
160
|
if (rgb.length !== width * height * 3)
|
|
160
161
|
throw new InvalidConfigurationError("Diffraction correction raster size mismatch.");
|
|
161
|
-
const
|
|
162
|
+
const samples = Float64Array.from(rgb);
|
|
163
|
+
return { samples, diagnostics: drainDetailRows(correctDiffractionInPlace(samples, width, height, filter)) };
|
|
164
|
+
}
|
|
165
|
+
/** Runs a row-by-row detail stage to its end and returns its result. */
|
|
166
|
+
export function drainDetailRows(rows) {
|
|
167
|
+
let step = rows.next();
|
|
168
|
+
while (!step.done)
|
|
169
|
+
step = rows.next();
|
|
170
|
+
return step.value;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* `applyDiffractionCorrection` in place, one output row per step (#571); each step yields the number of rows done. Output row y
|
|
174
|
+
* reads input rows y − R … y + R, so it waits in a ring of R + 1 rows and replaces input row y once row y + R is done. Every sample
|
|
175
|
+
* is the same sum in the same order as in a separate output image, so the result is bit-identical, with one image in memory
|
|
176
|
+
* instead of two. `rgb` must hold width × height pixels.
|
|
177
|
+
*/
|
|
178
|
+
export function* correctDiffractionInPlace(rgb, width, height, filter) {
|
|
179
|
+
const R = filter.settings.kernelRadiusPixels, size = 2 * R + 1, w = filter.weights, rowLength = width * 3, ring = new Float64Array((R + 1) * rowLength);
|
|
162
180
|
const xs = new Int32Array(width + 2 * R);
|
|
163
181
|
for (let i = 0; i < xs.length; i++)
|
|
164
182
|
xs[i] = Math.min(width - 1, Math.max(0, i - R)) * 3;
|
|
165
183
|
let negative = 0, above = 0;
|
|
166
|
-
for (let y = 0; y
|
|
167
|
-
|
|
184
|
+
for (let y = 0; y <= height + R; y++) {
|
|
185
|
+
// Output row y − R − 1 holds the slot of row y; input row y − R − 1 is read by no later output row, so it takes its place.
|
|
186
|
+
const o = (y % (R + 1)) * rowLength;
|
|
187
|
+
if (y > R)
|
|
188
|
+
rgb.set(ring.subarray(o, o + rowLength), (y - R - 1) * rowLength);
|
|
189
|
+
if (y >= height)
|
|
190
|
+
continue;
|
|
191
|
+
ring.fill(0, o, o + rowLength);
|
|
168
192
|
for (let dy = -R; dy <= R; dy++) {
|
|
169
|
-
const row = Math.min(height - 1, Math.max(0, y + dy)) *
|
|
193
|
+
const row = Math.min(height - 1, Math.max(0, y + dy)) * rowLength, wr = (dy + R) * size;
|
|
170
194
|
for (let dx = 0; dx < size; dx++) {
|
|
171
195
|
const weight = w[wr + dx];
|
|
172
196
|
if (weight === 0)
|
|
173
197
|
continue;
|
|
174
198
|
for (let x = 0; x < width; x++) {
|
|
175
199
|
const s = row + xs[x + dx], d = o + 3 * x;
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
200
|
+
ring[d] = ring[d] + weight * rgb[s];
|
|
201
|
+
ring[d + 1] = ring[d + 1] + weight * rgb[s + 1];
|
|
202
|
+
ring[d + 2] = ring[d + 2] + weight * rgb[s + 2];
|
|
179
203
|
}
|
|
180
204
|
}
|
|
181
205
|
}
|
|
206
|
+
for (let i = o; i < o + rowLength; i++) {
|
|
207
|
+
const v = ring[i];
|
|
208
|
+
if (!Number.isFinite(v))
|
|
209
|
+
throw new InvalidScientificResultError("Diffraction correction produced a non-finite sample.");
|
|
210
|
+
if (v < 0)
|
|
211
|
+
negative++;
|
|
212
|
+
else if (v > 1)
|
|
213
|
+
above++;
|
|
214
|
+
}
|
|
215
|
+
yield y + 1;
|
|
182
216
|
}
|
|
183
|
-
|
|
184
|
-
const v = out[i];
|
|
185
|
-
if (!Number.isFinite(v))
|
|
186
|
-
throw new InvalidScientificResultError("Diffraction correction produced a non-finite sample.");
|
|
187
|
-
if (v < 0)
|
|
188
|
-
negative++;
|
|
189
|
-
else if (v > 1)
|
|
190
|
-
above++;
|
|
191
|
-
}
|
|
192
|
-
return { samples: out, diagnostics: { negativeSampleCount: negative, aboveWhiteSampleCount: above } };
|
|
217
|
+
return { negativeSampleCount: negative, aboveWhiteSampleCount: above };
|
|
193
218
|
}
|
|
194
219
|
/** Normalized Gaussian weights exp(−i²/(2σ²)), i = −r..r with r = ⌈3σ⌉. */
|
|
195
220
|
export function unsharpMaskKernel(radiusPixels) {
|
|
@@ -213,64 +238,79 @@ export function applyUnsharpMask(encoded, width, height, settings) {
|
|
|
213
238
|
const s = parseUnsharpMaskSettings(settings);
|
|
214
239
|
if (encoded.length !== width * height * 3)
|
|
215
240
|
throw new InvalidConfigurationError("Unsharp mask raster size mismatch.");
|
|
216
|
-
const
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
241
|
+
const samples = new Float64Array(encoded.length);
|
|
242
|
+
return { samples, diagnostics: drainDetailRows(unsharpMaskRows(encoded, width, height, s, samples)) };
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* The unsharp mask one output row per step (#571); each step yields the number of rows done. The horizontal Gaussian pass of
|
|
246
|
+
* each input row is kept in a ring of 2r + 1 rows, and `prepareRow(y)`, when given, runs once on input row y before it is
|
|
247
|
+
* first read (`renderSdrWithUnsharpMaskInPlace` encodes the row there). Output row y goes to `out`: the clipped value, or
|
|
248
|
+
* Math.round(value · scale) with a `scale`. Every sum is the same, in the same order, as in whole-image passes, so the
|
|
249
|
+
* result is bit-identical, with 2r + 1 rows of working memory instead of three images. `settings` must be parsed and the
|
|
250
|
+
* raster sizes must match.
|
|
251
|
+
*/
|
|
252
|
+
export function* unsharpMaskRows(encoded, width, height, settings, out, scale, prepareRow) {
|
|
253
|
+
const k = unsharpMaskKernel(settings.radiusPixels), r = (k.length - 1) / 2, span = 2 * r + 1, rowLength = width * 3, ring = new Float64Array(span * rowLength);
|
|
254
|
+
const amount = settings.amount, threshold = settings.threshold;
|
|
255
|
+
let sharpened = 0, held = 0, low = 0, high = 0, increase = 0, decrease = 0, ready = 0;
|
|
256
|
+
for (let y = 0; y < height; y++) {
|
|
257
|
+
// Rows up to y + r, prepared and horizontally blurred.
|
|
258
|
+
for (const last = Math.min(height - 1, y + r); ready <= last; ready++) {
|
|
259
|
+
prepareRow?.(ready);
|
|
260
|
+
const source = ready * rowLength, slot = (ready % span) * rowLength;
|
|
261
|
+
for (let x = 0; x < width; x++) {
|
|
262
|
+
let a = 0, b = 0, c = 0;
|
|
263
|
+
for (let i = -r; i <= r; i++) {
|
|
264
|
+
const sx = source + Math.min(width - 1, Math.max(0, x + i)) * 3, w = k[i + r];
|
|
265
|
+
a += w * encoded[sx];
|
|
266
|
+
b += w * encoded[sx + 1];
|
|
267
|
+
c += w * encoded[sx + 2];
|
|
268
|
+
}
|
|
269
|
+
ring[slot + 3 * x] = a;
|
|
270
|
+
ring[slot + 3 * x + 1] = b;
|
|
271
|
+
ring[slot + 3 * x + 2] = c;
|
|
226
272
|
}
|
|
227
|
-
horizontal[d] = a;
|
|
228
|
-
horizontal[d + 1] = b;
|
|
229
|
-
horizontal[d + 2] = c;
|
|
230
273
|
}
|
|
231
|
-
|
|
274
|
+
const o = y * rowLength;
|
|
232
275
|
for (let x = 0; x < width; x++) {
|
|
233
|
-
const d = (y * width + x) * 3;
|
|
234
276
|
let a = 0, b = 0, c = 0;
|
|
235
277
|
for (let i = -r; i <= r; i++) {
|
|
236
|
-
const sy = (Math.min(height - 1, Math.max(0, y + i)) *
|
|
237
|
-
a += w *
|
|
238
|
-
b += w *
|
|
239
|
-
c += w *
|
|
278
|
+
const sy = (Math.min(height - 1, Math.max(0, y + i)) % span) * rowLength + 3 * x, w = k[i + r];
|
|
279
|
+
a += w * ring[sy];
|
|
280
|
+
b += w * ring[sy + 1];
|
|
281
|
+
c += w * ring[sy + 2];
|
|
282
|
+
}
|
|
283
|
+
for (let channel = 0; channel < 3; channel++) {
|
|
284
|
+
const index = o + 3 * x + channel, value = encoded[index], detail = value - (channel === 0 ? a : channel === 1 ? b : c);
|
|
285
|
+
let v = value;
|
|
286
|
+
if (detail === 0 || Math.abs(detail) < threshold) {
|
|
287
|
+
if (detail !== 0)
|
|
288
|
+
held++;
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
const change = amount * detail;
|
|
292
|
+
v = value + change;
|
|
293
|
+
sharpened++;
|
|
294
|
+
if (change > increase)
|
|
295
|
+
increase = change;
|
|
296
|
+
if (-change > decrease)
|
|
297
|
+
decrease = -change;
|
|
298
|
+
if (v < 0) {
|
|
299
|
+
v = 0;
|
|
300
|
+
low++;
|
|
301
|
+
}
|
|
302
|
+
else if (v > 1) {
|
|
303
|
+
v = 1;
|
|
304
|
+
high++;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
out[index] = scale === undefined ? v : Math.round(v * scale);
|
|
240
308
|
}
|
|
241
|
-
blurred[d] = a;
|
|
242
|
-
blurred[d + 1] = b;
|
|
243
|
-
blurred[d + 2] = c;
|
|
244
|
-
}
|
|
245
|
-
const out = new Float64Array(encoded.length);
|
|
246
|
-
let sharpened = 0, held = 0, low = 0, high = 0, increase = 0, decrease = 0;
|
|
247
|
-
for (let i = 0; i < encoded.length; i++) {
|
|
248
|
-
const x = encoded[i], detail = x - blurred[i];
|
|
249
|
-
if (detail === 0 || Math.abs(detail) < s.threshold) {
|
|
250
|
-
if (detail !== 0)
|
|
251
|
-
held++;
|
|
252
|
-
out[i] = x;
|
|
253
|
-
continue;
|
|
254
|
-
}
|
|
255
|
-
const change = s.amount * detail;
|
|
256
|
-
let v = x + change;
|
|
257
|
-
sharpened++;
|
|
258
|
-
if (change > increase)
|
|
259
|
-
increase = change;
|
|
260
|
-
if (-change > decrease)
|
|
261
|
-
decrease = -change;
|
|
262
|
-
if (v < 0) {
|
|
263
|
-
v = 0;
|
|
264
|
-
low++;
|
|
265
|
-
}
|
|
266
|
-
else if (v > 1) {
|
|
267
|
-
v = 1;
|
|
268
|
-
high++;
|
|
269
309
|
}
|
|
270
|
-
|
|
310
|
+
yield y + 1;
|
|
271
311
|
}
|
|
272
|
-
return {
|
|
273
|
-
|
|
312
|
+
return { kernelRadiusPixels: r, sharpenedSampleCount: sharpened, thresholdHeldSampleCount: held, clippedLowSampleCount: low,
|
|
313
|
+
clippedHighSampleCount: high, maximumIncrease: increase, maximumDecrease: decrease };
|
|
274
314
|
}
|
|
275
315
|
/**
|
|
276
316
|
* SDR rendering with an unsharp mask between the sRGB transfer and quantization. Per pixel it runs the reference renderer's
|
|
@@ -280,46 +320,27 @@ export function applyUnsharpMask(encoded, width, height, settings) {
|
|
|
280
320
|
export function renderSdrWithUnsharpMask(rgb, width, height, profile, settings) {
|
|
281
321
|
if (rgb.length !== width * height * 3)
|
|
282
322
|
throw new InvalidConfigurationError("SDR raster size mismatch.");
|
|
283
|
-
const
|
|
323
|
+
const { codes, counts: { negative, above, changed, low, high }, sharpening } = drainDetailRows(renderSdrWithUnsharpMaskInPlace(Float64Array.from(rgb), width, height, profile, parseUnsharpMaskSettings(settings)));
|
|
324
|
+
return { codes, counts: { negative, above, changed, low, high }, sharpening };
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* `renderSdrWithUnsharpMask` one output row per step (#571), encoding each row of `rgb` in place just before the mask first reads
|
|
328
|
+
* it (`rgb` then holds the encoded values). Bit-identical to the whole-image function, with no second image in memory. `settings`
|
|
329
|
+
* must be parsed and `rgb` must hold width × height pixels.
|
|
330
|
+
*/
|
|
331
|
+
export function* renderSdrWithUnsharpMaskInPlace(rgb, width, height, profile, settings) {
|
|
332
|
+
const scale = 2 ** profile.renderingExposureEv, tone = prepareSdrPixelTone(profile), scratch = new Float64Array(3);
|
|
284
333
|
if (!Number.isFinite(scale) || scale <= 0)
|
|
285
334
|
throw new InvalidConfigurationError("Rendering scale is unrepresentable.");
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
if (
|
|
291
|
-
throw new
|
|
292
|
-
|
|
293
|
-
for (let c = 0; c < 3; c++) {
|
|
294
|
-
const exposed = c === 0 ? er : c === 1 ? eg : eb;
|
|
295
|
-
if (exposed < 0)
|
|
296
|
-
counts.negative++;
|
|
297
|
-
if (exposed > 1)
|
|
298
|
-
counts.above++;
|
|
299
|
-
let mapped = scratch[c];
|
|
300
|
-
if (mapped !== exposed)
|
|
301
|
-
counts.changed++;
|
|
302
|
-
if (mapped === 0)
|
|
303
|
-
mapped = 0;
|
|
304
|
-
if (mapped < 0 || mapped > 1) {
|
|
305
|
-
if (reject)
|
|
306
|
-
throw new InvalidConfigurationError("Tone output exceeds the declared SDR gamut range.");
|
|
307
|
-
if (mapped < 0) {
|
|
308
|
-
counts.low++;
|
|
309
|
-
mapped = 0;
|
|
310
|
-
}
|
|
311
|
-
else {
|
|
312
|
-
counts.high++;
|
|
313
|
-
mapped = 1;
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
encoded[i + c] = encodeSrgbComponent(mapped);
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
const sharpened = applyUnsharpMask(encoded, width, height, settings), maximum = 2 ** profile.bitDepth - 1;
|
|
335
|
+
const counts = { negative: 0, above: 0, changed: 0, low: 0, high: 0, outOfGamut: false };
|
|
336
|
+
// The native SDR kernel per row, unquantized (maximum 0), in place: the reference renderer's operations in its order.
|
|
337
|
+
const encodeRow = (y) => {
|
|
338
|
+
renderSdrRunInto(rgb, y * width * 3, width, profile, tone, scale, 0, rgb, y * width * 3, scratch, counts);
|
|
339
|
+
if (counts.outOfGamut)
|
|
340
|
+
throw new InvalidConfigurationError("Tone output exceeds the declared SDR gamut range.");
|
|
341
|
+
};
|
|
320
342
|
const codes = profile.bitDepth === 8 ? new Uint8Array(rgb.length) : new Uint16Array(rgb.length);
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
return { codes, counts, sharpening: sharpened.diagnostics };
|
|
343
|
+
const sharpening = yield* unsharpMaskRows(rgb, width, height, settings, codes, 2 ** profile.bitDepth - 1, encodeRow);
|
|
344
|
+
return { codes, counts, sharpening };
|
|
324
345
|
}
|
|
325
346
|
//# sourceMappingURL=development-detail.js.map
|