@photivra/engine 2.0.0 → 2.2.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 +39 -1
- package/CITATION.cff +1 -1
- package/README.md +6 -6
- package/SECURITY.md +1 -1
- package/dist/capture/export-jpeg.js +7 -1
- package/dist/capture/export-jpeg.js.map +1 -1
- package/dist/capture/native-environment-lean.js +5 -2
- package/dist/capture/native-environment-lean.js.map +1 -1
- package/dist/capture/native-environment-raw.js +2 -2
- package/dist/capture/native-environment-raw.js.map +1 -1
- package/dist/capture/native-raw-development.js +1 -1
- package/dist/capture/native-raw-development.js.map +1 -1
- package/dist/capture/native-raw.d.ts +16 -0
- package/dist/capture/native-raw.js +16 -3
- package/dist/capture/native-raw.js.map +1 -1
- package/dist/capture/packed-sensor-raw.d.ts +7 -0
- package/dist/capture/packed-sensor-raw.js +6 -2
- package/dist/capture/packed-sensor-raw.js.map +1 -1
- package/dist/core/pixel-limits.d.ts +14 -0
- package/dist/core/pixel-limits.js +40 -0
- package/dist/core/pixel-limits.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/chart-radiance-batch.d.ts +7 -0
- package/dist/facade/chart-radiance-batch.js +7 -3
- package/dist/facade/chart-radiance-batch.js.map +1 -1
- package/dist/facade/diffraction-provider.d.ts +30 -0
- package/dist/facade/diffraction-provider.js +127 -0
- package/dist/facade/diffraction-provider.js.map +1 -0
- package/dist/facade/host-yield.d.ts +1 -1
- package/dist/facade/host-yield.js +0 -4
- package/dist/facade/host-yield.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +88 -2
- package/dist/facade/simulate-capture.js +343 -41
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/motion/temporal-exposure-sum.d.ts +7 -0
- package/dist/motion/temporal-exposure-sum.js +6 -2
- package/dist/motion/temporal-exposure-sum.js.map +1 -1
- package/dist/optics/diffraction-psf-profile.d.ts +118 -0
- package/dist/optics/diffraction-psf-profile.js +252 -0
- package/dist/optics/diffraction-psf-profile.js.map +1 -0
- package/dist/optics/irradiance-convolution.d.ts +7 -0
- package/dist/optics/irradiance-convolution.js +6 -2
- package/dist/optics/irradiance-convolution.js.map +1 -1
- package/dist/output/native-capture-sdr.d.ts +7 -0
- package/dist/output/native-capture-sdr.js +6 -3
- package/dist/output/native-capture-sdr.js.map +1 -1
- package/dist/output/png-encoder.d.ts +10 -1
- package/dist/output/png-encoder.js +10 -4
- package/dist/output/png-encoder.js.map +1 -1
- package/dist/output/print-jpeg.d.ts +18 -0
- package/dist/output/print-jpeg.js +15 -4
- package/dist/output/print-jpeg.js.map +1 -1
- package/dist/sensor/sampling-aperture.d.ts +15 -0
- package/dist/sensor/sampling-aperture.js +31 -10
- package/dist/sensor/sampling-aperture.js.map +1 -1
- package/docs/API_REFERENCE.md +27 -1
- package/docs/QUICK_START.md +285 -13
- package/docs/USAGE.md +3 -1
- package/docs/api/capture-native-raw.md +11 -2
- package/docs/api/capture-packed-sensor-raw.md +7 -1
- package/docs/api/core-pixel-limits.md +19 -0
- package/docs/api/core-version.md +1 -1
- package/docs/api/exports.json +62 -2
- package/docs/api/facade-chart-radiance-batch.md +8 -2
- package/docs/api/facade-simulate-capture.md +83 -3
- package/docs/api/motion-temporal-exposure-sum.md +7 -1
- package/docs/api/optics-diffraction-psf-profile.md +96 -0
- package/docs/api/optics-irradiance-convolution.md +7 -1
- package/docs/api/output-native-capture-sdr.md +7 -2
- package/docs/api/output-png-encoder.md +8 -1
- package/docs/api/output-print-jpeg.md +17 -0
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,44 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 2.
|
|
3
|
+
## 2.2.0 — unreleased (prepared October 17, 2026)
|
|
4
|
+
|
|
5
|
+
A minor release: opt-in pixel limits for full-resolution images up to 2^27 pixels (about 100 MP sensors) with a measured cost table (#337), and two `simulateCapture` fixes: pixel pitches that failed the aperture fit by a rounding error now work, and image brightness no longer depends on pixel size (#336). Without the new inputs, and at the default 6 µm pitch, every request, plan, RAW, image and encoded file is byte-identical to 2.1.0; at other pitches the brightness fix changes the output by design. Root exports grow from 1,677 to 1,680 symbols; none is removed.
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **Opt-in limits for full-resolution images up to about 100 MP.** Each full-resolution stage that admitted at most 24 000 000 pixels gains an optional input of the same name as its limit, bounded by a new ceiling of 2^27 = 134 217 728 pixels (16 384 × 8 192), enough for 12 252 × 8 168 (100.07 MP) and 11 552 × 8 664 (100.09 MP) sensors plus their demosaic margin: `maximumPixels` on native RAW (`NATIVE_RAW_LIMITS.ceilingPixels`), native capture SDR, irradiance convolution and temporal exposure sum; `maximumRegionSites` on `simulatePackedSensorRaw`; `maximumQueries` on `calculateChartRadianceBatch`; `maximumPixels` on Print JPEG (new `PRINT_JPEG_LIMITS`) and on `serializePngImage` (default still 100 000 000). Each value must be a safe integer from 1 to the ceiling. A raised native RAW limit is recorded in the plan and raises the native environment whole-event query budget ceiling in proportion (2 000 000 000 per 24 000 000 pixels); a raised Print JPEG limit raises its `maximumEncodedBytes` ceiling the same way (256 000 000 bytes per 24 000 000 pixels) and is recorded in the JPEG's XMP plan. Byte budgets (`maximumOutputBytes` and similar) still apply. New constants `FULL_RESOLUTION_DEFAULT_PIXELS` and `FULL_RESOLUTION_CEILING_PIXELS`.
|
|
10
|
+
- **`simulateCapture` `output.maximumPixels`.** Opt-in large captures: the most native sensor sites (output plus demosaic margin) the capture may allocate, up to 2^27. With it `output.width` and `output.height` may reach 16 384 sites including the margin instead of 4094; it is passed to the RAW, development, DNG, PNG and JPEG stages, and lifts the 1 GiB working-memory default of the AHD demosaic (which still admits at most 2^26 sites, checked before any work).
|
|
11
|
+
- **Measured cost of large images.** The quick start's new "Large images" section gives the measured time and peak memory per megapixel of each full-resolution stage at 1, 4, 16, 24 and 100 MP in Node (for example 100 MP 8-bit PNG 22.7 s, 1:1 JPEG 69.7 s, RAW development 20.5 s), and `simulateCapture` measured up to 16 MP (about 125 s per MP, 34 bytes per pixel at peak) and extrapolated to 100 MP (about 3.4 h on one core and 3.4 GB). Large sizes are opt-in because they are slow and memory-hungry; browsers may fail to allocate them.
|
|
12
|
+
|
|
13
|
+
Defaults are unchanged: without the new inputs every request, plan, RAW, image and encoded file is byte-identical to 2.1.0.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **`simulateCapture` rejected about a quarter of pixel pitches.** For pitches such as 9.287925696594426 µm (36 mm / 3876 px) a capture failed with `INVALID_SCIENTIFIC_INPUT` "Declared geometric sensitive aperture does not fit within the supplied physical imaging area". The facade gives the imaging width as `n · pitch / 1000` mm, and `resolveSensorSamplingAperture` compared it, converted back to micrometres, with the far aperture edge `pitch/2 + (n − 1)·pitch + pitch/2`: the same exact value reached by different rounded operations, which can differ by one unit in the last place. The lattice and aperture fit tests now allow 8 ε (about 1.8 × 10⁻¹⁵) of the imaging extent for rounding; anything larger is still rejected (a 10⁻⁹ µm excess is tested). The lean environment path uses the same allowance. A test sweeps 107 pitches of nine sensor formats at twelve resolutions plus 200 seeded pitches in 0.5–100 µm, at output sizes 32–96 with both border modes and AHD.
|
|
18
|
+
- **`simulateCapture` brightness depended on pixel size.** The tier's ISO signal chain and 60 000 e⁻ charge capacity were applied per pixel at every pitch, so the same exposure gave a darker image with smaller pixels (full frame, f/8, 1/125 s, ISO 100, 18 % grey: 8-bit sRGB mean 49.5 at 100 MP, 101.2 at 24 MP, 255 clipped at 1 MP). The facade now scales the conversion gain and saturation signal of every ISO regime with the pixel area relative to 6 µm, following standard output sensitivity S = 10/H (CIPA DC-004-2020 §3.2), which is independent of pixel size, and the photon count μp = A·E·t/(hν) (EMVA 1288 Release 4.0, Eq. 3). Brightness is now 101.2 at every full-frame resolution and per-pixel noise rises as pixels shrink (green standard deviation 0.18 codes at 29.4 µm, 0.93 at 6 µm, 1.83 at 2.9 µm). Read noise and dark current stay per pixel. The charge capacity follows the scaled saturation signal; this keeps the tier's ISO rating and highlight headroom and is labelled as an approximation, not a full-well model (see docs/QUICK_START.md, "ISO and pixel size"). A new assumption `sensor.isoAreaNormalization` records it when the pitch is not 6 µm. At the default 6 µm every output, assumption and hash lock is unchanged.
|
|
19
|
+
|
|
20
|
+
## 2.1.0 — published October 17, 2026
|
|
21
|
+
|
|
22
|
+
A minor release: additive, opt-in capture options for diffraction, AHD demosaicing and an optical anti-aliasing filter, per-run cost diagnostics and a measured cost table, and a fix for cancelling captures in Web Workers (#331–#333). Captures that use none of the new options are byte-identical to 2.0.0. Root exports grow from 1,668 to 1,677 symbols; none is removed.
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- **`createDiffractionLimitedPsfProfile`.** A sampled lens PSF profile (`LensSampledPsfProfile`) for an ideal, aberration-free, in-focus lens with a circular pupil: one unit-sum Airy kernel per wavelength on one shared grid. The engine integrates each cell from the circular-pupil OTF, reports the tail energy outside the window per wavelength, and renormalizes. Scalar Fraunhofer approximation; see `docs/PSF_FOUNDATION.md`.
|
|
27
|
+
- **`simulateCapture` `lens.diffraction`.** Opt-in diffraction blur at the capture's resolved f-number (`"circular-aperture"`, optional `kernelRadiusSamples`). Stopping down now softens the image: at 128 × 128 the slanted-edge 10–90 % width grows from 1.49 px (no diffraction) to 1.56, 1.69 and 2.73 px at f/4, f/8 and f/16. `result.request.diffraction` holds the profile and how it was applied.
|
|
28
|
+
- **`simulateCapture` `sensor.antiAliasing`.** Opt-in optical low-pass (anti-aliasing) filter: a birefringent `"four-spot"` or `"two-spot"` point splitter (default separation one pixel, first MTF zero at Nyquist) or caller `"point-splitting"` components, passed to the engine's existing point-splitting optical-stack kernel. On a 128 × 128 Siemens star at f/8 it halves the false colour (100.8 → 52.2 bilinear, 68.7 → 25.1 AHD) and widens the slanted edge from 1.49 to 2.34 px. It multiplies the scene queries by the number of spots; with `lens.diffraction` the object-space convolution still applies (one convolution per distinct sub-site shift, tested against the per-tap quadrature to 1e-12).
|
|
29
|
+
- **`simulateCapture` per-run cost diagnostics.** `diagnostics.options` lists the opt-ins that changed the work of a run (new constant `SIMULATE_CAPTURE_COST_OPTIONS`, type `SimulateCaptureCostOption`), and `diagnostics.timingsMs` gains `diffraction`, `demosaic` and `encode` where those stages ran, so an application can measure each option's cost on the user's device. Additive; timings never enter a digest or output byte.
|
|
30
|
+
- **Cost of each `simulateCapture` option** (docs/QUICK_START.md). Measured wall time of every opt-in that affects run time at 48 × 48 and 128 × 128 relative to the default, with method, machine and what each buys: for example anti-aliasing 2.0×, pupil sampling 2 × 8 rays 13×, auto white balance 1.9×, output formats about 1×.
|
|
31
|
+
- **`simulateCapture` `output.demosaic: "ahd"`.** Adaptive homogeneity-directed demosaicing (`createAhdDemosaicTask`) in the facade's development, which roughly halves false colour on sharp neutral chart edges.
|
|
32
|
+
|
|
33
|
+
### Performance
|
|
34
|
+
|
|
35
|
+
- **Diffraction as an object-space convolution.** For the facade's still, distortion-free planar scene, `lens.diffraction` convolves the scene radiance once per spectral node instead of querying the scene once per PSF tap. It gives the same expected signal as the per-tap environment PSF quadrature (to 1e-12 per site, tested) and takes 0.56 s instead of 13.1 s for a 48 × 48 capture at f/8 (4-vCPU Xeon, Node 24).
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
|
|
39
|
+
- **`simulateCapture` cancellation in Web Workers.** 2.0.0 yielded to the host with `scheduler.yield()` where available. Its continuations run ahead of ordinary queued tasks (WICG Prioritized Task Scheduling, continuation priorities), so a worker's cancel message waited until the whole capture finished. The facade now yields with a `MessageChannel` message, else `setImmediate`, else `setTimeout`; queued tasks, including the caller's abort, run at the next yield, and the 4 ms timer clamp is still avoided (`src/facade/host-yield.ts`). Output is unchanged. Chromium 141 worker, 128 px capture cancelled after 100 ms, three rounds: 2.0.0 ignored the cancel and finished (2.12–2.34 s), now it aborts after one tile and the next 16 px request returns 0.15–0.20 s after the cancel; an uncancelled 128 px capture takes the same time (medians 2.17 s before, 2.16 s after, six alternating rounds).
|
|
40
|
+
|
|
41
|
+
## 2.0.0 — published October 17, 2026
|
|
4
42
|
|
|
5
43
|
A major release.
|
|
6
44
|
|
package/CITATION.cff
CHANGED
|
@@ -9,7 +9,7 @@ abstract: "An open TypeScript engine for the science and mathematics of photogra
|
|
|
9
9
|
repository-code: "https://github.com/photivra/photivra"
|
|
10
10
|
url: "https://photivra.com"
|
|
11
11
|
license: "Apache-2.0"
|
|
12
|
-
version: "2.
|
|
12
|
+
version: "2.2.0"
|
|
13
13
|
keywords:
|
|
14
14
|
- photography
|
|
15
15
|
- camera optics
|
package/README.md
CHANGED
|
@@ -32,10 +32,10 @@ The source is licensed under Apache-2.0.
|
|
|
32
32
|
|
|
33
33
|
## Quick start
|
|
34
34
|
|
|
35
|
-
Install the published ESM package below. The [2.
|
|
35
|
+
Install the published ESM package below. The [2.2.0 release record](https://github.com/Photivra/photivra/blob/main/docs/RELEASE_2_2_0.md) and [changelog](https://github.com/Photivra/photivra/blob/main/CHANGELOG.md) describe the current release:
|
|
36
36
|
|
|
37
37
|
```sh
|
|
38
|
-
npm install @photivra/engine@2.
|
|
38
|
+
npm install @photivra/engine@2.2.0
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
Simulate a photograph of a test chart with a generic camera, then read the developed sRGB pixels:
|
|
@@ -75,7 +75,7 @@ console.log(horizontal.provenance);
|
|
|
75
75
|
|
|
76
76
|
Start with the [Developer Guide](https://github.com/Photivra/photivra/blob/main/docs/DEVELOPERS.md). Then use the [Usage Guide](https://github.com/Photivra/photivra/blob/main/docs/USAGE.md) and the [API reference](https://github.com/Photivra/photivra/blob/main/docs/API_REFERENCE.md), which is generated from the package exports.
|
|
77
77
|
|
|
78
|
-
Repository `main` may describe newer, unreleased work. For the stable contract, use the docs bundled in the published package, or the exact `v2.
|
|
78
|
+
Repository `main` may describe newer, unreleased work. For the stable contract, use the docs bundled in the published package, or the exact `v2.2.0` tag.
|
|
79
79
|
|
|
80
80
|
## Documentation
|
|
81
81
|
|
|
@@ -363,13 +363,13 @@ The application can then use those results, while the photography calculations t
|
|
|
363
363
|
|
|
364
364
|
## Status
|
|
365
365
|
|
|
366
|
-
- Repository package version: `2.
|
|
367
|
-
- Engine API contract: `2.
|
|
366
|
+
- Repository package version: `2.2.0` (release candidate prepared October 17, 2026; publication is separate)
|
|
367
|
+
- Engine API contract: `2.2.0`
|
|
368
368
|
- Versioned generic tier reference assets: [GENERIC_TIER_PRESETS.md](https://github.com/Photivra/photivra/blob/main/docs/GENERIC_TIER_PRESETS.md).
|
|
369
369
|
- Composed POC simulation API contract: `1.0.0`
|
|
370
370
|
- Stability: 1.0 root-package compatibility policy; bounded scientific models and independent POC contract
|
|
371
371
|
|
|
372
|
-
From 1.0.1, the package version and `ENGINE_API_VERSION` are equal. New captures/plans record 2.
|
|
372
|
+
From 1.0.1, the package version and `ENGINE_API_VERSION` are equal. New captures/plans record 2.2.0; existing archives keep their original creator identities. Schema, model and POC contract versions stay independent.
|
|
373
373
|
|
|
374
374
|
A breaking change to the root contracts now needs a new package major version. Additive and corrective changes follow [compatibility and migration](https://github.com/Photivra/photivra/blob/main/docs/RELEASE_1_3_0.md). A 1.0 package is not a claim of calibrated physical accuracy.
|
|
375
375
|
|
package/SECURITY.md
CHANGED
|
@@ -4,7 +4,7 @@ Please do not open a public issue that contains vulnerability details.
|
|
|
4
4
|
|
|
5
5
|
## Supported versions
|
|
6
6
|
|
|
7
|
-
The published 1.0.0 release started the 1.x root-package compatibility line. The current release is **1.
|
|
7
|
+
The published 1.0.0 release started the 1.x root-package compatibility line, and 2.0.0 started the 2.x line. The current release is **2.1.0**, published on October 17, 2026 (see [CHANGELOG.md](CHANGELOG.md)).
|
|
8
8
|
|
|
9
9
|
Security fixes target the current maintained development and release line. Do not assume that older 1.x releases, snapshots or pre-1.0 releases will receive fixes.
|
|
10
10
|
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* limits.
|
|
7
7
|
*/
|
|
8
8
|
import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
9
|
+
import { FULL_RESOLUTION_CEILING_PIXELS, scaleBudgetCeiling } from "../core/pixel-limits.js";
|
|
9
10
|
/**
|
|
10
11
|
* Identifies the exact byte output of the baseline encoder.
|
|
11
12
|
*
|
|
@@ -51,6 +52,11 @@ export function encodeExportJpeg(input) {
|
|
|
51
52
|
}
|
|
52
53
|
return encoder.finish();
|
|
53
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Largest byte budget the internal writer accepts: the Print JPEG budget ceiling at the largest opt-in source
|
|
57
|
+
* (256 000 000 bytes per 24 000 000 pixels at 2^27 pixels). Each caller enforces its own smaller budget.
|
|
58
|
+
*/
|
|
59
|
+
const EXPORT_JPEG_MAXIMUM_OUTPUT_BYTES = scaleBudgetCeiling(256_000_000, FULL_RESOLUTION_CEILING_PIXELS);
|
|
54
60
|
/**
|
|
55
61
|
* Internal size-limited JPEG writer. The reference export and the scalable export use exactly the same
|
|
56
62
|
* DCT and entropy-coding equations.
|
|
@@ -62,7 +68,7 @@ export function encodeExportJpeg(input) {
|
|
|
62
68
|
*/
|
|
63
69
|
export function createExportJpegEncoder(input) {
|
|
64
70
|
const { width, height, quantizationStep: q } = input;
|
|
65
|
-
if (![width, height, q, input.maximumOutputBytes].every(Number.isSafeInteger) || width < 1 || height < 1 || width > 65535 || height > 65535 || q < 1 || q > 255 || input.maximumOutputBytes < 1 || input.maximumOutputBytes >
|
|
71
|
+
if (![width, height, q, input.maximumOutputBytes].every(Number.isSafeInteger) || width < 1 || height < 1 || width > 65535 || height > 65535 || q < 1 || q > 255 || input.maximumOutputBytes < 1 || input.maximumOutputBytes > EXPORT_JPEG_MAXIMUM_OUTPUT_BYTES)
|
|
66
72
|
throw new InvalidConfigurationError("Invalid bounded JPEG encoding plan.");
|
|
67
73
|
const density = input.densityDotsPerInch;
|
|
68
74
|
if (density !== undefined && (!Number.isSafeInteger(density) || density < 1 || density > 65535))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"export-jpeg.js","sourceRoot":"","sources":["../../src/capture/export-jpeg.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Baseline JPEG encoder written for this project. It computes the DCT (discrete cosine transform)\n * directly and uses no third-party encoder source, default quantization tables or Huffman tables.\n * @see docs/SIMULATED_CAPTURE.md for equations, coordinate/unit conventions, blockers and support\n * limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\n\n/**\n * Identifies the exact byte output of the baseline encoder.\n *\n * Version 2 (engine 2.0.0) uses the fixed cosine table below instead of runtime `Math.cos`, and rounds\n * quantized coefficients half away from zero. Compared with version 1, bytes can differ only where a\n * coefficient before rounding was within about one ULP (unit in the last place) of a half-integer, or\n * was exactly a negative half-integer. The repository's test images are unchanged.\n */\nexport const EXPORT_JPEG_ENCODER_ID = \"photivra-baseline-jpeg-444-v2\" as const;\n/**\n * C(u,x) = cos((2x+1)·u·π/16) for u,x in 0..7, row-major by u.\n *\n * Each entry is the correctly rounded IEEE-754 double of the exact cosine. They were computed offline with\n * 130-digit decimal arithmetic and checked so that no neighbouring double is closer (see\n * docs/PHOTOGRAPHIC_EXPORT.md). Hard-coding them makes the DCT independent of each JavaScript engine's\n * `Math.cos`, which differs in the last bit between engines. These are mathematical facts, not third-party data.\n */\nexport const JPEG_DCT_COSINES: Readonly<Float64Array> = Float64Array.of(\n 1,1,1,1,1,1,1,1,\n 0.9807852804032304,0.8314696123025452,0.5555702330196022,0.19509032201612828,-0.19509032201612828,-0.5555702330196022,-0.8314696123025452,-0.9807852804032304,\n 0.9238795325112867,0.3826834323650898,-0.3826834323650898,-0.9238795325112867,-0.9238795325112867,-0.3826834323650898,0.3826834323650898,0.9238795325112867,\n 0.8314696123025452,-0.19509032201612828,-0.9807852804032304,-0.5555702330196022,0.5555702330196022,0.9807852804032304,0.19509032201612828,-0.8314696123025452,\n 0.7071067811865476,-0.7071067811865476,-0.7071067811865476,0.7071067811865476,0.7071067811865476,-0.7071067811865476,-0.7071067811865476,0.7071067811865476,\n 0.5555702330196022,-0.9807852804032304,0.19509032201612828,0.8314696123025452,-0.8314696123025452,-0.19509032201612828,0.9807852804032304,-0.5555702330196022,\n 0.3826834323650898,-0.9238795325112867,0.9238795325112867,-0.3826834323650898,-0.3826834323650898,0.9238795325112867,-0.9238795325112867,0.3826834323650898,\n 0.19509032201612828,-0.5555702330196022,0.8314696123025452,-0.9807852804032304,0.9807852804032304,-0.8314696123025452,0.5555702330196022,-0.19509032201612828\n);\n/**\n * Rounds a quantized coefficient to the nearest integer, with ties going away from zero (−2.5 → −3,\n * 2.5 → 3), so positive and negative values round the same way. `Math.round` alone sends −2.5 to −2.\n */\nexport function roundJpegCoefficient(value: number): number {\n return value<0 ? -Math.round(-value) : Math.round(value);\n}\n\n/** Internal baseline JPEG settings: 8-bit YCbCr 4:4:4, one explicit constant quantization step, and uniform Huffman tables written for this project. */\nexport interface ExportJpegInput { width: number; height: number; samples: readonly number[]; quantizationStep: number; exif: Uint8Array; xmp: Uint8Array }\n/** Encodes a baseline JPEG with a directly computed DCT. Uses no third-party encoder source, default quantization tables or Huffman tables. */\nexport function encodeExportJpeg(input: ExportJpegInput): Uint8Array {\n const { width, height, samples, quantizationStep: q } = input;\n if (![width,height,q].every(Number.isSafeInteger) || width < 1 || height < 1 || width*height > 4096 ||\n q < 1 || q > 255 || samples.length !== width*height*3 || Array.from(samples).some((v) => !Number.isInteger(v) || v < 0 || v > 255)) {\n throw new InvalidConfigurationError(\"Unsupported baseline JPEG input.\");\n }\n const encoder=createExportJpegEncoder({...input,maximumOutputBytes:1_000_000});\n for(let by=0;by<height;by+=8)for(let bx=0;bx<width;bx+=8){\n const block:number[]=[];\n for(let y=0;y<8;y++)for(let x=0;x<8;x++){\n const p=(Math.min(by+y,height-1)*width+Math.min(bx+x,width-1))*3;\n block.push(samples[p]!,samples[p+1]!,samples[p+2]!);\n }\n encoder.writeRgbBlock(block);\n }\n return encoder.finish();\n}\n/**\n * Internal size-limited JPEG writer. The reference export and the scalable export use exactly the same\n * DCT and entropy-coding equations.\n *\n * When `densityDotsPerInch` is supplied, it is written to the JFIF 1.02 APP0 segment as units=1 (dots\n * per inch) with equal X and Y density. JFIF density fields are 16-bit unsigned, so it must be an integer\n * in 1..65535; callers round any fractional density and store the exact value in EXIF. When omitted,\n * APP0 keeps units=0 with a 1:1 pixel aspect ratio and states no physical size.\n */\nexport function createExportJpegEncoder(input: Omit<ExportJpegInput,\"samples\"> & {maximumOutputBytes:number;icc?:Uint8Array;densityDotsPerInch?:number}): {\n writeRgbBlock(samples:readonly number[]):void; finish():Uint8Array; dispose():void;\n} {\n const {width,height,quantizationStep:q}=input;\n if(![width,height,q,input.maximumOutputBytes].every(Number.isSafeInteger)||width<1||height<1||width>65535||height>65535||q<1||q>255||input.maximumOutputBytes<1||input.maximumOutputBytes>256_000_000)\n throw new InvalidConfigurationError(\"Invalid bounded JPEG encoding plan.\");\n const density=input.densityDotsPerInch;\n if(density!==undefined&&(!Number.isSafeInteger(density)||density<1||density>65535))\n throw new InvalidConfigurationError(\"JFIF density requires an integer from 1 to 65535 dots per inch.\");\n // Growable output. Capacity starts at min(budget, 64 KiB) and doubles, but never beyond the budget. The budget\n // check is unchanged (offset + n > maximumOutputBytes fails), so the output bytes and failures are the same as\n // with a buffer allocated at full budget up front. An old buffer is zeroed after its bytes are copied over.\n const budget=input.maximumOutputBytes;\n let storage=new Uint8Array(Math.min(budget,65_536)),offset=0,disposed=false,blocks=0;\n const reserve=(count:number):void=>{\n if(disposed||offset+count>budget)throw new InvalidConfigurationError(\"JPEG output exceeds admitted byte budget or is disposed.\");\n if(offset+count<=storage.length)return;\n const grown=new Uint8Array(Math.min(budget,Math.max(storage.length*2,offset+count)));\n grown.set(storage.subarray(0,offset));storage.fill(0,0,offset);storage=grown;\n };\n const push=(...values:number[]):void=>{reserve(values.length);storage.set(values,offset);offset+=values.length;};\n // Fast path for one entropy-coded byte: the same budget/disposal check and byte order as push(), without an array per byte.\n const pushByte=(value:number):void=>{if(disposed||offset>=storage.length)reserve(1);storage[offset++]=value;};\n push(255,216);\n const marker = (id: number, payload: readonly number[]): void => {\n if (payload.length > 65533) throw new InvalidConfigurationError(\"JPEG metadata segment exceeds the standard APP limit.\");\n push(255,id,(payload.length+2)>>8,(payload.length+2)&255,...payload);\n };\n // JFIF 1.02 APP0: identifier, version 1.02, units (0 aspect ratio only, 1 dots per inch), Xdensity, Ydensity, no thumbnail.\n marker(224,density===undefined ? [74,70,73,70,0,1,2,0,0,1,0,1,0,0] : [74,70,73,70,0,1,2,1,density>>8,density&255,density>>8,density&255,0,0]);\n marker(225,[69,120,105,102,0,0,...input.exif]);\n marker(225,[...new TextEncoder().encode(\"http://ns.adobe.com/xap/1.0/\\0\"),...input.xmp]);\n if(input.icc){\n if(input.icc.length>65519)throw new InvalidConfigurationError(\"ICC profile exceeds the single-segment encoding envelope.\");\n marker(226,[...new TextEncoder().encode(\"ICC_PROFILE\\0\"),1,1,...input.icc]);\n }\n marker(219,[0,...Array<number>(64).fill(q)]);\n marker(192,[8,height>>8,height&255,width>>8,width&255,3,1,17,0,2,17,0,3,17,0]);\n // DC categories 0..11 use 4-bit codes; AC EOB/ZRL and all baseline run/category pairs use 8-bit codes.\n // Incomplete canonical Huffman trees reserve the all-ones code, so JPEG bit padding (1-bits) can never be read as a symbol.\n const dc = Array.from({length:12},(_,i) => i), ac = [0,240];\n for (let run=0;run<16;run++) for (let size=1;size<=10;size++) ac.push(run*16+size);\n marker(196,[0,...Array.from({length:16},(_,i) => i===3 ? 12 : 0),...dc,\n 16,...Array.from({length:16},(_,i) => i===7 ? ac.length : 0),...ac]);\n marker(218,[3,1,0,2,0,3,0,0,63,0]);\n let accumulator=0, bits=0;\n // Appends the low `count` bits (count <= 16) most-significant first, emitting each completed byte with 0xFF stuffing.\n const emit = (value: number, count: number): void => {\n accumulator=(accumulator<<count)|(value&((1<<count)-1)); bits+=count;\n while (bits>=8) { bits-=8; const byte=(accumulator>>>bits)&255; pushByte(byte); if (byte===255) pushByte(0); }\n accumulator&=(1<<bits)-1;\n };\n const amplitude = (value: number, max: number): number => {\n const size=value===0 ? 0 : Math.floor(Math.log2(Math.abs(value)))+1;\n if (size>max) throw new InvalidConfigurationError(\"JPEG coefficient exceeds baseline entropy range.\");\n return size;\n };\n const coefficient = (value: number, size: number): void => { if (size) emit(value>=0 ? value : value+(1<<size)-1,size); };\n const zigzag=new Int32Array(64);\n for (let diagonal=0,i=0;diagonal<=14;diagonal++) {\n const points: number[] = [];\n for (let y=0;y<8;y++) { const x=diagonal-y; if (x>=0 && x<8) points.push(y*8+x); }\n for (const point of diagonal%2===0 ? points.reverse() : points) zigzag[i++]=point;\n }\n // Huffman symbol index of each AC (run, size) pair; equals ac.indexOf(symbol) for every emitted symbol.\n const acIndex=new Int16Array(256).fill(-1);\n for (let i=ac.length-1;i>=0;i--) acIndex[ac[i]!]=i;\n/**\n * The 8×8 DCT, computed directly, with orthonormal DC factors and one chosen quantization step.\n *\n * This is a deliberately simple 4:4:4 reference encoder. Lossy quantization means exact RGB pixels are\n * not preserved. Decoding the JPEG and comparing is an interoperability check, not an exact scientific\n * check of pixel values.\n *\n * Each coefficient is the direct 64-term sum Σ_y Σ_x (f(x,y)·C(u,x))·C(v,y), summed over y, then x.\n * The row products f(x,y)·C(u,x) are computed once per u and reused for all eight v. This reuses the\n * identical IEEE-754 products and keeps the exact order of multiplication and summation. A factored\n * row/column DCT would reorder the sum, so it is deliberately not used.\n *\n * C(u,x) comes from the fixed table `JPEG_DCT_COSINES` (correctly rounded constants), not `Math.cos`,\n * so the coefficients do not depend on the JavaScript engine's maths library. Each quantized coefficient\n * is rounded half away from zero (`roundJpegCoefficient`).\n */\n const cosine=JPEG_DCT_COSINES;\n const previous=[0,0,0];\n const planes=[new Float64Array(64),new Float64Array(64),new Float64Array(64)];\n const rowProducts=new Float64Array(64), transformed=new Float64Array(64);\n const blueScale=2*(1-.114), redScale=2*(1-.299);\n return {\n writeRgbBlock(samples:readonly number[]):void {\n let valid=!disposed&&blocks<Math.ceil(width/8)*Math.ceil(height/8)&&samples.length===192;\n for(let i=0;valid&&i<192;i++){const v=samples[i]!;valid=Number.isInteger(v)&&v>=0&&v<=255;}\n if(!valid)throw new InvalidConfigurationError(\"JPEG requires complete bounded RGB coding blocks.\");\n const [luma,blueDifference,redDifference]=planes as [Float64Array,Float64Array,Float64Array];\n for (let i=0;i<64;i++) {\n // JPEG pads only partial 8x8 blocks (MCUs, minimum coded units). The declared image and crop size never change.\n const p=i*3;\n const red=samples[p]!, green=samples[p+1]!, blue=samples[p+2]!, luminance=.299*red+.587*green+.114*blue;\n luma[i]=luminance-128; blueDifference[i]=(blue-luminance)/blueScale; redDifference[i]=(red-luminance)/redScale;\n }\n for (let channel=0;channel<3;channel++) {\n const block=planes[channel]!;\n for (let u=0;u<8;u++) {\n const uOffset=u*8;\n for (let y=0;y<8;y++) for (let x=0;x<8;x++) rowProducts[y*8+x]=block[y*8+x]!*cosine[uOffset+x]!;\n const uFactor=u===0 ? Math.SQRT1_2 : 1;\n for (let v=0;v<8;v++) {\n const vOffset=v*8;\n let sum=0; for (let y=0;y<8;y++) { const cv=cosine[vOffset+y]!; for (let x=0;x<8;x++) sum+=rowProducts[y*8+x]!*cv; }\n transformed[vOffset+u]=roundJpegCoefficient(sum*.25*uFactor*(v===0 ? Math.SQRT1_2 : 1)/q);\n }\n }\n const difference=transformed[0]!-previous[channel]!, size=amplitude(difference,11); emit(size,4); coefficient(difference,size); previous[channel]=transformed[0]!;\n let zeroes=0;\n for (let i=1;i<64;i++) {\n const value=transformed[zigzag[i]!]!;\n if (value===0) { zeroes++; continue; }\n while (zeroes>=16) { emit(1,8); zeroes-=16; }\n const length=amplitude(value,10), symbol=zeroes*16+length; emit(acIndex[symbol]!,8); coefficient(value,length); zeroes=0;\n }\n if (zeroes) emit(0,8);\n }\n blocks++;\n },\n finish():Uint8Array {\n if(disposed||blocks!==Math.ceil(width/8)*Math.ceil(height/8))throw new InvalidConfigurationError(\"JPEG cannot finish incomplete or disposed encoding.\");\n if(bits)emit((1<<(8-bits))-1,8-bits);\n // Only the written prefix can hold data; zero it after the copy instead of filling the whole capacity.\n push(255,217);const output=storage.slice(0,offset);storage.fill(0,0,offset);storage=new Uint8Array(0);disposed=true;return output;\n },\n dispose():void {storage.fill(0,0,offset);storage=new Uint8Array(0);disposed=true;}\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"export-jpeg.js","sourceRoot":"","sources":["../../src/capture/export-jpeg.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Baseline JPEG encoder written for this project. It computes the DCT (discrete cosine transform)\n * directly and uses no third-party encoder source, default quantization tables or Huffman tables.\n * @see docs/SIMULATED_CAPTURE.md for equations, coordinate/unit conventions, blockers and support\n * limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { FULL_RESOLUTION_CEILING_PIXELS, scaleBudgetCeiling } from \"../core/pixel-limits.js\";\n\n/**\n * Identifies the exact byte output of the baseline encoder.\n *\n * Version 2 (engine 2.0.0) uses the fixed cosine table below instead of runtime `Math.cos`, and rounds\n * quantized coefficients half away from zero. Compared with version 1, bytes can differ only where a\n * coefficient before rounding was within about one ULP (unit in the last place) of a half-integer, or\n * was exactly a negative half-integer. The repository's test images are unchanged.\n */\nexport const EXPORT_JPEG_ENCODER_ID = \"photivra-baseline-jpeg-444-v2\" as const;\n/**\n * C(u,x) = cos((2x+1)·u·π/16) for u,x in 0..7, row-major by u.\n *\n * Each entry is the correctly rounded IEEE-754 double of the exact cosine. They were computed offline with\n * 130-digit decimal arithmetic and checked so that no neighbouring double is closer (see\n * docs/PHOTOGRAPHIC_EXPORT.md). Hard-coding them makes the DCT independent of each JavaScript engine's\n * `Math.cos`, which differs in the last bit between engines. These are mathematical facts, not third-party data.\n */\nexport const JPEG_DCT_COSINES: Readonly<Float64Array> = Float64Array.of(\n 1,1,1,1,1,1,1,1,\n 0.9807852804032304,0.8314696123025452,0.5555702330196022,0.19509032201612828,-0.19509032201612828,-0.5555702330196022,-0.8314696123025452,-0.9807852804032304,\n 0.9238795325112867,0.3826834323650898,-0.3826834323650898,-0.9238795325112867,-0.9238795325112867,-0.3826834323650898,0.3826834323650898,0.9238795325112867,\n 0.8314696123025452,-0.19509032201612828,-0.9807852804032304,-0.5555702330196022,0.5555702330196022,0.9807852804032304,0.19509032201612828,-0.8314696123025452,\n 0.7071067811865476,-0.7071067811865476,-0.7071067811865476,0.7071067811865476,0.7071067811865476,-0.7071067811865476,-0.7071067811865476,0.7071067811865476,\n 0.5555702330196022,-0.9807852804032304,0.19509032201612828,0.8314696123025452,-0.8314696123025452,-0.19509032201612828,0.9807852804032304,-0.5555702330196022,\n 0.3826834323650898,-0.9238795325112867,0.9238795325112867,-0.3826834323650898,-0.3826834323650898,0.9238795325112867,-0.9238795325112867,0.3826834323650898,\n 0.19509032201612828,-0.5555702330196022,0.8314696123025452,-0.9807852804032304,0.9807852804032304,-0.8314696123025452,0.5555702330196022,-0.19509032201612828\n);\n/**\n * Rounds a quantized coefficient to the nearest integer, with ties going away from zero (−2.5 → −3,\n * 2.5 → 3), so positive and negative values round the same way. `Math.round` alone sends −2.5 to −2.\n */\nexport function roundJpegCoefficient(value: number): number {\n return value<0 ? -Math.round(-value) : Math.round(value);\n}\n\n/** Internal baseline JPEG settings: 8-bit YCbCr 4:4:4, one explicit constant quantization step, and uniform Huffman tables written for this project. */\nexport interface ExportJpegInput { width: number; height: number; samples: readonly number[]; quantizationStep: number; exif: Uint8Array; xmp: Uint8Array }\n/** Encodes a baseline JPEG with a directly computed DCT. Uses no third-party encoder source, default quantization tables or Huffman tables. */\nexport function encodeExportJpeg(input: ExportJpegInput): Uint8Array {\n const { width, height, samples, quantizationStep: q } = input;\n if (![width,height,q].every(Number.isSafeInteger) || width < 1 || height < 1 || width*height > 4096 ||\n q < 1 || q > 255 || samples.length !== width*height*3 || Array.from(samples).some((v) => !Number.isInteger(v) || v < 0 || v > 255)) {\n throw new InvalidConfigurationError(\"Unsupported baseline JPEG input.\");\n }\n const encoder=createExportJpegEncoder({...input,maximumOutputBytes:1_000_000});\n for(let by=0;by<height;by+=8)for(let bx=0;bx<width;bx+=8){\n const block:number[]=[];\n for(let y=0;y<8;y++)for(let x=0;x<8;x++){\n const p=(Math.min(by+y,height-1)*width+Math.min(bx+x,width-1))*3;\n block.push(samples[p]!,samples[p+1]!,samples[p+2]!);\n }\n encoder.writeRgbBlock(block);\n }\n return encoder.finish();\n}\n/**\n * Largest byte budget the internal writer accepts: the Print JPEG budget ceiling at the largest opt-in source\n * (256 000 000 bytes per 24 000 000 pixels at 2^27 pixels). Each caller enforces its own smaller budget.\n */\nconst EXPORT_JPEG_MAXIMUM_OUTPUT_BYTES=scaleBudgetCeiling(256_000_000,FULL_RESOLUTION_CEILING_PIXELS);\n/**\n * Internal size-limited JPEG writer. The reference export and the scalable export use exactly the same\n * DCT and entropy-coding equations.\n *\n * When `densityDotsPerInch` is supplied, it is written to the JFIF 1.02 APP0 segment as units=1 (dots\n * per inch) with equal X and Y density. JFIF density fields are 16-bit unsigned, so it must be an integer\n * in 1..65535; callers round any fractional density and store the exact value in EXIF. When omitted,\n * APP0 keeps units=0 with a 1:1 pixel aspect ratio and states no physical size.\n */\nexport function createExportJpegEncoder(input: Omit<ExportJpegInput,\"samples\"> & {maximumOutputBytes:number;icc?:Uint8Array;densityDotsPerInch?:number}): {\n writeRgbBlock(samples:readonly number[]):void; finish():Uint8Array; dispose():void;\n} {\n const {width,height,quantizationStep:q}=input;\n if(![width,height,q,input.maximumOutputBytes].every(Number.isSafeInteger)||width<1||height<1||width>65535||height>65535||q<1||q>255||input.maximumOutputBytes<1||input.maximumOutputBytes>EXPORT_JPEG_MAXIMUM_OUTPUT_BYTES)\n throw new InvalidConfigurationError(\"Invalid bounded JPEG encoding plan.\");\n const density=input.densityDotsPerInch;\n if(density!==undefined&&(!Number.isSafeInteger(density)||density<1||density>65535))\n throw new InvalidConfigurationError(\"JFIF density requires an integer from 1 to 65535 dots per inch.\");\n // Growable output. Capacity starts at min(budget, 64 KiB) and doubles, but never beyond the budget. The budget\n // check is unchanged (offset + n > maximumOutputBytes fails), so the output bytes and failures are the same as\n // with a buffer allocated at full budget up front. An old buffer is zeroed after its bytes are copied over.\n const budget=input.maximumOutputBytes;\n let storage=new Uint8Array(Math.min(budget,65_536)),offset=0,disposed=false,blocks=0;\n const reserve=(count:number):void=>{\n if(disposed||offset+count>budget)throw new InvalidConfigurationError(\"JPEG output exceeds admitted byte budget or is disposed.\");\n if(offset+count<=storage.length)return;\n const grown=new Uint8Array(Math.min(budget,Math.max(storage.length*2,offset+count)));\n grown.set(storage.subarray(0,offset));storage.fill(0,0,offset);storage=grown;\n };\n const push=(...values:number[]):void=>{reserve(values.length);storage.set(values,offset);offset+=values.length;};\n // Fast path for one entropy-coded byte: the same budget/disposal check and byte order as push(), without an array per byte.\n const pushByte=(value:number):void=>{if(disposed||offset>=storage.length)reserve(1);storage[offset++]=value;};\n push(255,216);\n const marker = (id: number, payload: readonly number[]): void => {\n if (payload.length > 65533) throw new InvalidConfigurationError(\"JPEG metadata segment exceeds the standard APP limit.\");\n push(255,id,(payload.length+2)>>8,(payload.length+2)&255,...payload);\n };\n // JFIF 1.02 APP0: identifier, version 1.02, units (0 aspect ratio only, 1 dots per inch), Xdensity, Ydensity, no thumbnail.\n marker(224,density===undefined ? [74,70,73,70,0,1,2,0,0,1,0,1,0,0] : [74,70,73,70,0,1,2,1,density>>8,density&255,density>>8,density&255,0,0]);\n marker(225,[69,120,105,102,0,0,...input.exif]);\n marker(225,[...new TextEncoder().encode(\"http://ns.adobe.com/xap/1.0/\\0\"),...input.xmp]);\n if(input.icc){\n if(input.icc.length>65519)throw new InvalidConfigurationError(\"ICC profile exceeds the single-segment encoding envelope.\");\n marker(226,[...new TextEncoder().encode(\"ICC_PROFILE\\0\"),1,1,...input.icc]);\n }\n marker(219,[0,...Array<number>(64).fill(q)]);\n marker(192,[8,height>>8,height&255,width>>8,width&255,3,1,17,0,2,17,0,3,17,0]);\n // DC categories 0..11 use 4-bit codes; AC EOB/ZRL and all baseline run/category pairs use 8-bit codes.\n // Incomplete canonical Huffman trees reserve the all-ones code, so JPEG bit padding (1-bits) can never be read as a symbol.\n const dc = Array.from({length:12},(_,i) => i), ac = [0,240];\n for (let run=0;run<16;run++) for (let size=1;size<=10;size++) ac.push(run*16+size);\n marker(196,[0,...Array.from({length:16},(_,i) => i===3 ? 12 : 0),...dc,\n 16,...Array.from({length:16},(_,i) => i===7 ? ac.length : 0),...ac]);\n marker(218,[3,1,0,2,0,3,0,0,63,0]);\n let accumulator=0, bits=0;\n // Appends the low `count` bits (count <= 16) most-significant first, emitting each completed byte with 0xFF stuffing.\n const emit = (value: number, count: number): void => {\n accumulator=(accumulator<<count)|(value&((1<<count)-1)); bits+=count;\n while (bits>=8) { bits-=8; const byte=(accumulator>>>bits)&255; pushByte(byte); if (byte===255) pushByte(0); }\n accumulator&=(1<<bits)-1;\n };\n const amplitude = (value: number, max: number): number => {\n const size=value===0 ? 0 : Math.floor(Math.log2(Math.abs(value)))+1;\n if (size>max) throw new InvalidConfigurationError(\"JPEG coefficient exceeds baseline entropy range.\");\n return size;\n };\n const coefficient = (value: number, size: number): void => { if (size) emit(value>=0 ? value : value+(1<<size)-1,size); };\n const zigzag=new Int32Array(64);\n for (let diagonal=0,i=0;diagonal<=14;diagonal++) {\n const points: number[] = [];\n for (let y=0;y<8;y++) { const x=diagonal-y; if (x>=0 && x<8) points.push(y*8+x); }\n for (const point of diagonal%2===0 ? points.reverse() : points) zigzag[i++]=point;\n }\n // Huffman symbol index of each AC (run, size) pair; equals ac.indexOf(symbol) for every emitted symbol.\n const acIndex=new Int16Array(256).fill(-1);\n for (let i=ac.length-1;i>=0;i--) acIndex[ac[i]!]=i;\n/**\n * The 8×8 DCT, computed directly, with orthonormal DC factors and one chosen quantization step.\n *\n * This is a deliberately simple 4:4:4 reference encoder. Lossy quantization means exact RGB pixels are\n * not preserved. Decoding the JPEG and comparing is an interoperability check, not an exact scientific\n * check of pixel values.\n *\n * Each coefficient is the direct 64-term sum Σ_y Σ_x (f(x,y)·C(u,x))·C(v,y), summed over y, then x.\n * The row products f(x,y)·C(u,x) are computed once per u and reused for all eight v. This reuses the\n * identical IEEE-754 products and keeps the exact order of multiplication and summation. A factored\n * row/column DCT would reorder the sum, so it is deliberately not used.\n *\n * C(u,x) comes from the fixed table `JPEG_DCT_COSINES` (correctly rounded constants), not `Math.cos`,\n * so the coefficients do not depend on the JavaScript engine's maths library. Each quantized coefficient\n * is rounded half away from zero (`roundJpegCoefficient`).\n */\n const cosine=JPEG_DCT_COSINES;\n const previous=[0,0,0];\n const planes=[new Float64Array(64),new Float64Array(64),new Float64Array(64)];\n const rowProducts=new Float64Array(64), transformed=new Float64Array(64);\n const blueScale=2*(1-.114), redScale=2*(1-.299);\n return {\n writeRgbBlock(samples:readonly number[]):void {\n let valid=!disposed&&blocks<Math.ceil(width/8)*Math.ceil(height/8)&&samples.length===192;\n for(let i=0;valid&&i<192;i++){const v=samples[i]!;valid=Number.isInteger(v)&&v>=0&&v<=255;}\n if(!valid)throw new InvalidConfigurationError(\"JPEG requires complete bounded RGB coding blocks.\");\n const [luma,blueDifference,redDifference]=planes as [Float64Array,Float64Array,Float64Array];\n for (let i=0;i<64;i++) {\n // JPEG pads only partial 8x8 blocks (MCUs, minimum coded units). The declared image and crop size never change.\n const p=i*3;\n const red=samples[p]!, green=samples[p+1]!, blue=samples[p+2]!, luminance=.299*red+.587*green+.114*blue;\n luma[i]=luminance-128; blueDifference[i]=(blue-luminance)/blueScale; redDifference[i]=(red-luminance)/redScale;\n }\n for (let channel=0;channel<3;channel++) {\n const block=planes[channel]!;\n for (let u=0;u<8;u++) {\n const uOffset=u*8;\n for (let y=0;y<8;y++) for (let x=0;x<8;x++) rowProducts[y*8+x]=block[y*8+x]!*cosine[uOffset+x]!;\n const uFactor=u===0 ? Math.SQRT1_2 : 1;\n for (let v=0;v<8;v++) {\n const vOffset=v*8;\n let sum=0; for (let y=0;y<8;y++) { const cv=cosine[vOffset+y]!; for (let x=0;x<8;x++) sum+=rowProducts[y*8+x]!*cv; }\n transformed[vOffset+u]=roundJpegCoefficient(sum*.25*uFactor*(v===0 ? Math.SQRT1_2 : 1)/q);\n }\n }\n const difference=transformed[0]!-previous[channel]!, size=amplitude(difference,11); emit(size,4); coefficient(difference,size); previous[channel]=transformed[0]!;\n let zeroes=0;\n for (let i=1;i<64;i++) {\n const value=transformed[zigzag[i]!]!;\n if (value===0) { zeroes++; continue; }\n while (zeroes>=16) { emit(1,8); zeroes-=16; }\n const length=amplitude(value,10), symbol=zeroes*16+length; emit(acIndex[symbol]!,8); coefficient(value,length); zeroes=0;\n }\n if (zeroes) emit(0,8);\n }\n blocks++;\n },\n finish():Uint8Array {\n if(disposed||blocks!==Math.ceil(width/8)*Math.ceil(height/8))throw new InvalidConfigurationError(\"JPEG cannot finish incomplete or disposed encoding.\");\n if(bits)emit((1<<(8-bits))-1,8-bits);\n // Only the written prefix can hold data; zero it after the copy instead of filling the whole capacity.\n push(255,217);const output=storage.slice(0,offset);storage.fill(0,0,offset);storage=new Uint8Array(0);disposed=true;return output;\n },\n dispose():void {storage.fill(0,0,offset);storage=new Uint8Array(0);disposed=true;}\n };\n}\n"]}
|
|
@@ -13,6 +13,7 @@ import { parseFocusPlane } from "../optics/focus-state.js";
|
|
|
13
13
|
import { calculateIlluminationVignetting } from "../optics/illumination-vignetting.js";
|
|
14
14
|
import { applyPhysicalCameraRotation, resolveProjectionDistanceMm } from "../motion/camera-rotation.js";
|
|
15
15
|
import { prepareCaptureExposureWindowSampler } from "../sensor/exposure-window.js";
|
|
16
|
+
import { apertureFitAllowanceMicrometers } from "../sensor/sampling-aperture.js";
|
|
16
17
|
import { isPublicOpaqueId } from "../core/record-validation.js";
|
|
17
18
|
import { freezeOwnedData } from "../core/owned-data.js";
|
|
18
19
|
import { composeNativeEnvironmentSensorSite } from "./native-environment-optical-stage.js";
|
|
@@ -147,8 +148,10 @@ function geometry(t, k, frame, environment, index) {
|
|
|
147
148
|
const siteCenterFromTopLeftX = g.firstX + x * g.pitchX, siteCenterFromTopLeftY = g.firstY + y * g.pitchY;
|
|
148
149
|
const apertureCenterFromTopLeftX = siteCenterFromTopLeftX + g.offsetX, apertureCenterFromTopLeftY = siteCenterFromTopLeftY + g.offsetY;
|
|
149
150
|
const imagingWidthMicrometers = g.imagingWidthMm * 1000, imagingHeightMicrometers = g.imagingHeightMm * 1000;
|
|
150
|
-
|
|
151
|
-
|
|
151
|
+
const allowanceX = apertureFitAllowanceMicrometers(imagingWidthMicrometers), allowanceY = apertureFitAllowanceMicrometers(imagingHeightMicrometers);
|
|
152
|
+
if (apertureCenterFromTopLeftX - g.widthUm / 2 < -allowanceX || apertureCenterFromTopLeftY - g.heightUm / 2 < -allowanceY ||
|
|
153
|
+
apertureCenterFromTopLeftX + g.widthUm / 2 > imagingWidthMicrometers + allowanceX ||
|
|
154
|
+
apertureCenterFromTopLeftY + g.heightUm / 2 > imagingHeightMicrometers + allowanceY)
|
|
152
155
|
return undefined;
|
|
153
156
|
const centerX = -g.imagingWidthMm / 2 + apertureCenterFromTopLeftX / 1000, centerY = -g.imagingHeightMm / 2 + apertureCenterFromTopLeftY / 1000;
|
|
154
157
|
// calculateSensorSpatialSamplingQuadrature: midpoint grid nodes minus the anti-aliasing (AA) offset.
|