react-native-image-stitcher 0.15.2 → 0.16.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 +124 -1
- package/README.md +116 -5
- package/android/src/main/cpp/image_stitcher_jni.cpp +107 -11
- package/android/src/main/java/io/imagestitcher/rn/BatchStitcher.kt +223 -1
- package/android/src/main/java/io/imagestitcher/rn/IncrementalStitcher.kt +87 -30
- package/android/src/main/java/io/imagestitcher/rn/KeyframeGate.kt +1 -1
- package/android/src/main/java/io/imagestitcher/rn/RNSARSession.kt +14 -8
- package/android/src/main/java/io/imagestitcher/rn/ar/YuvImageConverter.kt +39 -1
- package/cpp/crop_quad.cpp +162 -0
- package/cpp/crop_quad.hpp +163 -0
- package/cpp/stitcher.cpp +651 -55
- package/cpp/stitcher.hpp +10 -0
- package/cpp/warp_guard.hpp +212 -0
- package/dist/camera/Camera.d.ts +196 -12
- package/dist/camera/Camera.js +629 -35
- package/dist/camera/CameraView.js +35 -16
- package/dist/camera/CaptureCountdownOverlay.d.ts +70 -0
- package/dist/camera/CaptureCountdownOverlay.js +239 -0
- package/dist/camera/CaptureFrameCounterOverlay.d.ts +58 -0
- package/dist/camera/CaptureFrameCounterOverlay.js +142 -0
- package/dist/camera/CaptureMemoryPill.d.ts +9 -1
- package/dist/camera/CaptureMemoryPill.js +3 -3
- package/dist/camera/CapturePreview.js +2 -1
- package/dist/camera/CaptureStatusOverlay.d.ts +11 -4
- package/dist/camera/CaptureStatusOverlay.js +22 -5
- package/dist/camera/CaptureThumbnailStrip.js +2 -1
- package/dist/camera/LateralMotionModal.d.ts +85 -0
- package/dist/camera/LateralMotionModal.js +134 -0
- package/dist/camera/PanHowToOverlay.d.ts +76 -0
- package/dist/camera/PanHowToOverlay.js +222 -0
- package/dist/camera/PanoramaSettings.d.ts +8 -6
- package/dist/camera/PanoramaSettings.js +26 -5
- package/dist/camera/PanoramaSettingsModal.js +4 -4
- package/dist/camera/RectCropPreview.d.ts +161 -0
- package/dist/camera/RectCropPreview.js +480 -0
- package/dist/camera/RotateToLandscapePrompt.d.ts +87 -0
- package/dist/camera/RotateToLandscapePrompt.js +138 -0
- package/dist/camera/buildPanoramaInitialSettings.d.ts +19 -2
- package/dist/camera/buildPanoramaInitialSettings.js +9 -0
- package/dist/camera/cameraErrorMessages.d.ts +30 -1
- package/dist/camera/cameraErrorMessages.js +26 -10
- package/dist/camera/cameraGuidanceCopy.d.ts +87 -0
- package/dist/camera/cameraGuidanceCopy.js +80 -0
- package/dist/camera/captureCountdown.d.ts +52 -0
- package/dist/camera/captureCountdown.js +76 -0
- package/dist/camera/captureWarnings.d.ts +90 -0
- package/dist/camera/captureWarnings.js +108 -0
- package/dist/camera/classifyStitchError.d.ts +30 -0
- package/dist/camera/classifyStitchError.js +42 -0
- package/dist/camera/cropGeometry.d.ts +136 -0
- package/dist/camera/cropGeometry.js +223 -0
- package/dist/camera/displayDecodeImageProps.d.ts +25 -0
- package/dist/camera/displayDecodeImageProps.js +29 -0
- package/dist/camera/guidanceGraphics.d.ts +58 -0
- package/dist/camera/guidanceGraphics.js +280 -0
- package/dist/camera/guidanceTokens.d.ts +54 -0
- package/dist/camera/guidanceTokens.js +58 -0
- package/dist/camera/panModeGate.d.ts +54 -0
- package/dist/camera/panModeGate.js +62 -0
- package/dist/camera/pickCaptureFormat.d.ts +71 -0
- package/dist/camera/pickCaptureFormat.js +85 -0
- package/dist/camera/stitchDebugInfo.d.ts +27 -0
- package/dist/camera/stitchDebugInfo.js +55 -0
- package/dist/camera/usePanMotion.d.ts +250 -0
- package/dist/camera/usePanMotion.js +451 -0
- package/dist/index.d.ts +24 -3
- package/dist/index.js +33 -2
- package/dist/stitching/computeInscribedRect.d.ts +40 -0
- package/dist/stitching/computeInscribedRect.js +55 -0
- package/dist/stitching/cropQuad.d.ts +78 -0
- package/dist/stitching/cropQuad.js +116 -0
- package/dist/stitching/incremental.d.ts +45 -0
- package/ios/Sources/RNImageStitcher/IncrementalStitcher.swift +56 -8
- package/ios/Sources/RNImageStitcher/KeyframeGate.swift +2 -2
- package/ios/Sources/RNImageStitcher/OpenCVKeyframeCollector.mm +48 -5
- package/ios/Sources/RNImageStitcher/OpenCVStitcher.h +27 -0
- package/ios/Sources/RNImageStitcher/OpenCVStitcher.mm +191 -7
- package/ios/Sources/RNImageStitcher/RNSARSession.swift +25 -1
- package/ios/Sources/RNImageStitcher/Stitcher.swift +34 -1
- package/ios/Sources/RNImageStitcher/StitcherBridge.m +5 -0
- package/ios/Sources/RNImageStitcher/StitcherBridge.swift +56 -0
- package/package.json +5 -1
- package/src/camera/Camera.tsx +994 -47
- package/src/camera/CameraView.tsx +48 -16
- package/src/camera/CaptureCountdownOverlay.tsx +272 -0
- package/src/camera/CaptureFrameCounterOverlay.tsx +183 -0
- package/src/camera/CaptureMemoryPill.tsx +17 -3
- package/src/camera/CapturePreview.tsx +5 -0
- package/src/camera/CaptureStatusOverlay.tsx +35 -7
- package/src/camera/CaptureThumbnailStrip.tsx +4 -0
- package/src/camera/LateralMotionModal.tsx +199 -0
- package/src/camera/PanHowToOverlay.tsx +246 -0
- package/src/camera/PanoramaSettings.ts +34 -11
- package/src/camera/PanoramaSettingsModal.tsx +4 -4
- package/src/camera/RectCropPreview.tsx +820 -0
- package/src/camera/RotateToLandscapePrompt.tsx +188 -0
- package/src/camera/buildPanoramaInitialSettings.ts +30 -1
- package/src/camera/cameraErrorMessages.ts +39 -2
- package/src/camera/cameraGuidanceCopy.ts +145 -0
- package/src/camera/captureCountdown.ts +83 -0
- package/src/camera/captureWarnings.ts +190 -0
- package/src/camera/classifyStitchError.ts +68 -0
- package/src/camera/cropGeometry.ts +268 -0
- package/src/camera/displayDecodeImageProps.ts +25 -0
- package/src/camera/guidanceGraphics.tsx +347 -0
- package/src/camera/guidanceTokens.ts +57 -0
- package/src/camera/panModeGate.ts +81 -0
- package/src/camera/pickCaptureFormat.ts +130 -0
- package/src/camera/stitchDebugInfo.ts +71 -0
- package/src/camera/usePanMotion.ts +667 -0
- package/src/index.ts +66 -3
- package/src/stitching/computeInscribedRect.ts +81 -0
- package/src/stitching/cropQuad.ts +167 -0
- package/src/stitching/incremental.ts +45 -0
- package/cpp/tests/CMakeLists.txt +0 -104
- package/cpp/tests/README.md +0 -86
- package/cpp/tests/keyframe_timebudget_test.cpp +0 -65
- package/cpp/tests/pose_test.cpp +0 -74
- package/cpp/tests/stitcher_frame_data_test.cpp +0 -132
- package/cpp/tests/stubs/jsi/jsi.h +0 -33
- package/cpp/tests/stubs/react-native-worklets-core/WKTJsiWorklet.h +0 -34
- package/cpp/tests/warp_guard_test.cpp +0 -48
- package/src/camera/__tests__/PanoramaSettingsBridge.test.ts +0 -190
- package/src/camera/__tests__/bandThumbRotation.test.ts +0 -120
- package/src/camera/__tests__/buildPanoramaInitialSettings.test.ts +0 -160
- package/src/camera/__tests__/cameraErrorMessages.test.ts +0 -76
- package/src/camera/__tests__/homeIndicatorEdge.test.ts +0 -116
- package/src/camera/__tests__/lowMemDevice.test.ts +0 -52
- package/src/camera/__tests__/selectCaptureDevice.test.ts +0 -210
- package/src/camera/__tests__/useContentRotation.test.ts +0 -89
- package/src/camera/__tests__/useOrientationDrift.test.ts +0 -169
- package/src/stitching/__tests__/subscribeIncrementalState.refine.test.ts +0 -276
- package/src/stitching/__tests__/useStitcherWorklet.test.ts +0 -202
|
@@ -77,8 +77,21 @@ exports.DEFAULT_PANORAMA_SETTINGS = {
|
|
|
77
77
|
captureSource: 'ar',
|
|
78
78
|
debug: false,
|
|
79
79
|
stitcher: {
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
// v0.16 — PANORAMA by default (was 'auto'). The auto-resolver's SCANS
|
|
81
|
+
// branch leans on double-integrated IMU translation, which is unreliable
|
|
82
|
+
// during rotation (gravity leakage inflates the translation estimate); in
|
|
83
|
+
// practice rotational pans are the common case and resolve to panorama
|
|
84
|
+
// anyway. Defaulting to panorama is the robust choice — host apps that
|
|
85
|
+
// genuinely capture flat documents/walls can still opt into 'auto' or
|
|
86
|
+
// 'scans' via the ⚙️ panel or the `defaultStitchMode` / `stitcher` props.
|
|
87
|
+
stitchMode: 'panorama',
|
|
88
|
+
// v0.16 — SPHERICAL by default (bounds both axes; the proven-robust wide/
|
|
89
|
+
// vertical-pan projection). This is now the single source of truth — the
|
|
90
|
+
// native side no longer hardcodes a warper, so the ⚙️ panel + the host's
|
|
91
|
+
// `defaultWarper` prop actually take effect. Note: choosing `plane` here
|
|
92
|
+
// re-arms the dynamic plane→spherical fallback/divergence switch in the
|
|
93
|
+
// manual pipeline (it only fires when warperType != spherical).
|
|
94
|
+
warperType: 'spherical',
|
|
82
95
|
blenderType: 'multiband',
|
|
83
96
|
seamFinderType: 'graphcut',
|
|
84
97
|
// v0.15 — inscribed-rect crop is OFF by default (bbox crop keeps all
|
|
@@ -89,9 +102,17 @@ exports.DEFAULT_PANORAMA_SETTINGS = {
|
|
|
89
102
|
},
|
|
90
103
|
frameSelection: {
|
|
91
104
|
mode: 'flow-based',
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
105
|
+
// v0.16 — denser keyframes by default: a 15% novelty gate, up to 8 frames,
|
|
106
|
+
// plus a 1.5 s time-budget force-accept (so a slow/static pan still lands a
|
|
107
|
+
// keyframe every 1.5 s even when novelty is low). With 8 frames this bounds
|
|
108
|
+
// a static/slow capture to ~8×1.5 ≈ 12 s before the keyframe-count
|
|
109
|
+
// auto-finalize. More overlap between consecutive keyframes ⇒ stronger
|
|
110
|
+
// feature matching ⇒ more robust registration. Memory-checked: 8 frames fit
|
|
111
|
+
// the BATCH held-set cap on both platforms. Overlap selectable in the
|
|
112
|
+
// settings panel {10,15,20,30}% (native clamp floor 10%); cap clamps [3,10].
|
|
113
|
+
maxKeyframes: 8,
|
|
114
|
+
overlapThreshold: 0.15,
|
|
115
|
+
maxKeyframeIntervalMs: 1500,
|
|
95
116
|
flow: exports.DEFAULT_FLOW_GATE_SETTINGS,
|
|
96
117
|
},
|
|
97
118
|
};
|
|
@@ -182,17 +182,17 @@ function PanoramaSettingsModal({ visible, settings, onChange, onClose, }) {
|
|
|
182
182
|
react_1.default.createElement(SectionHeader, { title: "Max keyframes per capture" }),
|
|
183
183
|
react_1.default.createElement(SegmentedControl, { options: ['3', '4', '5', '6', '8', '10'], value: String(settings.frameSelection.maxKeyframes), onChange: (v) => updateFrameSelection({
|
|
184
184
|
maxKeyframes: parseInt(v, 10),
|
|
185
|
-
}), caption: "Hard cap on accepted keyframes; native clamps to [3, 10].
|
|
185
|
+
}), caption: "Hard cap on accepted keyframes; native clamps to [3, 10]. 8 (default) is the sweet spot for cv::detail BA convergence while giving the 15%-overlap + 1 s time gate room to land frames." }),
|
|
186
186
|
react_1.default.createElement(SectionHeader, { title: "Overlap threshold (new content per keyframe)" }),
|
|
187
|
-
react_1.default.createElement(SegmentedControl, { options: ['
|
|
187
|
+
react_1.default.createElement(SegmentedControl, { options: ['10%', '15%', '20%', '30%'], value: `${Math.round(settings.frameSelection.overlapThreshold * 100)}%`, onChange: (v) => updateFrameSelection({
|
|
188
188
|
overlapThreshold: parseInt(v, 10) / 100,
|
|
189
|
-
}), caption: "Required NEW-content fraction.
|
|
189
|
+
}), caption: "Required NEW-content fraction (lower = denser keyframes, more overlap). 15% (default): ~7\u20139 keyframes for a 90\u00B0 pan. 10% is the native clamp floor." }),
|
|
190
190
|
react_1.default.createElement(SectionHeader, { title: "Keyframe interval (time-budget force-accept)" }),
|
|
191
191
|
react_1.default.createElement(SegmentedControl, { options: ['off', '1s', '2s', '3s', '5s'], value: settings.frameSelection.maxKeyframeIntervalMs === 0
|
|
192
192
|
? 'off'
|
|
193
193
|
: `${settings.frameSelection.maxKeyframeIntervalMs / 1000}s`, onChange: (v) => updateFrameSelection({
|
|
194
194
|
maxKeyframeIntervalMs: v === 'off' ? 0 : parseInt(v, 10) * 1000,
|
|
195
|
-
}), caption: "Force-accept a keyframe at least this often even if novelty is low, so slow / static pans don't leave gaps. Counts toward the keyframe cap. off = disabled.
|
|
195
|
+
}), caption: "Force-accept a keyframe at least this often even if novelty is low, so slow / static pans don't leave gaps. Counts toward the keyframe cap. off = disabled. 1s (default). Applies to AR + non-AR." }),
|
|
196
196
|
showFlowTunables && (react_1.default.createElement(react_native_1.View, { style: styles.nested },
|
|
197
197
|
react_1.default.createElement(react_native_1.Text, { style: styles.nestedLabel }, "Flow tuning"),
|
|
198
198
|
react_1.default.createElement(SectionHeader, { title: "Max corners (Shi-Tomasi)" }),
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RectCropPreview — item-7 of the first-time-user guidance flow: the
|
|
3
|
+
* post-capture crop editor.
|
|
4
|
+
*
|
|
5
|
+
* Shows the full stitched result image (contain-fit, letterboxed) with a
|
|
6
|
+
* 4-corner quad overlay. Each corner is INDEPENDENTLY draggable in
|
|
7
|
+
* on-screen coords via RN-core `PanResponder` (deliberately NO
|
|
8
|
+
* react-native-gesture-handler dependency — this library ships zero extra
|
|
9
|
+
* native deps for guidance). Corner positions are mapped to image-pixel
|
|
10
|
+
* space through the pure `cropGeometry` letterbox transform.
|
|
11
|
+
*
|
|
12
|
+
* ## What it surfaces (and what it does NOT do)
|
|
13
|
+
*
|
|
14
|
+
* This component is presentation + gesture only. On confirm it computes
|
|
15
|
+
* the 4 image-pixel corners and hands them to `onConfirm` — it does NOT
|
|
16
|
+
* call any native crop. The PARENT decides between the cheap axis-aligned
|
|
17
|
+
* `cropToRect` (when the quad is ~rectangular) and the perspective
|
|
18
|
+
* `cropToQuad`, using the `perspective` flag in the result:
|
|
19
|
+
*
|
|
20
|
+
* onConfirm({ quad, perspective: perspectiveCorrect && !isAxisAligned })
|
|
21
|
+
*
|
|
22
|
+
* Promoted + extended from `example/InscribedRectDebug.tsx`, which already
|
|
23
|
+
* did the image-px ↔ on-screen contain-fit mapping, a rect overlay, and
|
|
24
|
+
* the in-place native crop. This version replaces the single computed
|
|
25
|
+
* inscribed rect with a user-draggable free quad and the perspective
|
|
26
|
+
* decision; the letterbox math now lives in the shared `cropGeometry`
|
|
27
|
+
* module. Styling is carried over from InscribedRectDebug.
|
|
28
|
+
*
|
|
29
|
+
* ## Seeding
|
|
30
|
+
*
|
|
31
|
+
* The initial quad comes from `initialRect` (image-pixel coords) when the
|
|
32
|
+
* host passes one — `<Camera>` passes the panorama's MAX-INSCRIBED rectangle
|
|
33
|
+
* (the tightest clean rectangle with no black corners; item 2) so the editor
|
|
34
|
+
* opens on a sensible crop the user drags to taste. With no `initialRect`
|
|
35
|
+
* (native inscribed-rect unavailable) it falls back to an 8 %-inset
|
|
36
|
+
* rectangle. "Reset" returns to whichever seed was used.
|
|
37
|
+
*/
|
|
38
|
+
import React from 'react';
|
|
39
|
+
import { type GuidanceCopy } from './cameraGuidanceCopy';
|
|
40
|
+
import { type Quad } from './cropGeometry';
|
|
41
|
+
/** Image-pixel rectangle, used for the optional `initialRect` seed. */
|
|
42
|
+
export interface ImageRect {
|
|
43
|
+
x: number;
|
|
44
|
+
y: number;
|
|
45
|
+
width: number;
|
|
46
|
+
height: number;
|
|
47
|
+
}
|
|
48
|
+
/** What the host receives when the user taps Crop. */
|
|
49
|
+
export interface RectCropResult {
|
|
50
|
+
/**
|
|
51
|
+
* The 4 chosen corners in IMAGE-PIXEL space, canonically ordered
|
|
52
|
+
* [TL, TR, BR, BL]. The host feeds these to the native crop.
|
|
53
|
+
*/
|
|
54
|
+
quad: Quad;
|
|
55
|
+
/**
|
|
56
|
+
* `true` → the host should perspective-rectify (`cropToQuad`): the user
|
|
57
|
+
* picked a non-rectangular quad and `perspectiveCorrect` is enabled.
|
|
58
|
+
* `false` → the host can use the cheap axis-aligned `cropToRect` (the
|
|
59
|
+
* quad is ~rectangular, or perspective correction is disabled).
|
|
60
|
+
*/
|
|
61
|
+
perspective: boolean;
|
|
62
|
+
}
|
|
63
|
+
export interface RectCropPreviewProps {
|
|
64
|
+
/** file:// URI of the full result image to crop. */
|
|
65
|
+
imageUri: string;
|
|
66
|
+
/** Intrinsic pixel width of `imageUri`. */
|
|
67
|
+
imageWidth: number;
|
|
68
|
+
/** Intrinsic pixel height of `imageUri`. */
|
|
69
|
+
imageHeight: number;
|
|
70
|
+
/**
|
|
71
|
+
* DEBUG A/B harness — file:// URI of the SAME capture stitched by the
|
|
72
|
+
* OPPOSITE pipeline (manual cv::detail + plane). When set, a toggle appears
|
|
73
|
+
* that flips the displayed panorama between the primary (high-level +
|
|
74
|
+
* spherical) and this one, for on-device comparison on a single capture.
|
|
75
|
+
* Its dimensions are read at runtime via `Image.getSize`. When the manual
|
|
76
|
+
* output is showing, the crop quad is hidden and the accept button emits
|
|
77
|
+
* THIS uri (so you can pick the better pipeline per capture).
|
|
78
|
+
*/
|
|
79
|
+
altImageUri?: string;
|
|
80
|
+
/**
|
|
81
|
+
* 2026-06-15 — ON-DEMAND alt (high-level) stitch. The PRIMARY image is the
|
|
82
|
+
* MANUAL pipeline (the default output); this callback re-stitches the SAME
|
|
83
|
+
* captured keyframes via cv::Stitcher and resolves with a file:// uri (or
|
|
84
|
+
* null on failure). It runs only the FIRST time the user taps the
|
|
85
|
+
* "High-level" tab — nothing is computed unless asked for. When provided (or
|
|
86
|
+
* `altImageUri` is), the A/B toggle appears.
|
|
87
|
+
*
|
|
88
|
+
* Resolves with the high-level output's file:// `uri` AND its OWN
|
|
89
|
+
* DEV-overlay `debugInfo` recipe (so the params pill can switch to the
|
|
90
|
+
* high-level recipe while that tab is viewed), or `null` on failure.
|
|
91
|
+
*/
|
|
92
|
+
onRequestAlt?: () => Promise<{
|
|
93
|
+
uri: string;
|
|
94
|
+
debugInfo: string;
|
|
95
|
+
} | null>;
|
|
96
|
+
/** Show / hide the editor. */
|
|
97
|
+
visible: boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Tapped on "Crop". Receives the ordered image-pixel quad + the
|
|
100
|
+
* perspective decision; the host performs the actual native crop.
|
|
101
|
+
*/
|
|
102
|
+
onConfirm: (result: RectCropResult) => void;
|
|
103
|
+
/**
|
|
104
|
+
* Tapped on "Use original" (or hardware back / dismiss) — emit the stitch
|
|
105
|
+
* un-cropped. Also called when the user collapses the quad to something
|
|
106
|
+
* un-warpable, so a degenerate quad never reaches the native crop.
|
|
107
|
+
*/
|
|
108
|
+
onUseOriginal: (uri?: string) => void;
|
|
109
|
+
/**
|
|
110
|
+
* Tapped on "Retake" — discard this capture entirely and return to the
|
|
111
|
+
* camera. No result is emitted (the host clears the editor + lets the
|
|
112
|
+
* user capture again).
|
|
113
|
+
*/
|
|
114
|
+
onRetake: () => void;
|
|
115
|
+
/**
|
|
116
|
+
* Optional non-fatal warning messages (e.g. "<70 % of frames used") shown
|
|
117
|
+
* as a banner across the top of the editor so the user sees them before
|
|
118
|
+
* accepting a crop. Empty / undefined → no banner.
|
|
119
|
+
*/
|
|
120
|
+
warnings?: string[];
|
|
121
|
+
/**
|
|
122
|
+
* Crop mode vs preview-only mode. `true` (default) shows the draggable
|
|
123
|
+
* quad + corner handles + the [Retake][Use original][Crop] bar — the full
|
|
124
|
+
* crop editor. `false` hides the quad and all crop affordances, showing
|
|
125
|
+
* just the stitched image with a [Retake][Confirm] bar — a plain preview
|
|
126
|
+
* (`<Camera showPreview>` without `rectCrop`). Confirm emits the image
|
|
127
|
+
* un-cropped (same as "Use original").
|
|
128
|
+
*/
|
|
129
|
+
showCropControls?: boolean;
|
|
130
|
+
/**
|
|
131
|
+
* Optional image-pixel seed rect for the draggable quad. Defaults to
|
|
132
|
+
* an 8 %-inset rectangle of the full image. Ignored in preview-only mode.
|
|
133
|
+
*/
|
|
134
|
+
initialRect?: ImageRect;
|
|
135
|
+
/** Copy overrides (cropConfirm / cropReset). Falls back to defaults. */
|
|
136
|
+
copy?: Partial<GuidanceCopy>;
|
|
137
|
+
/**
|
|
138
|
+
* Safe-area insets (px). The editor is a full-screen Modal, so the host
|
|
139
|
+
* passes `insets.top`/`insets.bottom` to keep the top toolbar (A/B toggle,
|
|
140
|
+
* warnings) clear of the notch/Dynamic Island and the bottom button bar
|
|
141
|
+
* clear of the home indicator. Default 0.
|
|
142
|
+
*/
|
|
143
|
+
topInset?: number;
|
|
144
|
+
bottomInset?: number;
|
|
145
|
+
/**
|
|
146
|
+
* 2026-06-14 (DEV overlay) — optional multi-line debug text describing how
|
|
147
|
+
* this output was stitched (pipeline / warper / route / seam / blend / score
|
|
148
|
+
* / frames / size). When non-empty, rendered as a small monospace pill in
|
|
149
|
+
* the top-right corner. The host gates this on `__DEV__`; this component
|
|
150
|
+
* just renders whatever non-empty string it's given.
|
|
151
|
+
*/
|
|
152
|
+
debugInfo?: string;
|
|
153
|
+
/**
|
|
154
|
+
* 2026-06-15 — show the live memory-footprint pill (polled native RSS,
|
|
155
|
+
* green/amber/red) on the preview too, so the operator can watch the spike
|
|
156
|
+
* when the on-demand high-level re-stitch fires. Host gates on settings.debug.
|
|
157
|
+
*/
|
|
158
|
+
showMemoryPill?: boolean;
|
|
159
|
+
}
|
|
160
|
+
export declare function RectCropPreview(props: RectCropPreviewProps): React.JSX.Element;
|
|
161
|
+
//# sourceMappingURL=RectCropPreview.d.ts.map
|