react-native-image-stitcher 0.14.2 → 0.15.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 +131 -0
- package/README.md +35 -0
- package/RNImageStitcher.podspec +8 -7
- package/android/build.gradle +0 -16
- package/android/src/main/cpp/CMakeLists.txt +2 -63
- package/android/src/main/cpp/image_stitcher_jni.cpp +14 -0
- package/android/src/main/cpp/keyframe_gate_jni.cpp +13 -0
- package/android/src/main/java/io/imagestitcher/rn/BatchStitcher.kt +285 -3
- package/android/src/main/java/io/imagestitcher/rn/IncrementalStitcher.kt +180 -1162
- package/android/src/main/java/io/imagestitcher/rn/KeyframeGate.kt +29 -0
- package/android/src/main/java/io/imagestitcher/rn/RNImageStitcherPackage.kt +0 -4
- package/android/src/main/java/io/imagestitcher/rn/RNSARCameraView.kt +13 -64
- package/cpp/keyframe_gate.cpp +82 -23
- package/cpp/keyframe_gate.hpp +31 -2
- package/cpp/stitcher.cpp +208 -28
- package/cpp/tests/CMakeLists.txt +18 -12
- package/cpp/tests/keyframe_timebudget_test.cpp +65 -0
- package/cpp/tests/warp_guard_test.cpp +48 -0
- package/cpp/warp_guard.hpp +41 -0
- package/dist/camera/Camera.d.ts +31 -16
- package/dist/camera/Camera.js +10 -2
- package/dist/camera/CaptureStitchStatsToast.d.ts +15 -2
- package/dist/camera/CaptureStitchStatsToast.js +27 -7
- package/dist/camera/PanoramaSettings.d.ts +10 -223
- package/dist/camera/PanoramaSettings.js +6 -28
- package/dist/camera/PanoramaSettingsBridge.d.ts +1 -24
- package/dist/camera/PanoramaSettingsBridge.js +3 -102
- package/dist/camera/PanoramaSettingsModal.js +7 -1
- package/dist/camera/buildPanoramaInitialSettings.d.ts +11 -0
- package/dist/camera/buildPanoramaInitialSettings.js +4 -0
- package/dist/camera/cameraErrorMessages.d.ts +32 -0
- package/dist/camera/cameraErrorMessages.js +53 -0
- package/dist/camera/selectCaptureDevice.d.ts +5 -1
- package/dist/camera/selectCaptureDevice.js +22 -2
- package/dist/camera/useCapture.js +38 -0
- package/dist/index.d.ts +5 -8
- package/dist/index.js +11 -34
- package/dist/stitching/incremental.d.ts +1 -117
- package/dist/stitching/stitchVideo.d.ts +0 -35
- package/dist/types.d.ts +0 -87
- package/ios/Sources/RNImageStitcher/IncrementalStitcher.swift +96 -674
- package/ios/Sources/RNImageStitcher/IncrementalStitcherBridge.swift +9 -12
- package/ios/Sources/RNImageStitcher/KeyframeGate.swift +14 -0
- package/ios/Sources/RNImageStitcher/KeyframeGateBridge.h +7 -0
- package/ios/Sources/RNImageStitcher/KeyframeGateBridge.mm +6 -0
- package/ios/Sources/RNImageStitcher/OpenCVKeyframeCollector.h +2 -2
- package/ios/Sources/RNImageStitcher/OpenCVKeyframeCollector.mm +3 -3
- package/ios/Sources/RNImageStitcher/OpenCVStitcher.h +28 -60
- package/ios/Sources/RNImageStitcher/OpenCVStitcher.mm +180 -921
- package/ios/Sources/RNImageStitcher/RNSARSession.swift +10 -35
- package/ios/Sources/RNImageStitcher/Stitcher.swift +84 -35
- package/ios/Sources/RNImageStitcher/StitcherBridge.m +13 -0
- package/ios/Sources/RNImageStitcher/StitcherBridge.swift +132 -5
- package/package.json +3 -2
- package/src/camera/Camera.tsx +43 -22
- package/src/camera/CaptureStitchStatsToast.tsx +58 -14
- package/src/camera/PanoramaSettings.ts +16 -289
- package/src/camera/PanoramaSettingsBridge.ts +3 -114
- package/src/camera/PanoramaSettingsModal.tsx +14 -1
- package/src/camera/__tests__/PanoramaSettingsBridge.test.ts +3 -188
- package/src/camera/__tests__/buildPanoramaInitialSettings.test.ts +41 -0
- package/src/camera/__tests__/cameraErrorMessages.test.ts +76 -0
- package/src/camera/__tests__/selectCaptureDevice.test.ts +33 -0
- package/src/camera/buildPanoramaInitialSettings.ts +17 -0
- package/src/camera/cameraErrorMessages.ts +84 -0
- package/src/camera/selectCaptureDevice.ts +28 -3
- package/src/camera/useCapture.ts +44 -1
- package/src/index.ts +11 -40
- package/src/stitching/incremental.ts +3 -140
- package/src/stitching/stitchVideo.ts +0 -26
- package/src/types.ts +0 -95
- package/android/src/main/cpp/stitcher_jsi_install_jni.cpp +0 -227
- package/android/src/main/java/io/imagestitcher/rn/IncrementalFirstwinsEngine.kt +0 -1081
- package/android/src/main/java/io/imagestitcher/rn/StitcherJsiInstallerModule.kt +0 -103
- package/android/src/main/java/io/imagestitcher/rn/StitcherWorkletRuntime.kt +0 -256
- package/cpp/stitcher_frame_jsi.cpp +0 -214
- package/cpp/stitcher_frame_jsi.hpp +0 -108
- package/cpp/stitcher_proxy_jsi.cpp +0 -109
- package/cpp/stitcher_proxy_jsi.hpp +0 -46
- package/cpp/stitcher_worklet_dispatch.cpp +0 -103
- package/cpp/stitcher_worklet_dispatch.hpp +0 -71
- package/cpp/stitcher_worklet_registry.cpp +0 -91
- package/cpp/stitcher_worklet_registry.hpp +0 -146
- package/cpp/tests/stitcher_worklet_registry_test.cpp +0 -195
- package/dist/stitching/IncrementalStitcherView.d.ts +0 -41
- package/dist/stitching/IncrementalStitcherView.js +0 -157
- package/dist/stitching/StitcherWorkletRegistry.d.ts +0 -117
- package/dist/stitching/StitcherWorkletRegistry.js +0 -78
- package/dist/stitching/ensureStitcherProxyInstalled.d.ts +0 -8
- package/dist/stitching/ensureStitcherProxyInstalled.js +0 -81
- package/dist/stitching/useFrameProcessor.d.ts +0 -119
- package/dist/stitching/useFrameProcessor.js +0 -196
- package/dist/stitching/useFrameStream.d.ts +0 -34
- package/dist/stitching/useFrameStream.js +0 -234
- package/dist/stitching/useThrottledFrameProcessor.d.ts +0 -33
- package/dist/stitching/useThrottledFrameProcessor.js +0 -132
- package/ios/Sources/RNImageStitcher/OpenCVIncrementalStitcher.h +0 -474
- package/ios/Sources/RNImageStitcher/OpenCVIncrementalStitcher.mm +0 -1328
- package/ios/Sources/RNImageStitcher/OpenCVSlitScanStitcher.h +0 -103
- package/ios/Sources/RNImageStitcher/OpenCVSlitScanStitcher.mm +0 -3285
- package/ios/Sources/RNImageStitcher/RNSARWorkletRuntime.h +0 -128
- package/ios/Sources/RNImageStitcher/RNSARWorkletRuntime.mm +0 -313
- package/ios/Sources/RNImageStitcher/SaveFrameAsJpegPlugin.mm +0 -185
- package/ios/Sources/RNImageStitcher/StitcherFrameHostObject.h +0 -60
- package/ios/Sources/RNImageStitcher/StitcherFrameHostObject.mm +0 -214
- package/ios/Sources/RNImageStitcher/StitcherJsiInstaller.h +0 -42
- package/ios/Sources/RNImageStitcher/StitcherJsiInstaller.mm +0 -160
- package/src/stitching/IncrementalStitcherView.tsx +0 -198
- package/src/stitching/StitcherWorkletRegistry.ts +0 -156
- package/src/stitching/__tests__/StitcherWorkletRegistry.test.ts +0 -176
- package/src/stitching/__tests__/ensureStitcherProxyInstalled.test.ts +0 -94
- package/src/stitching/__tests__/useThrottledFrameProcessor.test.ts +0 -178
- package/src/stitching/ensureStitcherProxyInstalled.ts +0 -141
- package/src/stitching/useFrameProcessor.ts +0 -226
- package/src/stitching/useFrameStream.ts +0 -271
- package/src/stitching/useThrottledFrameProcessor.ts +0 -145
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
//
|
|
3
|
-
// v0.9.0 Layer 2 — throttle gate over v0.8.0's `useFrameProcessor`.
|
|
4
|
-
//
|
|
5
|
-
// ## What this is
|
|
6
|
-
//
|
|
7
|
-
// A thin wrapper around `useFrameProcessor` that enforces a maximum
|
|
8
|
-
// invocation rate (`sampleHz`) at the worklet layer. The host's
|
|
9
|
-
// worklet fires up to `sampleHz` times per second; ticks too close
|
|
10
|
-
// together are dropped via a `useSharedValue<number>` monotonic-time
|
|
11
|
-
// gate inside the worklet body.
|
|
12
|
-
//
|
|
13
|
-
// ## When to use this (vs alternatives)
|
|
14
|
-
//
|
|
15
|
-
// - **`useFrameProcessor` directly** — every camera frame (~30-60 Hz).
|
|
16
|
-
// Use for true-realtime processing that wants to see every frame.
|
|
17
|
-
// - **`useThrottledFrameProcessor`** (this hook) — sub-frame-rate
|
|
18
|
-
// worklet-native processing. The worklet runtime has direct
|
|
19
|
-
// access to `frame.toArrayBuffer()`, `frame.arDepth`,
|
|
20
|
-
// `frame.arAnchors`, and can call other vc Frame Processor plugins
|
|
21
|
-
// (native OCR libraries, TFLite ML inference, etc.). Results
|
|
22
|
-
// bridged to JS via `runOnJS`.
|
|
23
|
-
// - **`useFrameStream`** (Layer 3, also in this directory) —
|
|
24
|
-
// sub-frame-rate JS-thread consumer. The lib JPEG-encodes each
|
|
25
|
-
// sample on the producer thread and delivers a `SampledFrame`
|
|
26
|
-
// (file path + pose + dims) to a JS-thread callback. Use for
|
|
27
|
-
// file-path OCR libraries (RN modules wrapping ML Kit etc.),
|
|
28
|
-
// cloud upload, thumbnail UI.
|
|
29
|
-
//
|
|
30
|
-
// ## Use-case mapping (canonical)
|
|
31
|
-
//
|
|
32
|
-
// | Use case | Layer | Why |
|
|
33
|
-
// |---------------------------------------|-------|----------------------------------|
|
|
34
|
-
// | OCR via Vision.framework / ML Kit | **2** | native libs, bbox in frame coords|
|
|
35
|
-
// | TFLite ML detection (via vc plugin) | **2** | same shape as OCR |
|
|
36
|
-
// | LiDAR depth → 3D reconstruction | **2** | depth too large to bridge |
|
|
37
|
-
// | Pose-only telemetry | **2** | tiny payload, no encoding needed |
|
|
38
|
-
// | File-path OCR (RN module) | 3 | host wants a JPEG, not pixels |
|
|
39
|
-
// | Cloud upload (sampled JPEG feed) | 3 | JPEG IS the payload |
|
|
40
|
-
// | Live thumbnail preview UI | 3 | `<Image source={{uri: ...}}>` |
|
|
41
|
-
//
|
|
42
|
-
// See `docs/host-app-integration.md` § "Tier 2 + 3" for recipes.
|
|
43
|
-
//
|
|
44
|
-
// ## Threading
|
|
45
|
-
//
|
|
46
|
-
// The wrapped worklet fires on whatever runtime `useFrameProcessor`
|
|
47
|
-
// dispatches on:
|
|
48
|
-
// - **Non-AR mode**: vision-camera's Frame Processor runtime
|
|
49
|
-
// (producer thread).
|
|
50
|
-
// - **AR mode**: the lib's `RNSARWorkletRuntime` (iOS) /
|
|
51
|
-
// worklets-core default context (Android) — fired by the AR
|
|
52
|
-
// session's per-frame dispatch. See v0.8.0 Phase 4b.i / 4b.iii.
|
|
53
|
-
//
|
|
54
|
-
// Either way, the worklet MUST NOT block — the next frame's
|
|
55
|
-
// processing is gated on this one returning. Long work belongs
|
|
56
|
-
// behind `runOnJS` / a separate worklet runtime.
|
|
57
|
-
//
|
|
58
|
-
// ## Behaviour at the throttle boundary
|
|
59
|
-
//
|
|
60
|
-
// The hook tracks a monotonic-time shared value of "last sample time".
|
|
61
|
-
// Each tick checks if `frame.timestamp - lastSampleMs.value >=
|
|
62
|
-
// (1000 / sampleHz)`. If yes, the worklet body runs and the value
|
|
63
|
-
// updates; if no, the worklet returns silently.
|
|
64
|
-
//
|
|
65
|
-
// Edge cases:
|
|
66
|
-
// - First-ever tick: `lastSampleMs.value` starts at 0; first frame's
|
|
67
|
-
// timestamp will be >> 0 → first tick always fires. Subsequent
|
|
68
|
-
// ticks throttle as expected.
|
|
69
|
-
// - vc v4 timestamp semantics: per the project's worklet-throttle
|
|
70
|
-
// gotcha note, `frame.timestamp` is NOT reliably nanoseconds in
|
|
71
|
-
// vc v4. The hook treats `frame.timestamp` as ALREADY in
|
|
72
|
-
// milliseconds (which is what vc v4 actually delivers; the
|
|
73
|
-
// v0.8.0 StitcherFrame contract documents this). If a future
|
|
74
|
-
// vc version changes the unit, the throttle math here needs
|
|
75
|
-
// re-checking.
|
|
76
|
-
|
|
77
|
-
import type { DependencyList } from 'react';
|
|
78
|
-
import { useSharedValue } from 'react-native-worklets-core';
|
|
79
|
-
|
|
80
|
-
import { useFrameProcessor } from './useFrameProcessor';
|
|
81
|
-
import type {
|
|
82
|
-
StitcherFrame,
|
|
83
|
-
StitcherFrameProcessor,
|
|
84
|
-
} from './StitcherFrame';
|
|
85
|
-
import type { ThrottledFrameProcessorOptions } from '../types';
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Throttled variant of `useFrameProcessor`. See the module
|
|
89
|
-
* docstring for the full use-case mapping; quick version:
|
|
90
|
-
*
|
|
91
|
-
* ```tsx
|
|
92
|
-
* const fp = useThrottledFrameProcessor(
|
|
93
|
-
* (frame) => {
|
|
94
|
-
* 'worklet';
|
|
95
|
-
* // worklet-native OCR / ML / depth processing here
|
|
96
|
-
* },
|
|
97
|
-
* { sampleHz: 2 },
|
|
98
|
-
* [],
|
|
99
|
-
* );
|
|
100
|
-
* return <Camera frameProcessor={fp} ... />;
|
|
101
|
-
* ```
|
|
102
|
-
*
|
|
103
|
-
* @param worklet Host's frame-processor worklet. Must be
|
|
104
|
-
* `'worklet'`-prefixed. Runs at most `sampleHz`
|
|
105
|
-
* times per second.
|
|
106
|
-
* @param options `{ sampleHz }` — clamped to `[0.5, 30]`.
|
|
107
|
-
* @param deps Standard React deps array. Treated the same as
|
|
108
|
-
* `useFrameProcessor`'s deps — when they change the
|
|
109
|
-
* inner worklet is re-bound.
|
|
110
|
-
*
|
|
111
|
-
* @returns A `useFrameProcessor`-shaped processor object, pass it
|
|
112
|
-
* to `<Camera frameProcessor={...}>`.
|
|
113
|
-
*/
|
|
114
|
-
export function useThrottledFrameProcessor(
|
|
115
|
-
worklet: StitcherFrameProcessor,
|
|
116
|
-
options: ThrottledFrameProcessorOptions,
|
|
117
|
-
deps: DependencyList,
|
|
118
|
-
): ReturnType<typeof useFrameProcessor> {
|
|
119
|
-
// Clamp + derive interval. Done outside the worklet so the
|
|
120
|
-
// useSharedValue / useFrameProcessor hooks see stable values.
|
|
121
|
-
const sampleHz = Math.max(0.5, Math.min(30, options.sampleHz));
|
|
122
|
-
const minIntervalMs = 1000 / sampleHz;
|
|
123
|
-
|
|
124
|
-
// Monotonic-time gate. Initialised to 0 → first tick always
|
|
125
|
-
// fires (frame.timestamp >> 0).
|
|
126
|
-
const lastSampleMs = useSharedValue(0);
|
|
127
|
-
|
|
128
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
129
|
-
return useFrameProcessor(
|
|
130
|
-
(frame: StitcherFrame) => {
|
|
131
|
-
'worklet';
|
|
132
|
-
const now = frame.timestamp;
|
|
133
|
-
if (now - lastSampleMs.value < minIntervalMs) {
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
lastSampleMs.value = now;
|
|
137
|
-
worklet(frame);
|
|
138
|
-
},
|
|
139
|
-
// The throttle interval is captured in the worklet closure; if
|
|
140
|
-
// it changes we need to re-bind the worklet so the new
|
|
141
|
-
// `minIntervalMs` takes effect. Same for the host's worklet
|
|
142
|
-
// identity (so deps changes on the host side re-bind too).
|
|
143
|
-
[minIntervalMs, worklet, ...deps],
|
|
144
|
-
);
|
|
145
|
-
}
|