react-native-image-stitcher 0.5.1 → 0.6.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 CHANGED
@@ -16,6 +16,111 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
16
16
 
17
17
  ## [Unreleased]
18
18
 
19
+ ## [0.6.0] — 2026-05-25
20
+
21
+ > [!WARNING]
22
+ > **Breaking changes.** v0.6.0 retires the deprecated JS-driver
23
+ > non-AR path that was marked for removal in v0.5.0's *Deprecated*
24
+ > section. Hosts using the default `<Camera>` flow (`legacyDriver`
25
+ > unset) are not affected — they were already on
26
+ > `useFrameProcessorDriver`. Hosts that opted into the legacy
27
+ > driver (`legacyDriver={true}` on `<Camera>`, or a direct
28
+ > `useIncrementalJSDriver()` consumer) MUST migrate to the Frame
29
+ > Processor driver — see *Migration from 0.5.x* below.
30
+
31
+ ### Removed (breaking)
32
+
33
+ - **`useIncrementalJSDriver` hook** + its `UseIncrementalJSDriverOptions`
34
+ / `IncrementalJSDriverHandle` types. Deprecated in v0.5.0; the
35
+ v0.5 deprecation warning has now been replaced by deletion.
36
+ - **`legacyDriver?: boolean` prop on `<Camera>`**. The escape hatch
37
+ back to the JS driver is gone. Hosts that set this prop will
38
+ get a TS-level error; at runtime the prop is silently ignored.
39
+ - **`frameSourceMode: 'jsDriver'`** enum value in
40
+ `IncrementalStartOptions`. The TS type is now narrowed to
41
+ `'arSession' | 'frameProcessor'`. Passing `'jsDriver'` is a
42
+ compile error; at the native bridge layer the value falls through
43
+ to the default (now `'arSession'`).
44
+ - **`IncrementalStitcher.processFrameAtPath` native method** on both
45
+ iOS and Android. The only JS caller was `useIncrementalJSDriver`,
46
+ also deleted. Hosts calling
47
+ `NativeModules.IncrementalStitcher.processFrameAtPath(...)` via
48
+ raw `NativeModules` access will get a runtime "method does not
49
+ exist" error. Use the Frame Processor driver instead.
50
+
51
+ ### Changed (breaking)
52
+
53
+ - **Android `frameSourceMode` default switched from `"jsDriver"` to
54
+ `"arSession"`** for parity with iOS. Raw `NativeModules` callers
55
+ that omitted `frameSourceMode` were previously getting an inert
56
+ capture (the "jsDriver" branch dropped all engine input on
57
+ Android since v0.5.0); they now get AR-mode behaviour, matching
58
+ iOS. The production `<Camera>` is unaffected — it always passes
59
+ `frameSourceMode: 'arSession'` explicitly for AR captures.
60
+
61
+ ### Changed (non-breaking)
62
+
63
+ - **`RNSARCameraView` (AR mode) no longer eager-encodes a JPEG per
64
+ ARCore frame.** Migrated to the pixel-data path introduced for
65
+ the Frame Processor in v0.5.1's F8.6 work. AR-mode captures now
66
+ pass `nv21PixelData` / `nv21PixelWidth` / `nv21PixelHeight`
67
+ through `ingestFromARCameraView`; `legacyJpegPath` is always null
68
+ on this path. Expected gain on Galaxy A35: ~30-50 ms per
69
+ accepted frame, with the dominant savings on rejected frames
70
+ (no JPEG encode → no imread round-trip). Closes the v0.5.0
71
+ follow-up.
72
+
73
+ ### Removed (internal cleanup; no external API impact)
74
+
75
+ - **F8.6 perf-diagnostic logs** (`F8.6-route`, `F8.6-perf`)
76
+ introduced in v0.5.1 stripped from `IncrementalStitcher` +
77
+ `IncrementalFirstwinsEngine` — F8.6 is now baked in for
78
+ production and the diagnostic spam is no longer informative.
79
+ - **Orphaned native helpers** dropped after `processFrameAtPath`
80
+ removal:
81
+ - iOS: `addBatchKeyframePath(path:pose:)`, `isBatchKeyframeMode`
82
+ getter, `decodeJpegToGrayscalePixelBuffer` (only callers were
83
+ `processFrameAtPath`).
84
+ - Android: `decodeJpegToGrayscale` + `GrayscaleFrame` data class,
85
+ `isBatchKeyframeMode` getter (only callers were
86
+ `processFrameAtPath` and the AR-mode eager-encode branch).
87
+ - **Stale comments** referencing removed code paths swept across
88
+ Kotlin/Swift/Obj-C/TS. Historical "removed in v0.6" markers
89
+ retained; comments that described live code in terms of the
90
+ removed names rewritten to describe current behaviour.
91
+
92
+ ### Migration from 0.5.x
93
+
94
+ **Default `<Camera>` hosts (no `legacyDriver` prop set):** no
95
+ action required. `<Camera>` already used `useFrameProcessorDriver`
96
+ in non-AR mode and `RNSARSession` in AR mode since v0.5.0.
97
+
98
+ **Hosts with `legacyDriver={true}` on `<Camera>`:** remove the
99
+ prop. `<Camera>` will use the Frame Processor driver, which has
100
+ been the default since v0.5.0 and the only path since this release.
101
+
102
+ ```tsx
103
+ // Before (v0.5.x)
104
+ <Camera legacyDriver={true} ... />
105
+
106
+ // After (v0.6.0)
107
+ <Camera ... />
108
+ ```
109
+
110
+ **Hosts directly using `useIncrementalJSDriver`:** migrate to
111
+ `useFrameProcessorDriver`. The handle shape (`{ start, stop,
112
+ frameProcessor, isRunning }`) is preserved, but the new hook is a
113
+ Frame Processor + gyro driver instead of a `takeSnapshot` + JS
114
+ interval driver. See
115
+ [`src/stitching/useFrameProcessorDriver.ts`](src/stitching/useFrameProcessorDriver.ts)
116
+ for the migration mapping; the gyro pose synthesis convention
117
+ (`q = q_yaw * q_pitch * q_roll`) is identical, so existing pose
118
+ math at call sites continues to work.
119
+
120
+ **Hosts passing `frameSourceMode: 'jsDriver'` to
121
+ `incremental.start(...)`:** change to `'frameProcessor'`. The
122
+ TypeScript type now rejects `'jsDriver'` at compile time.
123
+
19
124
  ## [0.5.1] — 2026-05-25
20
125
 
21
126
  ### Added — F8.6 Android pixel-buffer engine parity
@@ -1056,7 +1161,12 @@ Native module names also changed:
1056
1161
  - iOS pod: `RetaiLensCaptureSDK` → `RNImageStitcher`
1057
1162
  - iOS xcframework: shipped as `opencv2.xcframework` (linked from `RNImageStitcher.podspec`)
1058
1163
 
1059
- [Unreleased]: https://github.com/bhargavkanda/react-native-image-stitcher/compare/v0.3.0...HEAD
1164
+ [Unreleased]: https://github.com/bhargavkanda/react-native-image-stitcher/compare/v0.6.0...HEAD
1165
+ [0.6.0]: https://github.com/bhargavkanda/react-native-image-stitcher/compare/v0.5.1...v0.6.0
1166
+ [0.5.1]: https://github.com/bhargavkanda/react-native-image-stitcher/compare/v0.5.0...v0.5.1
1167
+ [0.5.0]: https://github.com/bhargavkanda/react-native-image-stitcher/compare/v0.4.1...v0.5.0
1168
+ [0.4.1]: https://github.com/bhargavkanda/react-native-image-stitcher/compare/v0.4.0...v0.4.1
1169
+ [0.4.0]: https://github.com/bhargavkanda/react-native-image-stitcher/compare/v0.3.0...v0.4.0
1060
1170
  [0.3.0]: https://github.com/bhargavkanda/react-native-image-stitcher/compare/v0.2.1...v0.3.0
1061
1171
  [0.2.1]: https://github.com/bhargavkanda/react-native-image-stitcher/compare/v0.2.0...v0.2.1
1062
1172
  [0.2.0]: https://github.com/bhargavkanda/react-native-image-stitcher/compare/v0.1.3...v0.2.0
@@ -29,8 +29,8 @@ import com.mrousavy.camera.frameprocessors.VisionCameraProxy
29
29
  * 3. Call `IncrementalStitcher.consumeFrameFromPlugin(image, …)`
30
30
  * which:
31
31
  * - Drops the call if `frameSourceMode != "frameProcessor"`
32
- * (prevents double-feeding the engine alongside the legacy
33
- * `processFrameAtPath` path).
32
+ * (prevents double-feeding the engine alongside the
33
+ * AR-mode `ingestFromARCameraView` path).
34
34
  * - Otherwise: extracts the Y plane, evaluates the keyframe
35
35
  * gate via `KeyframeGate.evaluateWithFrame`, encodes the
36
36
  * accepted frame to JPEG synchronously, and hands the path
@@ -197,7 +197,7 @@ internal class IncrementalFirstwinsEngine(
197
197
  }
198
198
  val frameBGR = downsampleToCompose(srcRaw)
199
199
  if (frameBGR !== srcRaw) srcRaw.release()
200
- val tele = addFrameMat(
200
+ return addFrameMat(
201
201
  frameBGR,
202
202
  qx, qy, qz, qw,
203
203
  fx, fy, cx, cy,
@@ -206,8 +206,6 @@ internal class IncrementalFirstwinsEngine(
206
206
  fovHorizDegrees, fovVertDegrees,
207
207
  t0,
208
208
  )
209
- f8_6_logPerf("firstwins/jpeg", t0, tele.outcome)
210
- return tele
211
209
  }
212
210
 
213
211
  /**
@@ -283,7 +281,7 @@ internal class IncrementalFirstwinsEngine(
283
281
  }
284
282
  val frameBGR = downsampleToCompose(srcRaw)
285
283
  if (frameBGR !== srcRaw) srcRaw.release()
286
- val tele = addFrameMat(
284
+ return addFrameMat(
287
285
  frameBGR,
288
286
  qx, qy, qz, qw,
289
287
  fx, fy, cx, cy,
@@ -292,32 +290,6 @@ internal class IncrementalFirstwinsEngine(
292
290
  fovHorizDegrees, fovVertDegrees,
293
291
  t0,
294
292
  )
295
- f8_6_logPerf("firstwins/pixel", t0, tele.outcome)
296
- return tele
297
- }
298
-
299
- /**
300
- * F8.6 perf-diagnostic counter. Logs ingest timing every Nth
301
- * call so a single capture session yields enough samples to
302
- * eyeball the JPEG-path vs pixel-data-path delta. Remove this
303
- * once F8.6 is verified in production.
304
- */
305
- @Volatile private var f8_6_perfCallCounter: Long = 0L
306
- private fun f8_6_logPerf(
307
- path: String,
308
- t0Nanos: Long,
309
- outcome: FrameOutcome,
310
- ) {
311
- val n = ++f8_6_perfCallCounter
312
- // Every 5th call ≈ ~1 line/sec at 5 Hz live-engine rate;
313
- // first call always logs so we see something on capture
314
- // start without waiting.
315
- if (n == 1L || n % 5L == 0L) {
316
- Log.i(
317
- "F8.6-perf",
318
- "$path took ${msSince(t0Nanos)}ms outcome=$outcome (call #$n)",
319
- )
320
- }
321
293
  }
322
294
 
323
295
  /**