supervision 0.2.4 → 0.2.6

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 (166) hide show
  1. package/dist/depth-preview-probe-DG7McQEN.js +314 -0
  2. package/dist/depth-preview-probe-DG7McQEN.js.map +1 -0
  3. package/dist/depth-preview-track-BvgwNEE9.js +612 -0
  4. package/dist/depth-preview-track-BvgwNEE9.js.map +1 -0
  5. package/dist/detections/chunked-detection-frame-source.d.ts.map +1 -1
  6. package/dist/index.d.ts +4 -2
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +9504 -4719
  9. package/dist/index.js.map +1 -1
  10. package/dist/mask-preparation.worker.js +658 -21
  11. package/dist/mask-preparation.worker.js.map +1 -1
  12. package/dist/media/decoder-deadline.d.ts +18 -0
  13. package/dist/media/decoder-deadline.d.ts.map +1 -0
  14. package/dist/media/depth-preview-probe.d.ts +65 -0
  15. package/dist/media/depth-preview-probe.d.ts.map +1 -0
  16. package/dist/media/depth-preview-track.d.ts +96 -0
  17. package/dist/media/depth-preview-track.d.ts.map +1 -0
  18. package/dist/media/media-normalization.d.ts.map +1 -1
  19. package/dist/media/media-source.d.ts +7 -0
  20. package/dist/media/media-source.d.ts.map +1 -1
  21. package/dist/media/mediabunny-frame-clock.d.ts +7 -0
  22. package/dist/media/mediabunny-frame-clock.d.ts.map +1 -0
  23. package/dist/media/mediabunny-media-source.d.ts +3 -0
  24. package/dist/media/mediabunny-media-source.d.ts.map +1 -1
  25. package/dist/media/track-frame-index.d.ts +14 -0
  26. package/dist/media/track-frame-index.d.ts.map +1 -0
  27. package/dist/media/video-engine-media-source.d.ts.map +1 -1
  28. package/dist/media/video-engine-media-source.js +1 -1
  29. package/dist/render-preparation/depth/clip-preview.d.ts +41 -0
  30. package/dist/render-preparation/depth/clip-preview.d.ts.map +1 -0
  31. package/dist/render-preparation/depth/clip-timing.d.ts +18 -0
  32. package/dist/render-preparation/depth/clip-timing.d.ts.map +1 -0
  33. package/dist/render-preparation/depth/clip.d.ts +14 -0
  34. package/dist/render-preparation/depth/clip.d.ts.map +1 -0
  35. package/dist/render-preparation/depth/exact-at-rest.d.ts +44 -0
  36. package/dist/render-preparation/depth/exact-at-rest.d.ts.map +1 -0
  37. package/dist/render-preparation/depth/exact-playback.d.ts +40 -0
  38. package/dist/render-preparation/depth/exact-playback.d.ts.map +1 -0
  39. package/dist/render-preparation/depth/files.d.ts +55 -0
  40. package/dist/render-preparation/depth/files.d.ts.map +1 -0
  41. package/dist/render-preparation/depth/frame-decode.d.ts +20 -0
  42. package/dist/render-preparation/depth/frame-decode.d.ts.map +1 -0
  43. package/dist/render-preparation/depth/frame-preparer.d.ts +51 -0
  44. package/dist/render-preparation/depth/frame-preparer.d.ts.map +1 -0
  45. package/dist/render-preparation/depth/frame-window.d.ts +146 -0
  46. package/dist/render-preparation/depth/frame-window.d.ts.map +1 -0
  47. package/dist/render-preparation/depth/options.d.ts +37 -0
  48. package/dist/render-preparation/depth/options.d.ts.map +1 -0
  49. package/dist/render-preparation/depth/png16.d.ts +40 -0
  50. package/dist/render-preparation/depth/png16.d.ts.map +1 -0
  51. package/dist/render-preparation/depth/preview-luma-copier.d.ts +12 -0
  52. package/dist/render-preparation/depth/preview-luma-copier.d.ts.map +1 -0
  53. package/dist/render-preparation/depth/preview-luma.d.ts +48 -0
  54. package/dist/render-preparation/depth/preview-luma.d.ts.map +1 -0
  55. package/dist/render-preparation/depth/source.d.ts +123 -0
  56. package/dist/render-preparation/depth/source.d.ts.map +1 -0
  57. package/dist/render-preparation/depth/worker-protocol.d.ts +76 -0
  58. package/dist/render-preparation/depth/worker-protocol.d.ts.map +1 -0
  59. package/dist/render-preparation/playhead-motion.d.ts +67 -0
  60. package/dist/render-preparation/playhead-motion.d.ts.map +1 -0
  61. package/dist/render-preparation/prepared-render-window.d.ts +12 -0
  62. package/dist/render-preparation/prepared-render-window.d.ts.map +1 -1
  63. package/dist/renderers/depth-textures.d.ts +79 -0
  64. package/dist/renderers/depth-textures.d.ts.map +1 -0
  65. package/dist/renderers/id-mask-stroke-coverage.d.ts +3 -0
  66. package/dist/renderers/id-mask-stroke-coverage.d.ts.map +1 -0
  67. package/dist/renderers/media-renderer-core.d.ts.map +1 -1
  68. package/dist/renderers/media-renderer-scene.d.ts +14 -1
  69. package/dist/renderers/media-renderer-scene.d.ts.map +1 -1
  70. package/dist/renderers/pixi-batch-texture-bindings.d.ts +9 -0
  71. package/dist/renderers/pixi-batch-texture-bindings.d.ts.map +1 -0
  72. package/dist/renderers/pixi-depth-layer.d.ts +76 -0
  73. package/dist/renderers/pixi-depth-layer.d.ts.map +1 -0
  74. package/dist/renderers/pixi-depth-shader.d.ts +76 -0
  75. package/dist/renderers/pixi-depth-shader.d.ts.map +1 -0
  76. package/dist/renderers/pixi-focus-layer.d.ts +1 -0
  77. package/dist/renderers/pixi-focus-layer.d.ts.map +1 -1
  78. package/dist/renderers/pixi-frame-present.d.ts +1 -0
  79. package/dist/renderers/pixi-frame-present.d.ts.map +1 -1
  80. package/dist/renderers/pixi-id-mask-shader.d.ts +1 -0
  81. package/dist/renderers/pixi-id-mask-shader.d.ts.map +1 -1
  82. package/dist/renderers/pixi-interaction-layer.d.ts +1 -1
  83. package/dist/renderers/pixi-interaction-layer.d.ts.map +1 -1
  84. package/dist/renderers/pixi-interaction-presentation-layer.d.ts +1 -0
  85. package/dist/renderers/pixi-interaction-presentation-layer.d.ts.map +1 -1
  86. package/dist/renderers/pixi-mask-halo.d.ts +1 -0
  87. package/dist/renderers/pixi-mask-halo.d.ts.map +1 -1
  88. package/dist/renderers/pixi-mask-layer.d.ts +4 -0
  89. package/dist/renderers/pixi-mask-layer.d.ts.map +1 -1
  90. package/dist/renderers/pixi-media-scene.d.ts.map +1 -1
  91. package/dist/renderers/pixi-region-coverage-mask.d.ts +1 -0
  92. package/dist/renderers/pixi-region-coverage-mask.d.ts.map +1 -1
  93. package/dist/renderers/pixi-region-layer.d.ts +1 -0
  94. package/dist/renderers/pixi-region-layer.d.ts.map +1 -1
  95. package/dist/renderers/pixi-scene-layer-slot.d.ts +1 -0
  96. package/dist/renderers/pixi-scene-layer-slot.d.ts.map +1 -1
  97. package/dist/renderers/prepared-annotation-window.d.ts +1 -0
  98. package/dist/renderers/prepared-annotation-window.d.ts.map +1 -1
  99. package/dist/renderers/render-preparation-report.d.ts +23 -0
  100. package/dist/renderers/render-preparation-report.d.ts.map +1 -0
  101. package/dist/sessions/media-session-defaults.d.ts.map +1 -1
  102. package/dist/sessions/media-session-state.d.ts.map +1 -1
  103. package/dist/sessions/media-session.d.ts.map +1 -1
  104. package/dist/tracking.worker.js +64 -0
  105. package/dist/tracking.worker.js.map +1 -1
  106. package/dist/types/media-depth.d.ts +55 -0
  107. package/dist/types/media-depth.d.ts.map +1 -0
  108. package/dist/types/media-renderer.d.ts +19 -0
  109. package/dist/types/media-renderer.d.ts.map +1 -1
  110. package/dist/types/media-session.d.ts +19 -0
  111. package/dist/types/media-session.d.ts.map +1 -1
  112. package/dist/types/render-preparation.d.ts +105 -3
  113. package/dist/types/render-preparation.d.ts.map +1 -1
  114. package/dist/{video-engine-media-source-DR-x1UfK.js → video-engine-media-source-DOFsuGS4.js} +35 -29
  115. package/dist/video-engine-media-source-DOFsuGS4.js.map +1 -0
  116. package/dist/web-video-engine/analysis.js +6 -43
  117. package/dist/web-video-engine/cache-budget.d.ts +4 -7
  118. package/dist/web-video-engine/constants.d.ts +3 -4
  119. package/dist/web-video-engine/create-scrub-cursor.d.ts +1 -0
  120. package/dist/web-video-engine/decode-resolution-fynpRIAG.js +109 -0
  121. package/dist/web-video-engine/decode-scheduler.d.ts +1 -0
  122. package/dist/web-video-engine/engine-core.d.ts +4 -2
  123. package/dist/web-video-engine/engine.js +8 -6
  124. package/dist/web-video-engine/engine.worker.js +164 -66
  125. package/dist/web-video-engine/frame-cache.d.ts +9 -0
  126. package/dist/web-video-engine/frame-index.d.ts +1 -0
  127. package/dist/web-video-engine/frame-index.js +97 -0
  128. package/dist/web-video-engine/{frame-timeline-DreEwsRY.js → frame-timeline-CYgzzmpA.js} +1 -109
  129. package/dist/web-video-engine/frame-timeline-reader.d.ts +21 -0
  130. package/dist/web-video-engine/video-engine.d.ts +9 -4
  131. package/node_modules/supervision-js-core/THIRD_PARTY_NOTICES.md +132 -0
  132. package/node_modules/supervision-js-core/dist/detections/buffered-detection-timeline.d.ts.map +1 -1
  133. package/node_modules/supervision-js-core/dist/index.d.ts +7 -2
  134. package/node_modules/supervision-js-core/dist/index.d.ts.map +1 -1
  135. package/node_modules/supervision-js-core/dist/index.js +1138 -62
  136. package/node_modules/supervision-js-core/dist/index.js.map +1 -1
  137. package/node_modules/supervision-js-core/dist/interactions/annotation-editing-engine.d.ts.map +1 -1
  138. package/node_modules/supervision-js-core/dist/interactions/annotation-handles.d.ts +2 -2
  139. package/node_modules/supervision-js-core/dist/interactions/annotation-handles.d.ts.map +1 -1
  140. package/node_modules/supervision-js-core/dist/styles/annotation-renderer-presentation.d.ts.map +1 -1
  141. package/node_modules/supervision-js-core/dist/styles/annotation-renderer-registry.d.ts.map +1 -1
  142. package/node_modules/supervision-js-core/dist/types/annotation-renderer.d.ts +50 -3
  143. package/node_modules/supervision-js-core/dist/types/annotation-renderer.d.ts.map +1 -1
  144. package/node_modules/supervision-js-core/dist/types/depth-map.d.ts +203 -0
  145. package/node_modules/supervision-js-core/dist/types/depth-map.d.ts.map +1 -0
  146. package/node_modules/supervision-js-core/dist/types/editing.d.ts +4 -0
  147. package/node_modules/supervision-js-core/dist/types/editing.d.ts.map +1 -1
  148. package/node_modules/supervision-js-core/dist/types/media-rendering.d.ts +3 -0
  149. package/node_modules/supervision-js-core/dist/types/media-rendering.d.ts.map +1 -1
  150. package/node_modules/supervision-js-core/dist/utils/depth-color-mapping.d.ts +91 -0
  151. package/node_modules/supervision-js-core/dist/utils/depth-color-mapping.d.ts.map +1 -0
  152. package/node_modules/supervision-js-core/dist/utils/depth-colormap-tables.d.ts +30 -0
  153. package/node_modules/supervision-js-core/dist/utils/depth-colormap-tables.d.ts.map +1 -0
  154. package/node_modules/supervision-js-core/dist/utils/depth-colormaps.d.ts +16 -0
  155. package/node_modules/supervision-js-core/dist/utils/depth-colormaps.d.ts.map +1 -0
  156. package/node_modules/supervision-js-core/dist/utils/depth-manifest.d.ts +23 -0
  157. package/node_modules/supervision-js-core/dist/utils/depth-manifest.d.ts.map +1 -0
  158. package/node_modules/supervision-js-core/dist/utils/depth-readout.d.ts +14 -0
  159. package/node_modules/supervision-js-core/dist/utils/depth-readout.d.ts.map +1 -0
  160. package/node_modules/supervision-js-core/dist/utils/detection-frames.d.ts +21 -0
  161. package/node_modules/supervision-js-core/dist/utils/detection-frames.d.ts.map +1 -1
  162. package/node_modules/supervision-js-core/dist/utils/id-mask-frame.d.ts +3 -7
  163. package/node_modules/supervision-js-core/dist/utils/id-mask-frame.d.ts.map +1 -1
  164. package/node_modules/supervision-js-core/package.json +2 -1
  165. package/package.json +6 -1
  166. package/dist/video-engine-media-source-DR-x1UfK.js.map +0 -1
@@ -89,6 +89,19 @@ var DetectionFrameRetentionMode;
89
89
  * function and not in a smaller number here.
90
90
  */
91
91
  const PLAYHEAD_QUANTIZATION_TOLERANCE_SECONDS = 0.0005;
92
+ /**
93
+ * Validates and orders a window without copying it. The frames stay the
94
+ * caller's own objects, which is what a source wants: `DetectionFrame` and its
95
+ * `detections` are both `readonly`, nothing in the library writes to either,
96
+ * and the buffer that receives this window already keeps the objects it
97
+ * recognises and copies only the ones it does not
98
+ * (`reuseBufferedFrameSnapshots`). A source that copies first pays for every
99
+ * frame the buffer is about to discard.
100
+ */
101
+ function sortedDetectionFrames(detectionFrames) {
102
+ validateDetectionFrames(detectionFrames ?? []);
103
+ return [...(detectionFrames ?? [])].sort((left, right) => left.mediaTime - right.mediaTime);
104
+ }
92
105
  function copySortedDetectionFrames(detectionFrames) {
93
106
  validateDetectionFrames(detectionFrames ?? []);
94
107
  return (detectionFrames ?? [])
@@ -668,6 +681,9 @@ function createBufferedDetectionTimeline(options) {
668
681
  let state = createIdleDetectionBufferState();
669
682
  let destroyed = false;
670
683
  let loadId = 0;
684
+ // Preserve snapshot reuse without retaining evicted geometry.
685
+ const snapshotByIdentity = new Map();
686
+ let snapshotSourceVersion = null;
671
687
  let bufferedSourceVersion = null;
672
688
  let bufferedVersionRange = null;
673
689
  let timelineContext = {
@@ -693,6 +709,37 @@ function createBufferedDetectionTimeline(options) {
693
709
  }
694
710
  return ranges.reduce((version, range) => Math.max(version, options.source.getVersion?.(range) ?? 0), 0);
695
711
  };
712
+ const synchronizeSnapshotMemo = () => {
713
+ const sourceVersion = getSourceVersion();
714
+ if (snapshotSourceVersion === sourceVersion) {
715
+ return;
716
+ }
717
+ const frames = [...snapshotByIdentity.values()].flatMap((reference) => {
718
+ const frame = reference.deref();
719
+ return frame ? [frame] : [];
720
+ });
721
+ const changes = snapshotSourceVersion === null || frames.length === 0
722
+ ? undefined
723
+ : options.source.getChangesSince?.(snapshotSourceVersion, [
724
+ {
725
+ startTime: Math.min(...frames.map((frame) => frame.mediaTime)),
726
+ endTime: Math.max(...frames.map((frame) => frame.endTime ??
727
+ frame.mediaTime +
728
+ Number.EPSILON * Math.max(1, Math.abs(frame.mediaTime)))),
729
+ },
730
+ ]);
731
+ if (!changes || changes.requiresReload) {
732
+ snapshotByIdentity.clear();
733
+ }
734
+ else {
735
+ for (const frame of frames) {
736
+ if (changes.ranges.some((range) => detectionFrameOverlapsRange(frame, range.startTime, range.endTime))) {
737
+ snapshotByIdentity.delete(getDetectionFrameIdentity(frame));
738
+ }
739
+ }
740
+ }
741
+ snapshotSourceVersion = sourceVersion;
742
+ };
696
743
  const isLoadingEnabled = () => typeof options.enabled === "function"
697
744
  ? options.enabled()
698
745
  : options.enabled !== false;
@@ -740,14 +787,19 @@ function createBufferedDetectionTimeline(options) {
740
787
  return;
741
788
  }
742
789
  const committedSourceVersion = getSourceVersion(sourceRanges);
790
+ const sourceUnchanged = sourceVersion === committedSourceVersion;
743
791
  const loadedFrames = frameRanges.flat();
744
- buffer =
745
- bufferedSourceVersion !== null &&
746
- bufferedSourceVersion === committedSourceVersion
747
- ? reuseBufferedFrameSnapshots(buffer, loadedFrames)
748
- : copySortedDetectionFrames(loadedFrames);
792
+ synchronizeSnapshotMemo();
793
+ buffer = sourceUnchanged
794
+ ? reuseBufferedFrameSnapshots(bufferedSourceVersion === sourceVersion ? buffer : [], loadedFrames, snapshotByIdentity)
795
+ : copySortedDetectionFrames(loadedFrames);
796
+ if (sourceUnchanged) {
797
+ for (const frame of buffer) {
798
+ rememberSnapshot(snapshotByIdentity, frame);
799
+ }
800
+ }
749
801
  bufferedVersionRange = versionRange;
750
- bufferedSourceVersion = committedSourceVersion;
802
+ bufferedSourceVersion = sourceVersion;
751
803
  state = {
752
804
  bufferEndTime: endTime,
753
805
  bufferStartTime: startTime,
@@ -1003,6 +1055,8 @@ function createBufferedDetectionTimeline(options) {
1003
1055
  listeners.clear();
1004
1056
  pendingPrefetch = undefined;
1005
1057
  buffer = [];
1058
+ snapshotByIdentity.clear();
1059
+ snapshotSourceVersion = null;
1006
1060
  bufferedSourceVersion = null;
1007
1061
  bufferedVersionRange = null;
1008
1062
  state = {
@@ -1086,7 +1140,14 @@ function createBufferedDetectionTimeline(options) {
1086
1140
  bufferedVersionRange !== incrementalVersionRange) {
1087
1141
  return;
1088
1142
  }
1089
- buffer = mergeIncrementalFrames(buffer, changedFrameRanges.flat(), changedRanges);
1143
+ const changedFrames = copySortedDetectionFrames(changedFrameRanges.flat());
1144
+ synchronizeSnapshotMemo();
1145
+ buffer = mergeIncrementalFrames(buffer, changedFrames, changedRanges);
1146
+ if (getSourceVersion(sourceRanges) === changes.version) {
1147
+ for (const frame of buffer) {
1148
+ rememberSnapshot(snapshotByIdentity, frame);
1149
+ }
1150
+ }
1090
1151
  bufferedSourceVersion = changes.version;
1091
1152
  state = {
1092
1153
  ...state,
@@ -1391,18 +1452,36 @@ function mergeIncrementalFrames(currentFrames, changedFrames, changedRanges) {
1391
1452
  }
1392
1453
  return Array.from(framesByIdentity.values()).sort(compareDetectionFrames$1);
1393
1454
  }
1394
- /**
1395
- * Keeps the frame already held wherever the source returned one this buffer
1396
- * knows, and copies only what is new. Copying everything first and then
1397
- * discarding it is the same result for a great deal more work: a window rebuilt
1398
- * while a gesture moves inside it re-derives hundreds of frames it already has.
1399
- */
1400
- function reuseBufferedFrameSnapshots(currentFrames, loadedFrames) {
1401
- validateDetectionFrames(loadedFrames);
1455
+ const MAX_REMEMBERED_SNAPSHOTS = 8192;
1456
+ function rememberSnapshot(snapshots, frame) {
1457
+ const identity = getDetectionFrameIdentity(frame);
1458
+ if (snapshots.get(identity)?.deref() === frame) {
1459
+ return;
1460
+ }
1461
+ snapshots.delete(identity);
1462
+ snapshots.set(identity, new WeakRef(frame));
1463
+ while (snapshots.size > MAX_REMEMBERED_SNAPSHOTS) {
1464
+ const oldest = snapshots.keys().next().value;
1465
+ if (oldest === undefined) {
1466
+ break;
1467
+ }
1468
+ snapshots.delete(oldest);
1469
+ }
1470
+ }
1471
+ /** Reuse unchanged snapshots so moving the window copies only new frames. */
1472
+ function reuseBufferedFrameSnapshots(currentFrames, loadedFrames, snapshots) {
1402
1473
  const currentFramesByIdentity = new Map(currentFrames.map((frame) => [getDetectionFrameIdentity(frame), frame]));
1403
1474
  return loadedFrames
1404
- .map((frame) => currentFramesByIdentity.get(getDetectionFrameIdentity(frame)) ??
1405
- copyDetectionFrame(frame))
1475
+ .map((frame) => {
1476
+ const identity = getDetectionFrameIdentity(frame);
1477
+ const existing = currentFramesByIdentity.get(identity) ??
1478
+ snapshots.get(identity)?.deref();
1479
+ if (existing) {
1480
+ return existing;
1481
+ }
1482
+ validateDetectionFrames([frame]);
1483
+ return copyDetectionFrame(frame);
1484
+ })
1406
1485
  .sort(compareDetectionFrames$1);
1407
1486
  }
1408
1487
  function getDetectionFrameIdentity(frame) {
@@ -5311,9 +5390,9 @@ function pickAnnotationHandle(handles, point) {
5311
5390
  }
5312
5391
  return picked;
5313
5392
  }
5314
- function applyAnnotationHandleDrag(detection, handle, point) {
5393
+ function applyAnnotationHandleDrag(detection, handle, point, mediaDimensions) {
5315
5394
  if (detection.rect && handle.kind === AnnotationHandleKind.Resize) {
5316
- const rect = resizeRect(detection.rect, handle.id, point);
5395
+ const rect = resizeRect(detection.rect, handle.id, point, mediaDimensions);
5317
5396
  const boxRelative = detection.keypoints?.boxRelative;
5318
5397
  if (!detection.keypoints || !boxRelative?.some(Boolean)) {
5319
5398
  return { ...detection, rect };
@@ -5477,26 +5556,50 @@ function getPathHandles(points, closed, radius, hitSize) {
5477
5556
  }
5478
5557
  return handles;
5479
5558
  }
5480
- function resizeRect(rect, handle, point) {
5559
+ function resizeRect(rect, handle, point, mediaDimensions) {
5481
5560
  let left = rect.x - rect.width / 2;
5482
5561
  let right = rect.x + rect.width / 2;
5483
5562
  let top = rect.y - rect.height / 2;
5484
5563
  let bottom = rect.y + rect.height / 2;
5564
+ if (mediaDimensions) {
5565
+ left = Math.max(0, Math.min(left, mediaDimensions.width));
5566
+ right = Math.max(0, Math.min(right, mediaDimensions.width));
5567
+ top = Math.max(0, Math.min(top, mediaDimensions.height));
5568
+ bottom = Math.max(0, Math.min(bottom, mediaDimensions.height));
5569
+ }
5485
5570
  if (handle.includes("w"))
5486
- left = Math.min(point.x, right - 5);
5571
+ left = resizeEdge(point.x, right, -1, mediaDimensions?.width);
5487
5572
  if (handle.includes("e"))
5488
- right = Math.max(point.x, left + 5);
5573
+ right = resizeEdge(point.x, left, 1, mediaDimensions?.width);
5489
5574
  if (handle.includes("n"))
5490
- top = Math.min(point.y, bottom - 5);
5575
+ top = resizeEdge(point.y, bottom, -1, mediaDimensions?.height);
5491
5576
  if (handle.includes("s"))
5492
- bottom = Math.max(point.y, top + 5);
5577
+ bottom = resizeEdge(point.y, top, 1, mediaDimensions?.height);
5493
5578
  return {
5494
5579
  x: (left + right) / 2,
5495
5580
  y: (top + bottom) / 2,
5496
- width: right - left,
5497
- height: bottom - top,
5581
+ width: Math.abs(right - left),
5582
+ height: Math.abs(bottom - top),
5498
5583
  };
5499
5584
  }
5585
+ function resizeEdge(point, anchor, initialDirection, extent) {
5586
+ let direction = point === anchor ? initialDirection : point < anchor ? -1 : 1;
5587
+ let minimum = 5;
5588
+ if (extent !== undefined) {
5589
+ const available = direction === 1 ? extent - anchor : anchor;
5590
+ const opposite = direction === 1 ? anchor : extent - anchor;
5591
+ // Crossing cannot push the minimum-size box past the media edge. Use the
5592
+ // other side of the fixed anchor when it has more room.
5593
+ if (available < Math.min(minimum, extent) && opposite > available) {
5594
+ direction *= -1;
5595
+ }
5596
+ minimum = Math.min(minimum, direction === 1 ? extent - anchor : anchor);
5597
+ }
5598
+ const edge = direction === 1
5599
+ ? Math.max(point, anchor + minimum)
5600
+ : Math.min(point, anchor - minimum);
5601
+ return extent === undefined ? edge : Math.max(0, Math.min(edge, extent));
5602
+ }
5500
5603
  function replacePathPoint(detection, key, index, point) {
5501
5604
  const geometry = detection[key];
5502
5605
  const points = [...geometry.points];
@@ -5528,6 +5631,8 @@ function createAnnotationEditingEngine(options = {}) {
5528
5631
  return {
5529
5632
  getState: () => state,
5530
5633
  setCreationTool(nextTool) {
5634
+ if (nextTool === tool)
5635
+ return;
5531
5636
  if (gesture)
5532
5637
  cancel();
5533
5638
  tool = nextTool;
@@ -5551,12 +5656,10 @@ function createAnnotationEditingEngine(options = {}) {
5551
5656
  setPreview(resolveBoxPreview(gesture));
5552
5657
  break;
5553
5658
  case "move": {
5554
- const dx = input.point.x - gesture.start.point.x;
5555
- const dy = input.point.y - gesture.start.point.y;
5556
5659
  const moved = gesture.moved || exceedsMoveThreshold(gesture.start, input);
5557
5660
  gesture = { ...gesture, current: input, moved };
5558
5661
  if (moved) {
5559
- const preview = offsetDetection(gesture.detection, dx, dy);
5662
+ const { preview, dx, dy } = resolveMovePreview(gesture, input);
5560
5663
  setPreview(preview);
5561
5664
  if (gesture.detection.id !== undefined) {
5562
5665
  options.onFastTranslate?.(gesture.detection.id, dx, dy);
@@ -5574,7 +5677,7 @@ function createAnnotationEditingEngine(options = {}) {
5574
5677
  const moved = gesture.moved || exceedsMoveThreshold(gesture.start, input);
5575
5678
  gesture = { ...gesture, current: input, moved };
5576
5679
  if (moved) {
5577
- setPreview(applyAnnotationHandleDrag(gesture.detection, gesture.handle, input.point));
5680
+ setPreview(applyAnnotationHandleDrag(gesture.detection, gesture.handle, input.point, input.mediaDimensions ?? gesture.start.mediaDimensions));
5578
5681
  }
5579
5682
  break;
5580
5683
  }
@@ -5611,11 +5714,11 @@ function createAnnotationEditingEngine(options = {}) {
5611
5714
  rect.width < 1 ||
5612
5715
  rect.height < 1 ||
5613
5716
  (duration < CLICK_CANCEL_MS && diagonal <= CLICK_CANCEL_DIAGONAL)) {
5614
- cancel();
5717
+ rejectCreation();
5615
5718
  return;
5616
5719
  }
5617
5720
  if (tool?.shouldCommit?.(rect) === false) {
5618
- cancel();
5721
+ rejectCreation();
5619
5722
  return;
5620
5723
  }
5621
5724
  commit(preview, null);
@@ -5624,7 +5727,7 @@ function createAnnotationEditingEngine(options = {}) {
5624
5727
  if (active.kind === "freehand") {
5625
5728
  const points = [...active.points, input.point];
5626
5729
  if (points.length < 2 || tool?.shouldCommit?.(points) === false) {
5627
- cancel();
5730
+ rejectCreation();
5628
5731
  return;
5629
5732
  }
5630
5733
  commit(tool.createDetection(points), null);
@@ -5635,7 +5738,7 @@ function createAnnotationEditingEngine(options = {}) {
5635
5738
  setState(idleState());
5636
5739
  return;
5637
5740
  }
5638
- const preview = offsetDetection(active.detection, input.point.x - active.start.point.x, input.point.y - active.start.point.y);
5741
+ const { preview } = resolveMovePreview(active, input);
5639
5742
  commit(preview, active.detection);
5640
5743
  return;
5641
5744
  }
@@ -5643,7 +5746,7 @@ function createAnnotationEditingEngine(options = {}) {
5643
5746
  setState(idleState());
5644
5747
  return;
5645
5748
  }
5646
- const preview = applyAnnotationHandleDrag(active.detection, active.handle, input.point);
5749
+ const preview = applyAnnotationHandleDrag(active.detection, active.handle, input.point, input.mediaDimensions ?? active.start.mediaDimensions);
5647
5750
  commit(preview, active.detection);
5648
5751
  },
5649
5752
  keyDown(key) {
@@ -5775,10 +5878,13 @@ function createAnnotationEditingEngine(options = {}) {
5775
5878
  });
5776
5879
  }
5777
5880
  function resolveBoxPreview(active) {
5778
- const left = Math.min(active.start.point.x, active.current.point.x);
5779
- const right = Math.max(active.start.point.x, active.current.point.x);
5780
- const top = Math.min(active.start.point.y, active.current.point.y);
5781
- const bottom = Math.max(active.start.point.y, active.current.point.y);
5881
+ const dimensions = active.current.mediaDimensions ?? active.start.mediaDimensions;
5882
+ const start = boundPoint(active.start.point, dimensions);
5883
+ const current = boundPoint(active.current.point, dimensions);
5884
+ const left = Math.min(start.x, current.x);
5885
+ const right = Math.max(start.x, current.x);
5886
+ const top = Math.min(start.y, current.y);
5887
+ const bottom = Math.max(start.y, current.y);
5782
5888
  const rect = {
5783
5889
  x: (left + right) / 2,
5784
5890
  y: (top + bottom) / 2,
@@ -5787,6 +5893,35 @@ function createAnnotationEditingEngine(options = {}) {
5787
5893
  };
5788
5894
  return tool.createDetection(rect);
5789
5895
  }
5896
+ function resolveMovePreview(active, input) {
5897
+ let dx = input.point.x - active.start.point.x;
5898
+ let dy = input.point.y - active.start.point.y;
5899
+ let rect = active.detection.rect;
5900
+ const dimensions = input.mediaDimensions ?? active.start.mediaDimensions;
5901
+ if (rect && dimensions) {
5902
+ const width = Math.min(rect.width, dimensions.width);
5903
+ const height = Math.min(rect.height, dimensions.height);
5904
+ const x = Math.max(width / 2, Math.min(rect.x + dx, dimensions.width - width / 2));
5905
+ const y = Math.max(height / 2, Math.min(rect.y + dy, dimensions.height - height / 2));
5906
+ dx = x - rect.x;
5907
+ dy = y - rect.y;
5908
+ rect = { ...rect, x, y, width, height };
5909
+ }
5910
+ const preview = offsetDetection(active.detection, dx, dy);
5911
+ return {
5912
+ preview: rect && dimensions ? { ...preview, rect } : preview,
5913
+ dx,
5914
+ dy,
5915
+ };
5916
+ }
5917
+ function boundPoint(point, dimensions) {
5918
+ return dimensions
5919
+ ? {
5920
+ x: Math.max(0, Math.min(point.x, dimensions.width)),
5921
+ y: Math.max(0, Math.min(point.y, dimensions.height)),
5922
+ }
5923
+ : point;
5924
+ }
5790
5925
  function resolvePathPreview(points) {
5791
5926
  return tool.createDetection(points);
5792
5927
  }
@@ -5828,6 +5963,11 @@ function createAnnotationEditingEngine(options = {}) {
5828
5963
  preview,
5829
5964
  });
5830
5965
  }
5966
+ function rejectCreation() {
5967
+ const onRejected = tool?.onRejected;
5968
+ cancel();
5969
+ onRejected?.();
5970
+ }
5831
5971
  function cancel() {
5832
5972
  const pointerId = gesture && "start" in gesture
5833
5973
  ? gesture.start.pointerId
@@ -7268,6 +7408,7 @@ function resolveDefaultClassColor(detection, getClassColor) {
7268
7408
  const annotationRendererKinds = [
7269
7409
  "box",
7270
7410
  "box-corners",
7411
+ "depth",
7271
7412
  "ellipse",
7272
7413
  "heatmap",
7273
7414
  "keypoints",
@@ -7321,6 +7462,11 @@ const RegionRendererComposeMode = {
7321
7462
  const annotationRenderers = {
7322
7463
  box: (options) => createAnnotationRenderer("box", options),
7323
7464
  boxCorners: (options) => createAnnotationRenderer("box-corners", options),
7465
+ depth: (options) => ({
7466
+ ...options,
7467
+ id: options?.id ?? "depth",
7468
+ kind: "depth",
7469
+ }),
7324
7470
  ellipse: (options) => createAnnotationRenderer("ellipse", options),
7325
7471
  heatmap: (options) => ({
7326
7472
  ...options,
@@ -7356,6 +7502,7 @@ const annotationRendererRegistry = {
7356
7502
  createCanonicalStyle: createDefaultBoxCornerStyle,
7357
7503
  styleField: "boxCornerStyle",
7358
7504
  },
7505
+ depth: { cardinality: "multiple" },
7359
7506
  ellipse: {
7360
7507
  cardinality: "singleton",
7361
7508
  createCanonicalStyle: createDefaultEllipseStyle,
@@ -7420,6 +7567,241 @@ function resolveAnnotationRendererStyleFields(kinds) {
7420
7567
  });
7421
7568
  }
7422
7569
 
7570
+ /**
7571
+ * What the stored values of a depth map measure.
7572
+ *
7573
+ * Every kind stores 0 where there is no depth.
7574
+ */
7575
+ const DepthMapKind = {
7576
+ /** Stereo disparity in pixels of the map. Larger is nearer. */
7577
+ DisparityPx: "disparity_px",
7578
+ /** Metric depth along the optical axis in metres. Smaller is nearer. */
7579
+ DepthM: "depth_m",
7580
+ /**
7581
+ * Unitless inverse depth up to an unknown scale and shift, as monocular
7582
+ * models produce it. Larger is nearer; it has no metric depth.
7583
+ */
7584
+ RelativeInverse: "relative_inverse",
7585
+ };
7586
+ /**
7587
+ * The quantity a depth renderer colours.
7588
+ *
7589
+ * Disparity is inverse depth, so it spends colour on near detail the way
7590
+ * stereo measures it. Either way the nearest end of the range is the warm or
7591
+ * bright end of the colour table.
7592
+ */
7593
+ const DepthQuantity = {
7594
+ Disparity: "disparity",
7595
+ Depth: "depth",
7596
+ };
7597
+ const DepthColormap = {
7598
+ Turbo: "turbo",
7599
+ Viridis: "viridis",
7600
+ Cividis: "cividis",
7601
+ Inferno: "inferno",
7602
+ Magma: "magma",
7603
+ Grayscale: "grayscale",
7604
+ };
7605
+ /** How a depth map is sampled where one map pixel does not cover one media pixel. */
7606
+ const DepthSampling = {
7607
+ /** Nearest when the map is at least media size, edge-aware otherwise. */
7608
+ Auto: "auto",
7609
+ Nearest: "nearest",
7610
+ /**
7611
+ * Bilinear over valid neighbours only, falling back to the nearest one
7612
+ * across a depth edge, so objects never bleed into the background.
7613
+ */
7614
+ EdgeAware: "edge-aware",
7615
+ };
7616
+ /**
7617
+ * The luma range a depth preview video's codes are written in.
7618
+ *
7619
+ * TV range is what browsers' hardware decoders return as written; a decoder
7620
+ * may squeeze full range into TV range or move codes converting it to RGB.
7621
+ */
7622
+ const DepthPreviewLevels = {
7623
+ /** Every code from 0 to 255; the top code is 255. */
7624
+ Full: "full",
7625
+ /** Limited range: black is 16 and the top code is 235. */
7626
+ Tv: "tv",
7627
+ };
7628
+
7629
+ // Generated by tools/depth-colormaps/generate-depth-colormap-tables.py
7630
+ // from matplotlib 3.11.2. Do not edit by hand.
7631
+ //
7632
+ // Each table is 256 sRGB entries as 6-digit hex, darkest or coldest
7633
+ // first, in the order the colour coordinate t runs from 0 to 1.
7634
+ /*!
7635
+ * Turbo, Anton Mikhailov's published table.
7636
+ * Copyright 2019 Google LLC.
7637
+ * SPDX-License-Identifier: Apache-2.0
7638
+ * https://gist.github.com/mikhailov-work/ee72ba4191942acecc03fe6da94fc73f
7639
+ */
7640
+ const turboTable = [
7641
+ "30123b32154333184a341b51351e5836215f37246638276d392a733a2d793b2f803c32863d358b3e38913f3b973f3e9c",
7642
+ "4040a24143a74146ac4249b1424bb5434eba4451bf4454c34456c74559cb455ccf455ed34661d64664da4666dd4669e0",
7643
+ "466be3476ee64771e94773eb4776ee4778f0477bf2467df44680f64682f84685fa4687fb458afc458cfd448ffe4391fe",
7644
+ "4294ff4196ff4099ff3e9bfe3d9efe3ba0fd3aa3fc38a5fb37a8fa35abf833adf731aff52fb2f42eb4f22cb7f02ab9ee",
7645
+ "28bceb27bee925c0e723c3e422c5e220c7df1fc9dd1ecbda1ccdd81bd0d51ad2d21ad4d019d5cd18d7ca18d9c818dbc5",
7646
+ "18ddc218dec018e0bd19e2bb19e3b91ae4b61ce6b41de7b21fe9af20eaac22ebaa25eca727eea42aefa12cf09e2ff19b",
7647
+ "32f29835f39438f4913cf58e3ff68a43f78746f8844af8804ef97d52fa7a55fa7659fb735dfc6f61fc6c65fd6969fd66",
7648
+ "6dfe6271fe5f75fe5c79fe597dff5680ff5384ff5188ff4e8bff4b8fff4992ff4796fe4499fe429cfe409ffd3fa1fd3d",
7649
+ "a4fc3ca7fc3aa9fb39acfb38affa37b1f936b4f836b7f735b9f635bcf534bef434c1f334c3f134c6f034c8ef34cbed34",
7650
+ "cdec34d0ea34d2e935d4e735d7e535d9e436dbe236dde037dfdf37e1dd37e3db38e5d938e7d739e9d539ebd339ecd13a",
7651
+ "eecf3aefcd3af1cb3af2c93af4c73af5c53af6c33af7c13af8be39f9bc39faba39fbb838fbb637fcb336fcb136fdae35",
7652
+ "fdac34fea933fea732fea431fea130fe9e2ffe9b2dfe992cfe962bfe932afe9029fd8d27fd8a26fc8725fc8423fb8122",
7653
+ "fb7e21fa7b1ff9781ef9751df8721cf76f1af66c19f56918f46617f36315f26014f15d13f05b12ef5811ed5510ec530f",
7654
+ "eb500eea4e0de84b0ce7490ce5470be4450ae2430ae14109df3f08dd3d08dc3b07da3907d83706d63506d43305d23105",
7655
+ "d02f05ce2d04cc2b04ca2a04c82803c52603c32503c12302be2102bc2002b91e02b71d02b41b01b21a01af1801ac1701",
7656
+ "a91601a71401a41301a112019e10019b0f01980e01950d01920b018e0a018b09028808028507028106027e05027a0403",
7657
+ ].join("");
7658
+ /*!
7659
+ * Viridis, by Stéfan van der Walt, Nathaniel Smith and Eric Firing.
7660
+ * Released under CC0: https://github.com/BIDS/colormap
7661
+ */
7662
+ const viridisTable = [
7663
+ "44015444025645045745055946075a46085c460a5d460b5e470d60470e61471063471164471365481467481668481769",
7664
+ "48186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a",
7665
+ "472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f85",
7666
+ "4240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b",
7667
+ "3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d",
7668
+ "33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e",
7669
+ "2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e",
7670
+ "26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d",
7671
+ "21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f88",
7672
+ "1fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad81",
7673
+ "28ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc74",
7674
+ "3fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc863",
7675
+ "5ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d",
7676
+ "84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32",
7677
+ "addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21a",
7678
+ "d8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725",
7679
+ ].join("");
7680
+ /*!
7681
+ * Cividis, Nuñez, Anderton and Renslow, PLOS ONE 13(7) e0199239 (2018),
7682
+ * from https://github.com/pnnl/cmaputil as shipped by matplotlib.
7683
+ * Copyright (c) 2017, Battelle Memorial Institute. Redistributed under
7684
+ * its BSD-style licence, which asks for this notice to be kept.
7685
+ */
7686
+ const cividisTable = [
7687
+ "00224e00234f00245100255300255400265600275800285900285b00295d002a5f002a61002b62002c64002c66002d68",
7688
+ "002e6a002e6c002f6d00306f0030700031700031710132710533710833700c34700f357012357014367016377018376f",
7689
+ "1a386f1c396f1e3a6f203a6f213b6e233c6e243c6e263d6e273e6e293f6e2a3f6d2b406d2d416d2e416d2f426d31436d",
7690
+ "32436d33446d34456c35456c36466c38476c39486c3a486c3b496c3c4a6c3d4a6c3e4b6c3f4c6c404c6c414d6c424e6c",
7691
+ "434e6c444f6c45506c46516c47516c48526c49536c4a536c4b546c4c556c4d556c4e566c4f576c50576c51586d52596d",
7692
+ "535a6d545a6d555b6d555c6d565c6d575d6d585e6d595e6e5a5f6e5b606e5c616e5d616e5e626e5e636f5f636f60646f",
7693
+ "61656f62656f636670646770656870656870666970676a71686a71696b716a6c716b6d726c6d726c6e726d6f726e6f73",
7694
+ "6f70737071737172747272747273747374757474757575757676767777767777777878777979777a7a787b7a787c7b78",
7695
+ "7d7c787e7c787e7d787f7e78807f78817f788280798381798482798582798683798784788885788985788a86788b8778",
7696
+ "8c88788d88788e89788f8a78908b78918b78928c78928d78938e78948e77958f779690779791779892779992779a9376",
7697
+ "9b94769c95769d95769e96769f9775a09875a19975a29975a39a74a49b74a59c74a69c74a79d73a89e73a99f73aaa073",
7698
+ "aba072aca172ada272aea371afa471b0a571b1a570b3a670b4a76fb5a86fb6a96fb7a96eb8aa6eb9ab6dbaac6dbbad6d",
7699
+ "bcae6cbdae6cbeaf6bbfb06bc0b16ac1b26ac2b369c3b369c4b468c5b568c6b667c7b767c8b866c9b965cbb965ccba64",
7700
+ "cdbb63cebc63cfbd62d0be62d1bf61d2c060d3c05fd4c15fd5c25ed6c35dd7c45cd9c55cdac65bdbc75adcc859ddc858",
7701
+ "dec958dfca57e0cb56e1cc55e2cd54e4ce53e5cf52e6d051e7d150e8d24fe9d34eead34cebd44bedd54aeed649efd748",
7702
+ "f0d846f1d945f2da44f3db42f5dc41f6dd3ff7de3ef8df3cf9e03afbe138fce236fde334fee434fee535fee636fee838",
7703
+ ].join("");
7704
+ /*!
7705
+ * Inferno, by Stéfan van der Walt and Nathaniel Smith.
7706
+ * Released under CC0: https://github.com/BIDS/colormap
7707
+ */
7708
+ const infernoTable = [
7709
+ "00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a0722",
7710
+ "0b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48",
7711
+ "210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b0964",
7712
+ "3d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d",
7713
+ "57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e",
7714
+ "71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a",
7715
+ "8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62",
7716
+ "a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655",
7717
+ "bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545",
7718
+ "d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933",
7719
+ "e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711f",
7720
+ "f1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0a",
7721
+ "f98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0f",
7722
+ "fcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932",
7723
+ "f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865",
7724
+ "f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4",
7725
+ ].join("");
7726
+ /*!
7727
+ * Magma, by Stéfan van der Walt and Nathaniel Smith.
7728
+ * Released under CC0: https://github.com/BIDS/colormap
7729
+ */
7730
+ const magmaTable = [
7731
+ "00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e090720",
7732
+ "0a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c1044",
7733
+ "1d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f1163311165331067341069",
7734
+ "36106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b",
7735
+ "51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c81",
7736
+ "6a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e2482802582812581",
7737
+ "8326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f",
7738
+ "9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367a",
7739
+ "b73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070",
7740
+ "d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064",
7741
+ "e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695c",
7742
+ "f56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761",
7743
+ "fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571",
7744
+ "fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287",
7745
+ "fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1",
7746
+ "fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf",
7747
+ ].join("");
7748
+
7749
+ const DEPTH_COLORMAP_ENTRIES = 256;
7750
+ const colormapTables = {
7751
+ cividis: cividisTable,
7752
+ inferno: infernoTable,
7753
+ magma: magmaTable,
7754
+ turbo: turboTable,
7755
+ viridis: viridisTable,
7756
+ };
7757
+ const depthColormaps = new Set(Object.values(DepthColormap));
7758
+ function isDepthColormap(value) {
7759
+ return typeof value === "string" && depthColormaps.has(value);
7760
+ }
7761
+ /**
7762
+ * The colour table as 256 RGBA8 entries with opaque alpha, far or low values
7763
+ * first. Entry `i` is the colour of `t = i / 255`.
7764
+ */
7765
+ function createDepthColormapLut(name) {
7766
+ if (!isDepthColormap(name)) {
7767
+ throw new RangeError(`Unknown depth colormap "${String(name)}".`);
7768
+ }
7769
+ const lut = new Uint8Array(DEPTH_COLORMAP_ENTRIES * 4);
7770
+ for (let index = 0; index < DEPTH_COLORMAP_ENTRIES; index += 1) {
7771
+ const offset = index * 4;
7772
+ if (name === DepthColormap.Grayscale) {
7773
+ lut[offset] = index;
7774
+ lut[offset + 1] = index;
7775
+ lut[offset + 2] = index;
7776
+ }
7777
+ else {
7778
+ const table = colormapTables[name];
7779
+ const hex = index * 6;
7780
+ lut[offset] = Number.parseInt(table.slice(hex, hex + 2), 16);
7781
+ lut[offset + 1] = Number.parseInt(table.slice(hex + 2, hex + 4), 16);
7782
+ lut[offset + 2] = Number.parseInt(table.slice(hex + 4, hex + 6), 16);
7783
+ }
7784
+ lut[offset + 3] = 255;
7785
+ }
7786
+ return lut;
7787
+ }
7788
+ /**
7789
+ * CSS colours of a depth colormap at `stops` evenly spaced points, far end
7790
+ * first and near end last, read from the same table the depth renderer draws
7791
+ * with. A legend that matches the picture is
7792
+ * `linear-gradient(to right, ${colors.join(", ")})`.
7793
+ */
7794
+ function depthColormapColors(colormap, stops = 16) {
7795
+ if (!Number.isInteger(stops) || stops < 2 || stops > DEPTH_COLORMAP_ENTRIES) {
7796
+ throw new RangeError(`Depth colormap stops must be an integer from 2 to ${DEPTH_COLORMAP_ENTRIES}, got ${stops}.`);
7797
+ }
7798
+ const lut = createDepthColormapLut(colormap);
7799
+ return Array.from({ length: stops }, (_, stop) => {
7800
+ const offset = Math.round((stop * (DEPTH_COLORMAP_ENTRIES - 1)) / (stops - 1)) * 4;
7801
+ return `#${Array.from(lut.subarray(offset, offset + 3), (channel) => channel.toString(16).padStart(2, "0")).join("")}`;
7802
+ });
7803
+ }
7804
+
7423
7805
  /**
7424
7806
  * Resolves built-in renderer descriptors into the existing specialized style
7425
7807
  * fields. The browser backend deliberately keeps ownership of its box, mask,
@@ -7451,6 +7833,9 @@ function resolveAnnotationRendererPresentation(presentation) {
7451
7833
  if (renderer.kind === "heatmap") {
7452
7834
  validateHeatmapRenderer(renderer);
7453
7835
  }
7836
+ if (renderer.kind === "depth") {
7837
+ validateDepthRenderer(renderer);
7838
+ }
7454
7839
  if (rendererIds.has(renderer.id)) {
7455
7840
  throw new RangeError(`MediaRendererPresentation.renderers contains duplicate renderer id "${renderer.id}".`);
7456
7841
  }
@@ -7493,6 +7878,32 @@ function validateHeatmapRenderer(renderer) {
7493
7878
  throw new RangeError(`Invalid heatmap renderer settings for "${renderer.id}".`);
7494
7879
  }
7495
7880
  }
7881
+ const depthQuantities = new Set(Object.values(DepthQuantity));
7882
+ const depthSamplings = new Set(Object.values(DepthSampling));
7883
+ function validateDepthRenderer(renderer) {
7884
+ const { colormap, noDepthColor, opacity, quantity, range, sampling, wipe } = renderer;
7885
+ if ((colormap !== undefined && !isDepthColormap(colormap)) ||
7886
+ (quantity !== undefined && !depthQuantities.has(quantity)) ||
7887
+ (sampling !== undefined && !depthSamplings.has(sampling)) ||
7888
+ (range !== undefined &&
7889
+ range !== "clip" &&
7890
+ range !== "auto" &&
7891
+ (typeof range !== "object" ||
7892
+ range === null ||
7893
+ !Number.isFinite(range.min) ||
7894
+ !Number.isFinite(range.max) ||
7895
+ range.min >= range.max)) ||
7896
+ (opacity !== undefined && !Number.isFinite(opacity)) ||
7897
+ (wipe !== undefined &&
7898
+ !(Number.isFinite(wipe) && wipe >= 0 && wipe <= 1)) ||
7899
+ (noDepthColor !== undefined &&
7900
+ noDepthColor !== null &&
7901
+ !(Number.isInteger(noDepthColor) &&
7902
+ noDepthColor >= 0 &&
7903
+ noDepthColor <= 0xffffff))) {
7904
+ throw new RangeError(`Invalid depth renderer settings for "${renderer.id}".`);
7905
+ }
7906
+ }
7496
7907
  function isStyleBackedAnnotationRenderer(renderer) {
7497
7908
  return isStyleBackedAnnotationRendererKind(renderer.kind);
7498
7909
  }
@@ -7948,8 +8359,10 @@ function createIdMaskFrame(instructions, options = {}) {
7948
8359
  if (instructions.length === 0) {
7949
8360
  return undefined;
7950
8361
  }
7951
- const maskWidth = Math.max(...instructions.map(({ mask }) => mask.width));
7952
- const maskHeight = Math.max(...instructions.map(({ mask }) => mask.height));
8362
+ /* Pixel-grid dimensions use integer parts throughout allocation and RLE
8363
+ traversal. */
8364
+ const maskWidth = Math.floor(Math.max(...instructions.map(({ mask }) => mask.width)));
8365
+ const maskHeight = Math.floor(Math.max(...instructions.map(({ mask }) => mask.height)));
7953
8366
  const width = resolveRasterWidth(maskWidth, options.maxWidth);
7954
8367
  const height = width === maskWidth
7955
8368
  ? maskHeight
@@ -8001,8 +8414,8 @@ function createIdMaskFrame(instructions, options = {}) {
8001
8414
  */
8002
8415
  function writeMaskRuns(data, frameWidth, mask, detectionMaskId) {
8003
8416
  const counts = decodeCompressedRleCounts(mask.counts);
8004
- const maskWidth = mask.width;
8005
- const maskHeight = mask.height;
8417
+ const maskWidth = Math.floor(mask.width);
8418
+ const maskHeight = Math.floor(mask.height);
8006
8419
  let maskOffset = 0;
8007
8420
  for (let index = 0; index < counts.length; index += 1) {
8008
8421
  const runLength = counts[index] ?? 0;
@@ -8036,9 +8449,10 @@ function writeMaskRuns(data, frameWidth, mask, detectionMaskId) {
8036
8449
  */
8037
8450
  function writeScaledMaskRuns(data, axes, mask, detectionMaskId) {
8038
8451
  const counts = decodeCompressedRleCounts(mask.counts);
8039
- const maskWidth = mask.width;
8040
- const maskHeight = mask.height;
8452
+ const maskWidth = Math.floor(mask.width);
8453
+ const maskHeight = Math.floor(mask.height);
8041
8454
  let maskOffset = 0;
8455
+ const stride = axes.stride;
8042
8456
  for (let index = 0; index < counts.length; index += 1) {
8043
8457
  const runLength = counts[index] ?? 0;
8044
8458
  if (index % 2 === 0 || runLength <= 0) {
@@ -8047,17 +8461,30 @@ function writeScaledMaskRuns(data, axes, mask, detectionMaskId) {
8047
8461
  }
8048
8462
  let x = Math.floor(maskOffset / maskHeight);
8049
8463
  let y = maskOffset - x * maskHeight;
8050
- let column = axes.columns[x];
8051
- for (let step = 0; step < runLength; step += 1) {
8052
- if (x >= maskWidth) {
8053
- break;
8054
- }
8055
- data[axes.rows[y] + column] = detectionMaskId;
8056
- y += 1;
8464
+ let remaining = runLength;
8465
+ /* A run walks down one column and wraps into the next, so it splits into
8466
+ column-sized segments. Within a segment the destination offset only ever
8467
+ steps by the row pitch or stays put: createMaskAxisMap builds
8468
+ `rows[i] = min(height - 1, floor(i * scale)) * width` with scale <= 1, so
8469
+ consecutive entries differ by exactly 0 or exactly `width`. Walking the
8470
+ destination directly therefore touches the same bytes the per-pixel loop
8471
+ touched, and drops the bounds test, the wrap test and one typed-array
8472
+ load from every source pixel. Where the scale collapses several source
8473
+ rows onto one destination row, this writes that byte once instead of
8474
+ once per source row. */
8475
+ while (remaining > 0 && x < maskWidth) {
8476
+ const span = Math.min(remaining, maskHeight - y);
8477
+ const column = axes.columns[x];
8478
+ const first = axes.rows[y];
8479
+ const last = axes.rows[y + span - 1];
8480
+ for (let offset = first; offset <= last; offset += stride) {
8481
+ data[offset + column] = detectionMaskId;
8482
+ }
8483
+ remaining -= span;
8484
+ y += span;
8057
8485
  if (y === maskHeight) {
8058
8486
  y = 0;
8059
8487
  x += 1;
8060
- column = axes.columns[x];
8061
8488
  }
8062
8489
  }
8063
8490
  maskOffset += runLength;
@@ -8069,22 +8496,19 @@ function resolveRasterWidth(maskWidth, maxWidth) {
8069
8496
  : maskWidth;
8070
8497
  }
8071
8498
  /**
8072
- * A stroke is measured in texels of the raster it is drawn on, so a coarser
8073
- * raster measures it in coarser texels. A stroke of a texel or more keeps at
8074
- * least one, the thinnest line the shader can draw; a narrower one keeps its
8075
- * own width, which the shader draws as an inner boundary at any scale. The
8076
- * ceiling is the widest neighbourhood the shaders scan, so a wider stroke would
8077
- * be drawn at the ceiling anyway and every layer drawing the same annotation
8078
- * has to arrive at the same width.
8499
+ * Converts a source-grid stroke width into raster texels. Fractional widths
8500
+ * let coverage shaders draw a border within a texel. The ceiling bounds the
8501
+ * neighbourhood the shaders scan.
8079
8502
  */
8080
8503
  function resolveIdMaskStrokeTexels(strokeWidth, maskWidth, rasterWidth) {
8081
8504
  const scale = maskWidth > 0 ? rasterWidth / maskWidth : 1;
8082
- return Math.min(Math.max(strokeWidth * scale, Math.min(strokeWidth, 1)), MAX_ID_MASK_STROKE_WIDTH);
8505
+ return Math.min(strokeWidth * scale, MAX_ID_MASK_STROKE_WIDTH);
8083
8506
  }
8084
8507
  function createScaledMaskAxes(frame) {
8085
8508
  return {
8086
8509
  columns: createMaskAxisMap(frame.maskWidth, frame.width, 1),
8087
8510
  rows: createMaskAxisMap(frame.maskHeight, frame.height, frame.width),
8511
+ stride: frame.width,
8088
8512
  };
8089
8513
  }
8090
8514
  /** Rows hold their destination offset, so writing a run is two lookups. */
@@ -8313,6 +8737,658 @@ function includes(values, value) {
8313
8737
  : values.has(value);
8314
8738
  }
8315
8739
 
8740
+ const DEPTH_MANIFEST_SCHEMA = "supervision.depth-manifest";
8741
+ const PREVIEW_TOP_CODES = {
8742
+ full: 255,
8743
+ tv: 235,
8744
+ };
8745
+ /**
8746
+ * TV black, 16, is written for no depth, and a decoder that converts to RGB
8747
+ * returns every code below it as black too, so the reserved band must cover it.
8748
+ */
8749
+ const PREVIEW_MIN_RESERVED_CODES = { full: 0, tv: 16 };
8750
+ const depthPreviewLevels = new Set(Object.values(DepthPreviewLevels));
8751
+ const depthMapKinds = new Set(Object.values(DepthMapKind));
8752
+ const FRAME_INDEX_TOKEN = /\{index(?::0(\d{1,2}))?\}/g;
8753
+ /**
8754
+ * Reads the snake_case `depth.json` a producer writes into a
8755
+ * {@link DepthManifest}, and rejects anything a renderer could not honour.
8756
+ *
8757
+ * Messages name the offending wire field, such as
8758
+ * `depth.json: storage.scale must be a positive number`. Unknown fields are
8759
+ * ignored so newer producers stay readable.
8760
+ */
8761
+ function parseDepthManifest(json) {
8762
+ const root = readObject(json, "the manifest");
8763
+ if (root.schema !== DEPTH_MANIFEST_SCHEMA) {
8764
+ fail(`schema must be "${DEPTH_MANIFEST_SCHEMA}"`);
8765
+ }
8766
+ if (root.version !== 1) {
8767
+ fail(`version ${String(root.version)} is not supported; expected 1`);
8768
+ }
8769
+ const kind = root.kind;
8770
+ if (typeof kind !== "string" || !depthMapKinds.has(kind)) {
8771
+ fail(`kind must be one of ${[...depthMapKinds].join(", ")}`);
8772
+ }
8773
+ const depthKind = kind;
8774
+ const width = readPositiveInteger(root.width, "width");
8775
+ const height = readPositiveInteger(root.height, "height");
8776
+ const view = readOptionalString(root.view, "view");
8777
+ const storage = readObject(root.storage, "storage");
8778
+ if (storage.format !== "png16") {
8779
+ fail('storage.format must be "png16"');
8780
+ }
8781
+ const scale = readPositiveNumber(storage.scale, "storage.scale");
8782
+ if (storage.no_depth !== 0) {
8783
+ fail("storage.no_depth must be 0");
8784
+ }
8785
+ const camera = root.camera === undefined || root.camera === null
8786
+ ? undefined
8787
+ : readCamera(root.camera);
8788
+ const displayRange = readDisplayRange(root, depthKind);
8789
+ const hasImage = root.image !== undefined && root.image !== null;
8790
+ const hasFrames = root.frames !== undefined && root.frames !== null;
8791
+ if (hasImage === hasFrames) {
8792
+ fail("exactly one of image or frames must be present");
8793
+ }
8794
+ const image = hasImage ? readImage(root.image) : undefined;
8795
+ const frames = hasFrames ? readFrames(root.frames) : undefined;
8796
+ let preview;
8797
+ if (root.preview !== undefined && root.preview !== null) {
8798
+ if (!frames) {
8799
+ fail("preview is only valid next to frames");
8800
+ }
8801
+ if (depthKind !== DepthMapKind.DisparityPx) {
8802
+ fail(`preview is only supported for kind ${DepthMapKind.DisparityPx}`);
8803
+ }
8804
+ preview = readPreview(root.preview);
8805
+ }
8806
+ return {
8807
+ schema: DEPTH_MANIFEST_SCHEMA,
8808
+ version: 1,
8809
+ kind: depthKind,
8810
+ ...(view === undefined ? {} : { view }),
8811
+ width,
8812
+ height,
8813
+ storage: { format: "png16", noDepth: 0, scale },
8814
+ ...(camera === undefined ? {} : { camera }),
8815
+ ...(displayRange === undefined ? {} : { displayRange }),
8816
+ ...(image === undefined ? {} : { image }),
8817
+ ...(frames === undefined ? {} : { frames }),
8818
+ ...(preview === undefined ? {} : { preview }),
8819
+ };
8820
+ }
8821
+ /**
8822
+ * Expands a clip frame pattern for one frame index: `{index}` becomes the
8823
+ * plain number and `{index:06}` the number zero-padded to six digits.
8824
+ */
8825
+ function resolveDepthFrameFile(pattern, index) {
8826
+ if (!Number.isInteger(index) || index < 0) {
8827
+ throw new RangeError(`Depth frame index must be a non-negative integer, got ${index}.`);
8828
+ }
8829
+ return pattern.replace(FRAME_INDEX_TOKEN, (_token, width) => width === undefined
8830
+ ? String(index)
8831
+ : String(index).padStart(Number(width), "0"));
8832
+ }
8833
+ /**
8834
+ * Checks a host-supplied depth map's shape, without reading its sample values.
8835
+ */
8836
+ function validateDepthMap(map) {
8837
+ const reject = (message) => {
8838
+ throw new RangeError(`DepthMap ${message}.`);
8839
+ };
8840
+ if (!depthMapKinds.has(map.kind)) {
8841
+ reject(`kind must be one of ${[...depthMapKinds].join(", ")}`);
8842
+ }
8843
+ if (!isPositiveInteger(map.width) || !isPositiveInteger(map.height)) {
8844
+ reject("width and height must be positive integers");
8845
+ }
8846
+ const pixelCount = map.width * map.height;
8847
+ const samples = map.samples;
8848
+ if (samples?.encoding === "scaled16") {
8849
+ if (!(samples.values instanceof Uint16Array)) {
8850
+ reject("samples.values must be a Uint16Array for scaled16 samples");
8851
+ }
8852
+ if (!isPositiveNumber(samples.scale)) {
8853
+ reject("samples.scale must be a positive number");
8854
+ }
8855
+ }
8856
+ else if (samples?.encoding === "preview8") {
8857
+ if (!(samples.values instanceof Uint8Array)) {
8858
+ reject("samples.values must be a Uint8Array for preview8 samples");
8859
+ }
8860
+ const levels = samples.levels ?? DepthPreviewLevels.Full;
8861
+ if (!depthPreviewLevels.has(levels)) {
8862
+ reject(`samples.levels must be one of ${[...depthPreviewLevels].join(", ")}`);
8863
+ }
8864
+ if (!isReservedPreviewCode(samples.reservedMax, levels)) {
8865
+ reject(`samples.reservedMax must be ${describeReservedCodes(levels)}`);
8866
+ }
8867
+ if (!isRange(samples.range)) {
8868
+ reject("samples.range must have finite bounds with min < max");
8869
+ }
8870
+ }
8871
+ else {
8872
+ reject('samples.encoding must be "scaled16" or "preview8"');
8873
+ }
8874
+ if (samples.values.length !== pixelCount) {
8875
+ reject(`samples.values has ${samples.values.length} values for ${map.width}x${map.height} pixels`);
8876
+ }
8877
+ if (map.camera !== undefined && !isCamera(map.camera)) {
8878
+ reject("camera needs finite fxPx and baselineM above 0, and finite optional offsets");
8879
+ }
8880
+ if (map.displayRange !== undefined && !isRange(map.displayRange)) {
8881
+ reject("displayRange must have finite bounds with min < max");
8882
+ }
8883
+ if (map.confidence !== undefined) {
8884
+ if (!(map.confidence instanceof Uint8Array)) {
8885
+ reject("confidence must be a Uint8Array");
8886
+ }
8887
+ if (map.confidence.length !== pixelCount) {
8888
+ reject(`confidence has ${map.confidence.length} values for ${map.width}x${map.height} pixels`);
8889
+ }
8890
+ }
8891
+ }
8892
+ function readCamera(value) {
8893
+ const camera = readObject(value, "camera");
8894
+ const fxPx = readPositiveNumber(camera.fx_px, "camera.fx_px");
8895
+ const baselineM = readPositiveNumber(camera.baseline_m, "camera.baseline_m");
8896
+ const doffsPx = readOptionalFinite(camera.doffs_px, "camera.doffs_px");
8897
+ const cxPx = readOptionalFinite(camera.cx_px, "camera.cx_px");
8898
+ const cyPx = readOptionalFinite(camera.cy_px, "camera.cy_px");
8899
+ return {
8900
+ fxPx,
8901
+ baselineM,
8902
+ ...(doffsPx === undefined ? {} : { doffsPx }),
8903
+ ...(cxPx === undefined ? {} : { cxPx }),
8904
+ ...(cyPx === undefined ? {} : { cyPx }),
8905
+ };
8906
+ }
8907
+ /**
8908
+ * `display_range` is in the kind's unit; `display_range_px` is its name for
8909
+ * disparity, kept because disparity producers already write it.
8910
+ */
8911
+ function readDisplayRange(root, kind) {
8912
+ const inKindUnit = readOptionalRange(root.display_range, "display_range");
8913
+ const inPixels = readOptionalRange(root.display_range_px, "display_range_px");
8914
+ if (inPixels !== undefined && kind !== DepthMapKind.DisparityPx) {
8915
+ fail(`display_range_px is only valid for kind ${DepthMapKind.DisparityPx}; use display_range`);
8916
+ }
8917
+ if (inKindUnit !== undefined &&
8918
+ inPixels !== undefined &&
8919
+ (inKindUnit.min !== inPixels.min || inKindUnit.max !== inPixels.max)) {
8920
+ fail("display_range and display_range_px disagree");
8921
+ }
8922
+ return inKindUnit ?? inPixels;
8923
+ }
8924
+ function readImage(value) {
8925
+ const image = readObject(value, "image");
8926
+ const file = readFileName(image.file, "image.file");
8927
+ const confidenceFile = readOptionalFileName(image.confidence_file, "image.confidence_file");
8928
+ return {
8929
+ file,
8930
+ ...(confidenceFile === undefined ? {} : { confidenceFile }),
8931
+ };
8932
+ }
8933
+ function readFrames(value) {
8934
+ const frames = readObject(value, "frames");
8935
+ const count = readPositiveInteger(frames.count, "frames.count");
8936
+ const exact = readFramePattern(frames.exact, "frames.exact");
8937
+ const confidence = frames.confidence === undefined || frames.confidence === null
8938
+ ? undefined
8939
+ : readFramePattern(frames.confidence, "frames.confidence");
8940
+ const timesS = frames.times_s === undefined || frames.times_s === null
8941
+ ? undefined
8942
+ : readFrameTimes(frames.times_s, count);
8943
+ return {
8944
+ count,
8945
+ exact,
8946
+ ...(confidence === undefined ? {} : { confidence }),
8947
+ ...(timesS === undefined ? {} : { timesS }),
8948
+ };
8949
+ }
8950
+ function readFrameTimes(value, count) {
8951
+ if (!Array.isArray(value) || value.length !== count) {
8952
+ fail(`frames.times_s must be an array of frames.count (${count}) times`);
8953
+ }
8954
+ const times = value;
8955
+ times.forEach((time, index) => {
8956
+ if (typeof time !== "number" || !Number.isFinite(time) || time < 0) {
8957
+ fail(`frames.times_s[${index}] must be a finite number of seconds >= 0`);
8958
+ }
8959
+ if (index > 0 && time <= times[index - 1]) {
8960
+ fail(`frames.times_s must strictly increase at index ${index}`);
8961
+ }
8962
+ });
8963
+ return [...times];
8964
+ }
8965
+ /** A preview without `levels` predates TV range and is read as full range. */
8966
+ function readPreview(value) {
8967
+ const preview = readObject(value, "preview");
8968
+ const file = readFileName(preview.file, "preview.file");
8969
+ const codec = readOptionalString(preview.codec, "preview.codec");
8970
+ const levels = preview.levels ?? DepthPreviewLevels.Full;
8971
+ const reservedMax = preview.reserved_max;
8972
+ if (typeof levels !== "string" || !depthPreviewLevels.has(levels)) {
8973
+ fail(`preview.levels must be one of ${[...depthPreviewLevels].join(", ")}`);
8974
+ }
8975
+ const previewLevels = levels;
8976
+ if (!isReservedPreviewCode(reservedMax, previewLevels)) {
8977
+ fail(`preview.reserved_max must be ${describeReservedCodes(previewLevels)}`);
8978
+ }
8979
+ const range = readOptionalRange(preview.range_px, "preview.range_px");
8980
+ if (range === undefined) {
8981
+ fail("preview.range_px is required");
8982
+ }
8983
+ return {
8984
+ file,
8985
+ ...(codec === undefined ? {} : { codec }),
8986
+ levels: previewLevels,
8987
+ reservedMax,
8988
+ range,
8989
+ };
8990
+ }
8991
+ /** The code that stands for the top of a preview's range: 255, or 235 in TV range. */
8992
+ function depthPreviewTopCode(levels = "full") {
8993
+ return PREVIEW_TOP_CODES[levels];
8994
+ }
8995
+ function readFramePattern(value, path) {
8996
+ const pattern = readFileName(value, path);
8997
+ if (!new RegExp(FRAME_INDEX_TOKEN.source).test(pattern)) {
8998
+ fail(`${path} must contain {index} or a padded {index:06}`);
8999
+ }
9000
+ return pattern;
9001
+ }
9002
+ function readOptionalRange(value, path) {
9003
+ if (value === undefined || value === null) {
9004
+ return undefined;
9005
+ }
9006
+ if (!Array.isArray(value) ||
9007
+ value.length !== 2 ||
9008
+ !value.every((bound) => typeof bound === "number" && Number.isFinite(bound))) {
9009
+ fail(`${path} must be two finite numbers [low, high]`);
9010
+ }
9011
+ const [min, max] = value;
9012
+ if (!(min < max)) {
9013
+ fail(`${path} must have low < high`);
9014
+ }
9015
+ return { min, max };
9016
+ }
9017
+ function readObject(value, path) {
9018
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
9019
+ fail(`${path} must be an object`);
9020
+ }
9021
+ return value;
9022
+ }
9023
+ function readPositiveInteger(value, path) {
9024
+ if (!isPositiveInteger(value)) {
9025
+ fail(`${path} must be a positive integer`);
9026
+ }
9027
+ return value;
9028
+ }
9029
+ function readPositiveNumber(value, path) {
9030
+ if (!isPositiveNumber(value)) {
9031
+ fail(`${path} must be a positive number`);
9032
+ }
9033
+ return value;
9034
+ }
9035
+ function readOptionalFinite(value, path) {
9036
+ if (value === undefined || value === null) {
9037
+ return undefined;
9038
+ }
9039
+ if (typeof value !== "number" || !Number.isFinite(value)) {
9040
+ fail(`${path} must be a finite number`);
9041
+ }
9042
+ return value;
9043
+ }
9044
+ function readOptionalString(value, path) {
9045
+ if (value === undefined || value === null) {
9046
+ return undefined;
9047
+ }
9048
+ if (typeof value !== "string") {
9049
+ fail(`${path} must be a string`);
9050
+ }
9051
+ return value;
9052
+ }
9053
+ function readFileName(value, path) {
9054
+ if (typeof value !== "string" || value.length === 0) {
9055
+ fail(`${path} must be a non-empty file name`);
9056
+ }
9057
+ return value;
9058
+ }
9059
+ function readOptionalFileName(value, path) {
9060
+ return value === undefined || value === null
9061
+ ? undefined
9062
+ : readFileName(value, path);
9063
+ }
9064
+ function isPositiveInteger(value) {
9065
+ return typeof value === "number" && Number.isInteger(value) && value > 0;
9066
+ }
9067
+ function isPositiveNumber(value) {
9068
+ return typeof value === "number" && Number.isFinite(value) && value > 0;
9069
+ }
9070
+ /** At least two valid codes must remain, or the preview span is zero. */
9071
+ function isReservedPreviewCode(value, levels) {
9072
+ return (typeof value === "number" &&
9073
+ Number.isInteger(value) &&
9074
+ value >= PREVIEW_MIN_RESERVED_CODES[levels] &&
9075
+ value <= PREVIEW_TOP_CODES[levels] - 2);
9076
+ }
9077
+ function describeReservedCodes(levels) {
9078
+ return `an integer from ${PREVIEW_MIN_RESERVED_CODES[levels]} to ${PREVIEW_TOP_CODES[levels] - 2} at ${levels} levels`;
9079
+ }
9080
+ function isRange(range) {
9081
+ return (range !== undefined &&
9082
+ Number.isFinite(range.min) &&
9083
+ Number.isFinite(range.max) &&
9084
+ range.min < range.max);
9085
+ }
9086
+ function isCamera(camera) {
9087
+ return (isPositiveNumber(camera.fxPx) &&
9088
+ isPositiveNumber(camera.baselineM) &&
9089
+ [camera.doffsPx, camera.cxPx, camera.cyPx].every((value) => value === undefined || Number.isFinite(value)));
9090
+ }
9091
+ function fail(message) {
9092
+ throw new RangeError(`depth.json: ${message}`);
9093
+ }
9094
+
9095
+ /** Percentiles `"auto"` colours between: outliers and flying pixels fall outside. */
9096
+ const DEFAULT_DEPTH_PERCENTILE_LOW = 0.02;
9097
+ const DEFAULT_DEPTH_PERCENTILE_HIGH = 0.98;
9098
+ /** Below this share of valid samples a percentile says nothing about the scene. */
9099
+ const MIN_VALID_SAMPLE_SHARE = 0.01;
9100
+ const PERCENTILE_SAMPLE_STRIDE = 2;
9101
+ const FALLBACK_RANGE = { min: 0, max: 1 };
9102
+ /**
9103
+ * Metric depth needs a camera to come out of disparity, and relative inverse
9104
+ * depth has no metric depth at all, so both fall back to disparity.
9105
+ */
9106
+ function resolveDepthQuantity(kind, quantity = DepthQuantity.Disparity, camera) {
9107
+ if (quantity === DepthQuantity.Disparity) {
9108
+ return { fellBack: false, quantity };
9109
+ }
9110
+ if (kind === DepthMapKind.DepthM ||
9111
+ (kind === DepthMapKind.DisparityPx && camera !== undefined)) {
9112
+ return { fellBack: false, quantity: DepthQuantity.Depth };
9113
+ }
9114
+ return { fellBack: true, quantity: DepthQuantity.Disparity };
9115
+ }
9116
+ function resolveDepthValueConversion(map, quantity) {
9117
+ const resolved = resolveDepthQuantity(map.kind, quantity, map.camera);
9118
+ const nearIsLow = resolved.quantity === DepthQuantity.Depth;
9119
+ const identity = {
9120
+ ...resolved,
9121
+ innerOffset: 0,
9122
+ nearIsLow,
9123
+ numerator: 1,
9124
+ outerOffset: 0,
9125
+ reciprocal: false,
9126
+ };
9127
+ const camera = map.camera;
9128
+ const focalBaseline = camera ? camera.fxPx * camera.baselineM : 1;
9129
+ const doffs = camera?.doffsPx ?? 0;
9130
+ if (map.kind === DepthMapKind.DisparityPx &&
9131
+ resolved.quantity === DepthQuantity.Depth) {
9132
+ // Z = fx * B / (d + doffs)
9133
+ return {
9134
+ ...identity,
9135
+ innerOffset: doffs,
9136
+ numerator: focalBaseline,
9137
+ reciprocal: true,
9138
+ };
9139
+ }
9140
+ if (map.kind === DepthMapKind.DepthM &&
9141
+ resolved.quantity === DepthQuantity.Disparity) {
9142
+ // d = fx * B / Z - doffs, or plain inverse depth without a camera.
9143
+ return {
9144
+ ...identity,
9145
+ numerator: focalBaseline,
9146
+ outerOffset: doffs === 0 ? 0 : -doffs,
9147
+ reciprocal: true,
9148
+ };
9149
+ }
9150
+ return identity;
9151
+ }
9152
+ function convertDepthValue(value, conversion) {
9153
+ return conversion.reciprocal
9154
+ ? conversion.numerator / (value + conversion.innerOffset) +
9155
+ conversion.outerOffset
9156
+ : value;
9157
+ }
9158
+ /**
9159
+ * Converts a range in the map kind's unit, swapping its bounds under a
9160
+ * reciprocal. Null when a bound has no image, such as disparity at or below
9161
+ * `-doffsPx` for depth, which would be infinite or negative.
9162
+ */
9163
+ function convertDepthRange(range, conversion) {
9164
+ if (!hasConvertedValue(Math.min(range.min, range.max), conversion)) {
9165
+ return null;
9166
+ }
9167
+ const first = convertDepthValue(range.min, conversion);
9168
+ const second = convertDepthValue(range.max, conversion);
9169
+ const min = Math.min(first, second);
9170
+ const max = Math.max(first, second);
9171
+ return Number.isFinite(min) && Number.isFinite(max) && min < max
9172
+ ? { max, min }
9173
+ : null;
9174
+ }
9175
+ /** The value in the map kind's unit, or null where there is no depth. */
9176
+ function decodeDepthSample(stored, samples) {
9177
+ if (samples.encoding === "scaled16") {
9178
+ return stored === 0 ? null : stored / samples.scale;
9179
+ }
9180
+ if (stored <= samples.reservedMax) {
9181
+ return null;
9182
+ }
9183
+ const span = depthPreviewSpan(samples);
9184
+ return (samples.range.min +
9185
+ (Math.min(stored - samples.reservedMax - 1, span) / span) *
9186
+ (samples.range.max - samples.range.min));
9187
+ }
9188
+ /**
9189
+ * Steps between the lowest valid preview code and the top one, so one step
9190
+ * is `(range.max - range.min) / span`.
9191
+ */
9192
+ function depthPreviewSpan(samples) {
9193
+ return depthPreviewTopCode(samples.levels) - samples.reservedMax - 1;
9194
+ }
9195
+ /**
9196
+ * This map's own percentile range in the coloured quantity's unit, or null
9197
+ * when fewer than 1 % of the samples it reads hold depth.
9198
+ *
9199
+ * It depends on this map alone, so a frame always gets the same range. Pass
9200
+ * the result back as an explicit range to keep colours steady across frames.
9201
+ */
9202
+ function computeDepthPercentileRange(map, options = {}) {
9203
+ const low = options.low ?? DEFAULT_DEPTH_PERCENTILE_LOW;
9204
+ const high = options.high ?? DEFAULT_DEPTH_PERCENTILE_HIGH;
9205
+ if (!Number.isFinite(low) ||
9206
+ !Number.isFinite(high) ||
9207
+ low < 0 ||
9208
+ high > 1 ||
9209
+ low >= high) {
9210
+ throw new RangeError("Depth percentiles need 0 <= low < high <= 1, as fractions.");
9211
+ }
9212
+ const conversion = resolveDepthValueConversion(map, options.quantity);
9213
+ const histogram = histogramDepthCodes(map, conversion);
9214
+ if (histogram.valid < histogram.sampled * MIN_VALID_SAMPLE_SHARE) {
9215
+ return null;
9216
+ }
9217
+ return rangeFromHistogram(map, histogram, low, high, conversion);
9218
+ }
9219
+ /**
9220
+ * The range a renderer colours between, in the coloured quantity's unit.
9221
+ *
9222
+ * `autoRange` lets a caller that already computed this map's percentile range
9223
+ * skip the histogram. A range that cannot be honoured falls back step by step:
9224
+ * the display range to the percentile range, and that to the full range of
9225
+ * the valid samples, so a sparse frame still colours what it has.
9226
+ */
9227
+ function resolveDepthDisplayRange(map, options, conversion, autoRange) {
9228
+ const range = options.range ?? "clip";
9229
+ if (typeof range === "object") {
9230
+ return range;
9231
+ }
9232
+ if (range === "clip" && map.displayRange) {
9233
+ const clip = convertDepthRange(map.displayRange, conversion);
9234
+ if (clip) {
9235
+ return clip;
9236
+ }
9237
+ }
9238
+ const percentile = autoRange !== undefined
9239
+ ? autoRange
9240
+ : computeDepthPercentileRange(map, { quantity: conversion.quantity });
9241
+ if (percentile) {
9242
+ return percentile;
9243
+ }
9244
+ const histogram = histogramDepthCodes(map, conversion);
9245
+ return histogram.valid > 0
9246
+ ? rangeFromHistogram(map, histogram, 0, 1, conversion)
9247
+ : FALLBACK_RANGE;
9248
+ }
9249
+ /** Resolves a renderer's quantity and range for one map into shader terms. */
9250
+ function resolveDepthColorMapping(map, options = {}, autoRange) {
9251
+ const conversion = resolveDepthValueConversion(map, options.quantity);
9252
+ const range = resolveDepthDisplayRange(map, options, conversion, autoRange);
9253
+ return { ...conversion, hi: range.max, lo: range.min };
9254
+ }
9255
+ function histogramDepthCodes(map, conversion) {
9256
+ const { samples } = map;
9257
+ const values = samples.values;
9258
+ const counts = new Uint32Array(samples.encoding === "scaled16" ? 65_536 : 256);
9259
+ let firstValid = samples.encoding === "scaled16" ? 1 : samples.reservedMax + 1;
9260
+ // Decoded values never fall as codes rise, so the codes the conversion
9261
+ // gives a value for start at one code.
9262
+ while (firstValid < counts.length &&
9263
+ !hasConvertedValue(decodeDepthSample(firstValid, samples), conversion)) {
9264
+ firstValid += 1;
9265
+ }
9266
+ let sampled = 0;
9267
+ let valid = 0;
9268
+ for (let y = 0; y < map.height; y += PERCENTILE_SAMPLE_STRIDE) {
9269
+ const row = y * map.width;
9270
+ for (let x = 0; x < map.width; x += PERCENTILE_SAMPLE_STRIDE) {
9271
+ const code = values[row + x];
9272
+ sampled += 1;
9273
+ if (code >= firstValid) {
9274
+ counts[code] += 1;
9275
+ valid += 1;
9276
+ }
9277
+ }
9278
+ }
9279
+ return { counts, sampled, valid };
9280
+ }
9281
+ /**
9282
+ * Exact percentiles over the stored codes, taken by nearest rank and then
9283
+ * mapped through the monotonic conversion to the coloured quantity. A frame
9284
+ * whose chosen codes coincide, preview codes above the top one counting as
9285
+ * the top one, is widened by one code, so the range stays usable as an
9286
+ * explicit range.
9287
+ */
9288
+ function rangeFromHistogram(map, histogram, low, high, conversion) {
9289
+ const topCode = map.samples.encoding === "scaled16"
9290
+ ? histogram.counts.length - 1
9291
+ : depthPreviewTopCode(map.samples.levels);
9292
+ const lastRank = histogram.valid - 1;
9293
+ let lowCode = Math.min(topCode, codeAtRank(histogram.counts, Math.round(low * lastRank)));
9294
+ let highCode = Math.min(topCode, codeAtRank(histogram.counts, Math.round(high * lastRank)));
9295
+ if (lowCode === highCode) {
9296
+ if (highCode < topCode)
9297
+ highCode += 1;
9298
+ else
9299
+ lowCode -= 1;
9300
+ }
9301
+ const lowValue = decodeDepthSample(lowCode, map.samples) ?? 0;
9302
+ const highValue = decodeDepthSample(highCode, map.samples) ?? 0;
9303
+ return (convertDepthRange({ max: highValue, min: lowValue }, conversion) ??
9304
+ FALLBACK_RANGE);
9305
+ }
9306
+ /**
9307
+ * Whether `value` converts to the coloured quantity: depth from disparity at
9308
+ * or below `-doffsPx` would be infinite or negative, and `readDepthAt` gives
9309
+ * it none.
9310
+ */
9311
+ function hasConvertedValue(value, conversion) {
9312
+ return !conversion.reciprocal || value + conversion.innerOffset > 0;
9313
+ }
9314
+ function codeAtRank(counts, rank) {
9315
+ let seen = 0;
9316
+ for (let code = 0; code < counts.length; code += 1) {
9317
+ seen += counts[code];
9318
+ if (seen > rank) {
9319
+ return code;
9320
+ }
9321
+ }
9322
+ return counts.length - 1;
9323
+ }
9324
+
9325
+ /**
9326
+ * Reads the depth map pixel under a point.
9327
+ *
9328
+ * `coordinateSpace` is the size `point` is measured in, normally the media's;
9329
+ * the map is stretched over it the way the renderer draws it. Without it the
9330
+ * point is in map pixels. Returns null outside the map.
9331
+ */
9332
+ function readDepthAt(map, point, coordinateSpace) {
9333
+ const scaleX = coordinateSpace ? map.width / coordinateSpace.width : 1;
9334
+ const scaleY = coordinateSpace ? map.height / coordinateSpace.height : 1;
9335
+ const x = Math.floor(point.x * scaleX);
9336
+ const y = Math.floor(point.y * scaleY);
9337
+ if (!Number.isFinite(x) ||
9338
+ !Number.isFinite(y) ||
9339
+ x < 0 ||
9340
+ y < 0 ||
9341
+ x >= map.width ||
9342
+ y >= map.height) {
9343
+ return null;
9344
+ }
9345
+ const index = y * map.width + x;
9346
+ const { samples } = map;
9347
+ const stored = samples.values[index];
9348
+ const value = decodeDepthSample(stored, samples);
9349
+ const step = samples.encoding === "scaled16"
9350
+ ? 1 / samples.scale
9351
+ : (samples.range.max - samples.range.min) / depthPreviewSpan(samples);
9352
+ const confidence = map.confidence?.[index];
9353
+ const readout = {
9354
+ precision: samples.encoding === "scaled16" ? "exact" : "preview",
9355
+ step,
9356
+ stored,
9357
+ valid: value !== null,
9358
+ x,
9359
+ y,
9360
+ ...(confidence === undefined ? {} : { confidence: confidence / 255 }),
9361
+ };
9362
+ if (value === null) {
9363
+ return readout;
9364
+ }
9365
+ const camera = map.camera;
9366
+ const focalBaseline = camera ? camera.fxPx * camera.baselineM : undefined;
9367
+ const doffs = camera?.doffsPx ?? 0;
9368
+ switch (map.kind) {
9369
+ case DepthMapKind.DisparityPx: {
9370
+ const shifted = value + doffs;
9371
+ return {
9372
+ ...readout,
9373
+ disparityPx: value,
9374
+ ...(focalBaseline !== undefined && shifted > 0
9375
+ ? { depthM: focalBaseline / shifted }
9376
+ : {}),
9377
+ };
9378
+ }
9379
+ case DepthMapKind.DepthM:
9380
+ return {
9381
+ ...readout,
9382
+ depthM: value,
9383
+ ...(focalBaseline !== undefined
9384
+ ? { disparityPx: focalBaseline / value - doffs }
9385
+ : {}),
9386
+ };
9387
+ default:
9388
+ return { ...readout, relativeInverse: value };
9389
+ }
9390
+ }
9391
+
8316
9392
  var MediaRendererFit;
8317
9393
  (function (MediaRendererFit) {
8318
9394
  /**
@@ -8474,5 +9550,5 @@ var MediaSessionActivityStatus;
8474
9550
  MediaSessionActivityStatus["Waiting"] = "waiting";
8475
9551
  })(MediaSessionActivityStatus || (MediaSessionActivityStatus = {}));
8476
9552
 
8477
- export { AnnotationFrameMutationKind, AnnotationGeometryKind, AnnotationGestureStateKind, AnnotationHandleKind, BaseBoxCornerStyle, BaseBoxStyle, BaseFocusStyle, BaseInteractionStyle, BaseKeypointStyle, BaseLabelStyle, BaseMarkerStyle, BaseMaskStyle, BaseOrientedBoxStyle, BasePercentageBarStyle, BasePolygonStyle, BasePolylineStyle, BoxShape, StrokeAlignment as BoxStrokeAlignment, DEFAULT_DETECTION_CLASS_STYLES, DEFAULT_DETECTION_COLOR_SEQUENCE, DetectionBufferStatus, DetectionFrameRetentionMode, DetectionFrameSelectionMode, DetectionInteractionState, DetectionMaskEncoding, DetectionMaskPayloadFormat, DetectionPickTarget, FocusTargetMode, KeypointMarkerShape, KeypointVisibility, LabelPlacement, LabelVisibilityMode, MAX_ID_MASK_PALETTE_ENTRIES, MAX_ID_MASK_STROKE_WIDTH, MarkerShape, MarkerSizeSpace, MaskRenderMode, MediaErrorKind, MediaInteractionMode, MediaRendererFit, MediaRendererPlaybackState, MediaSessionActivityKind, MediaSessionActivityStatus, MediaSessionMode, MediaSessionStatus, MediaSourceStatus, PercentageBarPlacement, PlaybackGateReach, RegionRendererComposeMode, RegionRendererCoverageKind, RegionRendererMediaEffectKind, RegionRendererRegionKind, RegionRendererSizeSpace, RegionRendererSourceKind, SUPERVISION_ROBOFLOW_COLOR, ShapeInstructionKind, StrokeAlignment, TrackingGeometry, annotationRendererKinds, annotationRenderers, applyAnnotationHandleDrag, canReuseMaskStyleArtifacts, centerRectToTopLeftRect, computeDetectionMaskRect, computeMaskBounds, containsPoint, convertDetectionBoxToMask, convertDetectionBoxToPolygon, convertDetectionMaskToBox, convertDetectionMaskToPolygon, convertDetectionPolygonToBox, convertDetectionPolygonToMask, copySortedDetectionFrames, createAnnotationEditingEngine, createArrayDetectionFrameSource, createBufferedDetectionTimeline, createByteTrackTracker, createCBIoUTracker, createColdDetectionFrameSource, createCompositeDetectionFrameSource, createDefaultAnnotationPresentation, createDetectionPickKey, createEditableAnnotationFrameSession, createIdMaskFrame, createIdleDetectionBufferState, createMemoryColdDetectionFrameStore, createOCSortTracker, createProjectedDetectionFrameSource, createSortTracker, createSourceAwarePresentation, createViewportController, createWritableDetectionFrameSource, decodeCompressedRleCounts, decodeCompressedRleMask, decodeDetectionMaskPayload, deleteAnnotationVertex, detectMaskBorders, detectionFrameOverlapsRange, detectionPostProcessors, distanceToSegment, encodeBinaryMask, encodeBinaryMaskWithBounds, encodeCompressedRleCounts, encodeDetectionMaskPayload, extractDetectionMaskRectRuns, extractMaskContour, extractMaskRectRuns, filterDetectionFramesForRange, findClosestAnnotationSegment, followDetectionPickAcrossFrames, getAnnotationHandles, getBufferedDetectionTimelineFrameSnapshot, getDetectionRect, getPointsRect, haveSameDetectionPickIdentities, includeDefined, isDeflatedBase64DetectionMaskPayload, lightenColor, mediaToScreen, mergeDetectionMasks, mergeDetectionPolygonsByClass, normalizeDetectionClassName, offsetDetection, pickAnnotationHandle, pickDetectionAtPoint, pickDetectionByMaskId, pointInPolygon, polygonArea, polygonToRect, projectDetectionFrame, projectDetectionFrameForTracking, projectDetectionFrames, rasterizePolygonToMask, rasterizeRectToMask, rebaseDetectionPickToFrame, rectArea, rectToPolygon, resolveAnnotationRendererPresentation, resolveAnnotationRendererStyleFields, resolveAnnotationStyleState, resolveContrastTextColor, resolveDetectionClassColorStyle, resolveEllipseSegmentCount, resolveIdMaskPaletteId, resolveIdMaskStrokeTexels, resolveMarkerGeometry, resolveMaskStyleOpacity, resolveStyleValue, sampleEllipseArc, screenToMedia, selectDetectionFrame, topLeftRectToCenterRect, validateDetectionFrames, writeIdMaskPaletteEntry };
9553
+ export { AnnotationFrameMutationKind, AnnotationGeometryKind, AnnotationGestureStateKind, AnnotationHandleKind, BaseBoxCornerStyle, BaseBoxStyle, BaseFocusStyle, BaseInteractionStyle, BaseKeypointStyle, BaseLabelStyle, BaseMarkerStyle, BaseMaskStyle, BaseOrientedBoxStyle, BasePercentageBarStyle, BasePolygonStyle, BasePolylineStyle, BoxShape, StrokeAlignment as BoxStrokeAlignment, DEFAULT_DETECTION_CLASS_STYLES, DEFAULT_DETECTION_COLOR_SEQUENCE, DepthColormap, DepthMapKind, DepthPreviewLevels, DepthQuantity, DepthSampling, DetectionBufferStatus, DetectionFrameRetentionMode, DetectionFrameSelectionMode, DetectionInteractionState, DetectionMaskEncoding, DetectionMaskPayloadFormat, DetectionPickTarget, FocusTargetMode, KeypointMarkerShape, KeypointVisibility, LabelPlacement, LabelVisibilityMode, MAX_ID_MASK_PALETTE_ENTRIES, MAX_ID_MASK_STROKE_WIDTH, MarkerShape, MarkerSizeSpace, MaskRenderMode, MediaErrorKind, MediaInteractionMode, MediaRendererFit, MediaRendererPlaybackState, MediaSessionActivityKind, MediaSessionActivityStatus, MediaSessionMode, MediaSessionStatus, MediaSourceStatus, PLAYHEAD_QUANTIZATION_TOLERANCE_SECONDS, PercentageBarPlacement, PlaybackGateReach, RegionRendererComposeMode, RegionRendererCoverageKind, RegionRendererMediaEffectKind, RegionRendererRegionKind, RegionRendererSizeSpace, RegionRendererSourceKind, SUPERVISION_ROBOFLOW_COLOR, ShapeInstructionKind, StrokeAlignment, TrackingGeometry, annotationRendererKinds, annotationRenderers, applyAnnotationHandleDrag, canReuseMaskStyleArtifacts, centerRectToTopLeftRect, computeDepthPercentileRange, computeDetectionMaskRect, computeMaskBounds, containsPoint, convertDetectionBoxToMask, convertDetectionBoxToPolygon, convertDetectionMaskToBox, convertDetectionMaskToPolygon, convertDetectionPolygonToBox, convertDetectionPolygonToMask, copySortedDetectionFrames, createAnnotationEditingEngine, createArrayDetectionFrameSource, createBufferedDetectionTimeline, createByteTrackTracker, createCBIoUTracker, createColdDetectionFrameSource, createCompositeDetectionFrameSource, createDefaultAnnotationPresentation, createDepthColormapLut, createDetectionPickKey, createEditableAnnotationFrameSession, createIdMaskFrame, createIdleDetectionBufferState, createMemoryColdDetectionFrameStore, createOCSortTracker, createProjectedDetectionFrameSource, createSortTracker, createSourceAwarePresentation, createViewportController, createWritableDetectionFrameSource, decodeCompressedRleCounts, decodeCompressedRleMask, decodeDetectionMaskPayload, deleteAnnotationVertex, depthColormapColors, depthPreviewTopCode, detectMaskBorders, detectionFrameOverlapsRange, detectionPostProcessors, distanceToSegment, encodeBinaryMask, encodeBinaryMaskWithBounds, encodeCompressedRleCounts, encodeDetectionMaskPayload, extractDetectionMaskRectRuns, extractMaskContour, extractMaskRectRuns, filterDetectionFramesForRange, findClosestAnnotationSegment, followDetectionPickAcrossFrames, getAnnotationHandles, getBufferedDetectionTimelineFrameSnapshot, getDetectionRect, getPointsRect, haveSameDetectionPickIdentities, includeDefined, isDeflatedBase64DetectionMaskPayload, isDepthColormap, lightenColor, mediaToScreen, mergeDetectionMasks, mergeDetectionPolygonsByClass, normalizeDetectionClassName, offsetDetection, parseDepthManifest, pickAnnotationHandle, pickDetectionAtPoint, pickDetectionByMaskId, pointInPolygon, polygonArea, polygonToRect, projectDetectionFrame, projectDetectionFrameForTracking, projectDetectionFrames, rasterizePolygonToMask, rasterizeRectToMask, readDepthAt, rebaseDetectionPickToFrame, rectArea, rectToPolygon, resolveAnnotationRendererPresentation, resolveAnnotationRendererStyleFields, resolveAnnotationStyleState, resolveContrastTextColor, resolveDepthColorMapping, resolveDepthFrameFile, resolveDepthQuantity, resolveDetectionClassColorStyle, resolveEllipseSegmentCount, resolveIdMaskPaletteId, resolveIdMaskStrokeTexels, resolveMarkerGeometry, resolveMaskStyleOpacity, resolveStyleValue, sampleEllipseArc, screenToMedia, selectDetectionFrame, sortedDetectionFrames, topLeftRectToCenterRect, validateDepthMap, validateDetectionFrames, writeIdMaskPaletteEntry };
8478
9554
  //# sourceMappingURL=index.js.map