react-native-image-stitcher 0.14.2 → 0.15.1

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.
Files changed (120) hide show
  1. package/CHANGELOG.md +164 -0
  2. package/README.md +35 -0
  3. package/RNImageStitcher.podspec +8 -7
  4. package/android/build.gradle +0 -16
  5. package/android/src/main/cpp/CMakeLists.txt +2 -63
  6. package/android/src/main/cpp/image_stitcher_jni.cpp +14 -0
  7. package/android/src/main/cpp/keyframe_gate_jni.cpp +13 -0
  8. package/android/src/main/java/io/imagestitcher/rn/BatchStitcher.kt +285 -3
  9. package/android/src/main/java/io/imagestitcher/rn/IncrementalStitcher.kt +180 -1162
  10. package/android/src/main/java/io/imagestitcher/rn/KeyframeGate.kt +29 -0
  11. package/android/src/main/java/io/imagestitcher/rn/RNImageStitcherPackage.kt +0 -4
  12. package/android/src/main/java/io/imagestitcher/rn/RNSARCameraView.kt +129 -71
  13. package/android/src/main/java/io/imagestitcher/rn/RNSARSession.kt +49 -0
  14. package/cpp/keyframe_gate.cpp +82 -23
  15. package/cpp/keyframe_gate.hpp +31 -2
  16. package/cpp/stitcher.cpp +208 -28
  17. package/cpp/tests/CMakeLists.txt +18 -12
  18. package/cpp/tests/keyframe_timebudget_test.cpp +65 -0
  19. package/cpp/tests/warp_guard_test.cpp +48 -0
  20. package/cpp/warp_guard.hpp +41 -0
  21. package/dist/camera/Camera.d.ts +31 -16
  22. package/dist/camera/Camera.js +11 -3
  23. package/dist/camera/CameraView.js +93 -3
  24. package/dist/camera/CaptureStitchStatsToast.d.ts +15 -2
  25. package/dist/camera/CaptureStitchStatsToast.js +27 -7
  26. package/dist/camera/PanoramaSettings.d.ts +10 -223
  27. package/dist/camera/PanoramaSettings.js +6 -28
  28. package/dist/camera/PanoramaSettingsBridge.d.ts +1 -24
  29. package/dist/camera/PanoramaSettingsBridge.js +3 -102
  30. package/dist/camera/PanoramaSettingsModal.js +7 -1
  31. package/dist/camera/buildPanoramaInitialSettings.d.ts +11 -0
  32. package/dist/camera/buildPanoramaInitialSettings.js +4 -0
  33. package/dist/camera/cameraErrorMessages.d.ts +32 -0
  34. package/dist/camera/cameraErrorMessages.js +53 -0
  35. package/dist/camera/selectCaptureDevice.d.ts +5 -1
  36. package/dist/camera/selectCaptureDevice.js +22 -2
  37. package/dist/camera/useCapture.js +38 -0
  38. package/dist/index.d.ts +5 -8
  39. package/dist/index.js +11 -34
  40. package/dist/stitching/incremental.d.ts +1 -117
  41. package/dist/stitching/stitchVideo.d.ts +0 -35
  42. package/dist/types.d.ts +0 -87
  43. package/ios/Sources/RNImageStitcher/IncrementalStitcher.swift +96 -674
  44. package/ios/Sources/RNImageStitcher/IncrementalStitcherBridge.swift +9 -12
  45. package/ios/Sources/RNImageStitcher/KeyframeGate.swift +14 -0
  46. package/ios/Sources/RNImageStitcher/KeyframeGateBridge.h +7 -0
  47. package/ios/Sources/RNImageStitcher/KeyframeGateBridge.mm +6 -0
  48. package/ios/Sources/RNImageStitcher/OpenCVKeyframeCollector.h +2 -2
  49. package/ios/Sources/RNImageStitcher/OpenCVKeyframeCollector.mm +3 -3
  50. package/ios/Sources/RNImageStitcher/OpenCVStitcher.h +28 -60
  51. package/ios/Sources/RNImageStitcher/OpenCVStitcher.mm +180 -921
  52. package/ios/Sources/RNImageStitcher/RNSARCameraView.swift +82 -7
  53. package/ios/Sources/RNImageStitcher/RNSARSession.swift +10 -35
  54. package/ios/Sources/RNImageStitcher/Stitcher.swift +84 -35
  55. package/ios/Sources/RNImageStitcher/StitcherBridge.m +13 -0
  56. package/ios/Sources/RNImageStitcher/StitcherBridge.swift +132 -5
  57. package/package.json +3 -2
  58. package/src/camera/Camera.tsx +44 -23
  59. package/src/camera/CameraView.tsx +113 -4
  60. package/src/camera/CaptureStitchStatsToast.tsx +58 -14
  61. package/src/camera/PanoramaSettings.ts +16 -289
  62. package/src/camera/PanoramaSettingsBridge.ts +3 -114
  63. package/src/camera/PanoramaSettingsModal.tsx +14 -1
  64. package/src/camera/__tests__/PanoramaSettingsBridge.test.ts +3 -188
  65. package/src/camera/__tests__/buildPanoramaInitialSettings.test.ts +41 -0
  66. package/src/camera/__tests__/cameraErrorMessages.test.ts +76 -0
  67. package/src/camera/__tests__/selectCaptureDevice.test.ts +33 -0
  68. package/src/camera/buildPanoramaInitialSettings.ts +17 -0
  69. package/src/camera/cameraErrorMessages.ts +84 -0
  70. package/src/camera/selectCaptureDevice.ts +28 -3
  71. package/src/camera/useCapture.ts +44 -1
  72. package/src/index.ts +11 -40
  73. package/src/stitching/incremental.ts +3 -140
  74. package/src/stitching/stitchVideo.ts +0 -26
  75. package/src/types.ts +0 -95
  76. package/android/src/main/cpp/stitcher_jsi_install_jni.cpp +0 -227
  77. package/android/src/main/java/io/imagestitcher/rn/IncrementalFirstwinsEngine.kt +0 -1081
  78. package/android/src/main/java/io/imagestitcher/rn/StitcherJsiInstallerModule.kt +0 -103
  79. package/android/src/main/java/io/imagestitcher/rn/StitcherWorkletRuntime.kt +0 -256
  80. package/cpp/stitcher_frame_jsi.cpp +0 -214
  81. package/cpp/stitcher_frame_jsi.hpp +0 -108
  82. package/cpp/stitcher_proxy_jsi.cpp +0 -109
  83. package/cpp/stitcher_proxy_jsi.hpp +0 -46
  84. package/cpp/stitcher_worklet_dispatch.cpp +0 -103
  85. package/cpp/stitcher_worklet_dispatch.hpp +0 -71
  86. package/cpp/stitcher_worklet_registry.cpp +0 -91
  87. package/cpp/stitcher_worklet_registry.hpp +0 -146
  88. package/cpp/tests/stitcher_worklet_registry_test.cpp +0 -195
  89. package/dist/stitching/IncrementalStitcherView.d.ts +0 -41
  90. package/dist/stitching/IncrementalStitcherView.js +0 -157
  91. package/dist/stitching/StitcherWorkletRegistry.d.ts +0 -117
  92. package/dist/stitching/StitcherWorkletRegistry.js +0 -78
  93. package/dist/stitching/ensureStitcherProxyInstalled.d.ts +0 -8
  94. package/dist/stitching/ensureStitcherProxyInstalled.js +0 -81
  95. package/dist/stitching/useFrameProcessor.d.ts +0 -119
  96. package/dist/stitching/useFrameProcessor.js +0 -196
  97. package/dist/stitching/useFrameStream.d.ts +0 -34
  98. package/dist/stitching/useFrameStream.js +0 -234
  99. package/dist/stitching/useThrottledFrameProcessor.d.ts +0 -33
  100. package/dist/stitching/useThrottledFrameProcessor.js +0 -132
  101. package/ios/Sources/RNImageStitcher/OpenCVIncrementalStitcher.h +0 -474
  102. package/ios/Sources/RNImageStitcher/OpenCVIncrementalStitcher.mm +0 -1328
  103. package/ios/Sources/RNImageStitcher/OpenCVSlitScanStitcher.h +0 -103
  104. package/ios/Sources/RNImageStitcher/OpenCVSlitScanStitcher.mm +0 -3285
  105. package/ios/Sources/RNImageStitcher/RNSARWorkletRuntime.h +0 -128
  106. package/ios/Sources/RNImageStitcher/RNSARWorkletRuntime.mm +0 -313
  107. package/ios/Sources/RNImageStitcher/SaveFrameAsJpegPlugin.mm +0 -185
  108. package/ios/Sources/RNImageStitcher/StitcherFrameHostObject.h +0 -60
  109. package/ios/Sources/RNImageStitcher/StitcherFrameHostObject.mm +0 -214
  110. package/ios/Sources/RNImageStitcher/StitcherJsiInstaller.h +0 -42
  111. package/ios/Sources/RNImageStitcher/StitcherJsiInstaller.mm +0 -160
  112. package/src/stitching/IncrementalStitcherView.tsx +0 -198
  113. package/src/stitching/StitcherWorkletRegistry.ts +0 -156
  114. package/src/stitching/__tests__/StitcherWorkletRegistry.test.ts +0 -176
  115. package/src/stitching/__tests__/ensureStitcherProxyInstalled.test.ts +0 -94
  116. package/src/stitching/__tests__/useThrottledFrameProcessor.test.ts +0 -178
  117. package/src/stitching/ensureStitcherProxyInstalled.ts +0 -141
  118. package/src/stitching/useFrameProcessor.ts +0 -226
  119. package/src/stitching/useFrameStream.ts +0 -271
  120. 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
- }