@jax-data-science/sci-image-visualizer 0.1.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.
Files changed (311) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +404 -0
  3. package/esm2022/index.mjs +52 -0
  4. package/esm2022/jax-data-science-sci-image-visualizer.mjs +5 -0
  5. package/esm2022/lib/channel-histogram/channel-histogram.component.mjs +398 -0
  6. package/esm2022/lib/contracts/capabilities.contract.mjs +32 -0
  7. package/esm2022/lib/contracts/cell-segmenter.contract.mjs +12 -0
  8. package/esm2022/lib/contracts/channel-histogram-api.contract.mjs +14 -0
  9. package/esm2022/lib/contracts/colormap-lut.mjs +95 -0
  10. package/esm2022/lib/contracts/coordinate-transform.contract.mjs +2 -0
  11. package/esm2022/lib/contracts/display-types.mjs +8 -0
  12. package/esm2022/lib/contracts/image.contract.mjs +11 -0
  13. package/esm2022/lib/contracts/intensity.mjs +28 -0
  14. package/esm2022/lib/contracts/plot-type.mjs +112 -0
  15. package/esm2022/lib/contracts/ports/image-state.port.mjs +3 -0
  16. package/esm2022/lib/contracts/ports/preferences.port.mjs +3 -0
  17. package/esm2022/lib/contracts/ports/region-io.port.mjs +3 -0
  18. package/esm2022/lib/contracts/ports/tile-access.port.mjs +3 -0
  19. package/esm2022/lib/contracts/region-editor-api.contract.mjs +4 -0
  20. package/esm2022/lib/contracts/region-overlay.contract.mjs +2 -0
  21. package/esm2022/lib/contracts/region-store.contract.mjs +2 -0
  22. package/esm2022/lib/contracts/sam.contract.mjs +12 -0
  23. package/esm2022/lib/contracts/toolbar-config.mjs +8 -0
  24. package/esm2022/lib/contracts/visualizer.contract.mjs +10 -0
  25. package/esm2022/lib/contracts/viz-config.mjs +3 -0
  26. package/esm2022/lib/hex-color-picker/hex-color-picker.component.mjs +260 -0
  27. package/esm2022/lib/implementations/base-store-visualizer.mjs +76 -0
  28. package/esm2022/lib/implementations/napari-js/napari-axes-labels.mjs +106 -0
  29. package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +847 -0
  30. package/esm2022/lib/implementations/napari-js/napari-scale-bar.mjs +92 -0
  31. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +2283 -0
  32. package/esm2022/lib/implementations/napari-js/napari-volume-z-handle.mjs +126 -0
  33. package/esm2022/lib/implementations/osd/display-pipeline.mjs +143 -0
  34. package/esm2022/lib/implementations/osd/histogram-sampler.mjs +217 -0
  35. package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +1780 -0
  36. package/esm2022/lib/implementations/osd/osd-coordinate-transform.mjs +25 -0
  37. package/esm2022/lib/implementations/osd/osd-coords.mjs +53 -0
  38. package/esm2022/lib/implementations/osd/osd-lib.mjs +20 -0
  39. package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +1237 -0
  40. package/esm2022/lib/implementations/osd/osd-scale-bar.mjs +88 -0
  41. package/esm2022/lib/implementations/osd/slice-cache.mjs +488 -0
  42. package/esm2022/lib/implementations/osd/tile-client.mjs +29 -0
  43. package/esm2022/lib/implementations/plotly/plotly-coordinate-transform.mjs +37 -0
  44. package/esm2022/lib/implementations/plotly/plotly-region-overlay.mjs +31 -0
  45. package/esm2022/lib/implementations/plotly/plotly-trace-builders.mjs +183 -0
  46. package/esm2022/lib/implementations/plotly/plotly.service.mjs +2137 -0
  47. package/esm2022/lib/implementations/simple-slice-access.service.mjs +99 -0
  48. package/esm2022/lib/models/bezier.mjs +120 -0
  49. package/esm2022/lib/models/class-preset.mjs +46 -0
  50. package/esm2022/lib/models/geometry.mjs +198 -0
  51. package/esm2022/lib/models/region.mjs +166 -0
  52. package/esm2022/lib/models/shape.mjs +53 -0
  53. package/esm2022/lib/plot.utilities.mjs +693 -0
  54. package/esm2022/lib/processing/image-converter.service.mjs +90 -0
  55. package/esm2022/lib/processing/image-crop.mjs +62 -0
  56. package/esm2022/lib/processing/processing-image.mjs +50 -0
  57. package/esm2022/lib/provide-visualization.mjs +63 -0
  58. package/esm2022/lib/region-editor/mask-raster.mjs +95 -0
  59. package/esm2022/lib/region-editor/mask-worker.mjs +10 -0
  60. package/esm2022/lib/region-editor/region-editor.component.mjs +1190 -0
  61. package/esm2022/lib/region-ops.service.mjs +301 -0
  62. package/esm2022/lib/render-orchestrator.mjs +87 -0
  63. package/esm2022/lib/routing-visualizer.service.mjs +533 -0
  64. package/esm2022/lib/store/class-color.util.mjs +52 -0
  65. package/esm2022/lib/store/region-store.service.mjs +1029 -0
  66. package/esm2022/lib/store/visualizer-store.service.mjs +352 -0
  67. package/esm2022/lib/toolbar/brush/brush-tool.service.mjs +546 -0
  68. package/esm2022/lib/toolbar/crop/slide-crop.mjs +57 -0
  69. package/esm2022/lib/toolbar/segmentation/cell-segment-tool.service.mjs +115 -0
  70. package/esm2022/lib/toolbar/segmentation/cellpose-segmenter.service.mjs +84 -0
  71. package/esm2022/lib/toolbar/segmentation/onnx-sam-session.mjs +133 -0
  72. package/esm2022/lib/toolbar/segmentation/ort-runtime-config.mjs +31 -0
  73. package/esm2022/lib/toolbar/segmentation/sam-model-registry.mjs +108 -0
  74. package/esm2022/lib/toolbar/segmentation/sam-onnx-core.mjs +159 -0
  75. package/esm2022/lib/toolbar/segmentation/sam-point-tool.service.mjs +255 -0
  76. package/esm2022/lib/toolbar/segmentation/sam-prompt.mjs +94 -0
  77. package/esm2022/lib/toolbar/segmentation/sam-tool.service.mjs +188 -0
  78. package/esm2022/lib/toolbar/toolbar.component.mjs +311 -0
  79. package/esm2022/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.mjs +234 -0
  80. package/esm2022/lib/toolbar/wand/wand-tool.service.mjs +499 -0
  81. package/esm2022/lib/toolbar/wand/wand.service.mjs +921 -0
  82. package/esm2022/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.mjs +157 -0
  83. package/esm2022/lib/visualization.module.mjs +162 -0
  84. package/esm2022/lib/visualizer.component.mjs +1597 -0
  85. package/fesm2022/jax-data-science-sci-image-visualizer-mask-worker-uhepXUhM.mjs +12 -0
  86. package/fesm2022/jax-data-science-sci-image-visualizer-mask-worker-uhepXUhM.mjs.map +1 -0
  87. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-ci1q0xnJ.mjs +327 -0
  88. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-ci1q0xnJ.mjs.map +1 -0
  89. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +21314 -0
  90. package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -0
  91. package/fesm2022/mask.worker.js +989 -0
  92. package/fesm2022/onnx-sam.worker.js +202 -0
  93. package/index.d.ts +39 -0
  94. package/lib/channel-histogram/channel-histogram.component.d.ts +112 -0
  95. package/lib/contracts/capabilities.contract.d.ts +30 -0
  96. package/lib/contracts/cell-segmenter.contract.d.ts +40 -0
  97. package/lib/contracts/channel-histogram-api.contract.d.ts +98 -0
  98. package/lib/contracts/colormap-lut.d.ts +21 -0
  99. package/lib/contracts/coordinate-transform.contract.d.ts +43 -0
  100. package/lib/contracts/display-types.d.ts +41 -0
  101. package/lib/contracts/image.contract.d.ts +72 -0
  102. package/lib/contracts/intensity.d.ts +18 -0
  103. package/lib/contracts/plot-type.d.ts +108 -0
  104. package/lib/contracts/ports/image-state.port.d.ts +29 -0
  105. package/lib/contracts/ports/preferences.port.d.ts +19 -0
  106. package/lib/contracts/ports/region-io.port.d.ts +29 -0
  107. package/lib/contracts/ports/tile-access.port.d.ts +27 -0
  108. package/lib/contracts/region-editor-api.contract.d.ts +83 -0
  109. package/lib/contracts/region-overlay.contract.d.ts +47 -0
  110. package/lib/contracts/region-store.contract.d.ts +74 -0
  111. package/lib/contracts/sam.contract.d.ts +98 -0
  112. package/lib/contracts/toolbar-config.d.ts +24 -0
  113. package/lib/contracts/visualizer.contract.d.ts +346 -0
  114. package/lib/contracts/viz-config.d.ts +25 -0
  115. package/lib/hex-color-picker/hex-color-picker.component.d.ts +47 -0
  116. package/lib/implementations/base-store-visualizer.d.ts +71 -0
  117. package/lib/implementations/napari-js/napari-axes-labels.d.ts +47 -0
  118. package/lib/implementations/napari-js/napari-region-overlay.d.ts +115 -0
  119. package/lib/implementations/napari-js/napari-scale-bar.d.ts +31 -0
  120. package/lib/implementations/napari-js/napari-visualizer.service.d.ts +455 -0
  121. package/lib/implementations/napari-js/napari-volume-z-handle.d.ts +46 -0
  122. package/lib/implementations/osd/display-pipeline.d.ts +47 -0
  123. package/lib/implementations/osd/histogram-sampler.d.ts +85 -0
  124. package/lib/implementations/osd/openseadragon-visualizer.service.d.ts +476 -0
  125. package/lib/implementations/osd/osd-coordinate-transform.d.ts +17 -0
  126. package/lib/implementations/osd/osd-coords.d.ts +16 -0
  127. package/lib/implementations/osd/osd-lib.d.ts +19 -0
  128. package/lib/implementations/osd/osd-region-overlay.d.ts +191 -0
  129. package/lib/implementations/osd/osd-scale-bar.d.ts +17 -0
  130. package/lib/implementations/osd/slice-cache.d.ts +161 -0
  131. package/lib/implementations/osd/tile-client.d.ts +32 -0
  132. package/lib/implementations/plotly/plotly-coordinate-transform.d.ts +19 -0
  133. package/lib/implementations/plotly/plotly-region-overlay.d.ts +23 -0
  134. package/lib/implementations/plotly/plotly-trace-builders.d.ts +60 -0
  135. package/lib/implementations/plotly/plotly.service.d.ts +594 -0
  136. package/lib/implementations/simple-slice-access.service.d.ts +64 -0
  137. package/lib/models/bezier.d.ts +59 -0
  138. package/lib/models/class-preset.d.ts +39 -0
  139. package/lib/models/geometry.d.ts +66 -0
  140. package/lib/models/region.d.ts +132 -0
  141. package/lib/models/shape.d.ts +44 -0
  142. package/lib/plot.utilities.d.ts +107 -0
  143. package/lib/processing/image-converter.service.d.ts +28 -0
  144. package/lib/processing/image-crop.d.ts +18 -0
  145. package/lib/processing/processing-image.d.ts +17 -0
  146. package/lib/provide-visualization.d.ts +34 -0
  147. package/lib/region-editor/mask-raster.d.ts +61 -0
  148. package/lib/region-editor/mask-worker.d.ts +7 -0
  149. package/lib/region-editor/region-editor.component.d.ts +305 -0
  150. package/lib/region-ops.service.d.ts +92 -0
  151. package/lib/render-orchestrator.d.ts +59 -0
  152. package/lib/routing-visualizer.service.d.ts +227 -0
  153. package/lib/store/class-color.util.d.ts +26 -0
  154. package/lib/store/region-store.service.d.ts +315 -0
  155. package/lib/store/visualizer-store.service.d.ts +123 -0
  156. package/lib/toolbar/brush/brush-tool.service.d.ts +143 -0
  157. package/lib/toolbar/crop/slide-crop.d.ts +30 -0
  158. package/lib/toolbar/segmentation/cell-segment-tool.service.d.ts +32 -0
  159. package/lib/toolbar/segmentation/cellpose-segmenter.service.d.ts +39 -0
  160. package/lib/toolbar/segmentation/onnx-sam-session.d.ts +25 -0
  161. package/lib/toolbar/segmentation/ort-runtime-config.d.ts +4 -0
  162. package/lib/toolbar/segmentation/sam-model-registry.d.ts +36 -0
  163. package/lib/toolbar/segmentation/sam-onnx-core.d.ts +48 -0
  164. package/lib/toolbar/segmentation/sam-point-tool.service.d.ts +59 -0
  165. package/lib/toolbar/segmentation/sam-prompt.d.ts +34 -0
  166. package/lib/toolbar/segmentation/sam-tool.service.d.ts +50 -0
  167. package/lib/toolbar/toolbar.component.d.ts +167 -0
  168. package/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.d.ts +64 -0
  169. package/lib/toolbar/wand/wand-tool.service.d.ts +149 -0
  170. package/lib/toolbar/wand/wand.service.d.ts +133 -0
  171. package/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.d.ts +49 -0
  172. package/lib/visualization.module.d.ts +45 -0
  173. package/lib/visualizer.component.d.ts +378 -0
  174. package/package.json +73 -0
  175. package/src/lib/assets/3d-coordinates.svg +49 -0
  176. package/src/lib/assets/cells.svg +1 -0
  177. package/src/lib/assets/click.svg +1 -0
  178. package/src/lib/assets/colormap-luts.json +1 -0
  179. package/src/lib/assets/contour.svg +48 -0
  180. package/src/lib/assets/cube-3d.svg +1 -0
  181. package/src/lib/assets/edit-selection-white.svg +47 -0
  182. package/src/lib/assets/heatmap.svg +1 -0
  183. package/src/lib/assets/icons/colormap-Pastel1.png +0 -0
  184. package/src/lib/assets/icons/colormap-accent.png +0 -0
  185. package/src/lib/assets/icons/colormap-afmhot.png +0 -0
  186. package/src/lib/assets/icons/colormap-autumn.png +0 -0
  187. package/src/lib/assets/icons/colormap-berlin.png +0 -0
  188. package/src/lib/assets/icons/colormap-binary.png +0 -0
  189. package/src/lib/assets/icons/colormap-blackbody.png +0 -0
  190. package/src/lib/assets/icons/colormap-bluered.png +0 -0
  191. package/src/lib/assets/icons/colormap-blues.png +0 -0
  192. package/src/lib/assets/icons/colormap-bone.png +0 -0
  193. package/src/lib/assets/icons/colormap-brbg.png +0 -0
  194. package/src/lib/assets/icons/colormap-brg.png +0 -0
  195. package/src/lib/assets/icons/colormap-bugn.png +0 -0
  196. package/src/lib/assets/icons/colormap-bupu.png +0 -0
  197. package/src/lib/assets/icons/colormap-bwr.png +0 -0
  198. package/src/lib/assets/icons/colormap-cividis.png +0 -0
  199. package/src/lib/assets/icons/colormap-cmrmap.png +0 -0
  200. package/src/lib/assets/icons/colormap-cool.png +0 -0
  201. package/src/lib/assets/icons/colormap-coolwarm.png +0 -0
  202. package/src/lib/assets/icons/colormap-copper.png +0 -0
  203. package/src/lib/assets/icons/colormap-cubehelix.png +0 -0
  204. package/src/lib/assets/icons/colormap-dark2.png +0 -0
  205. package/src/lib/assets/icons/colormap-earth.png +0 -0
  206. package/src/lib/assets/icons/colormap-electric.png +0 -0
  207. package/src/lib/assets/icons/colormap-flag.png +0 -0
  208. package/src/lib/assets/icons/colormap-gist_earth.png +0 -0
  209. package/src/lib/assets/icons/colormap-gist_gray.png +0 -0
  210. package/src/lib/assets/icons/colormap-gist_heat.png +0 -0
  211. package/src/lib/assets/icons/colormap-gist_ncar.png +0 -0
  212. package/src/lib/assets/icons/colormap-gist_rainbow.png +0 -0
  213. package/src/lib/assets/icons/colormap-gist_stern.png +0 -0
  214. package/src/lib/assets/icons/colormap-gist_yarg.png +0 -0
  215. package/src/lib/assets/icons/colormap-gnbu.png +0 -0
  216. package/src/lib/assets/icons/colormap-gnuplot.png +0 -0
  217. package/src/lib/assets/icons/colormap-gnuplot2.png +0 -0
  218. package/src/lib/assets/icons/colormap-gray.png +0 -0
  219. package/src/lib/assets/icons/colormap-greens-inv.png +0 -0
  220. package/src/lib/assets/icons/colormap-greens.png +0 -0
  221. package/src/lib/assets/icons/colormap-greys-inv.png +0 -0
  222. package/src/lib/assets/icons/colormap-greys.png +0 -0
  223. package/src/lib/assets/icons/colormap-hot.png +0 -0
  224. package/src/lib/assets/icons/colormap-hsv.png +0 -0
  225. package/src/lib/assets/icons/colormap-inferno.png +0 -0
  226. package/src/lib/assets/icons/colormap-jet.png +0 -0
  227. package/src/lib/assets/icons/colormap-magma.png +0 -0
  228. package/src/lib/assets/icons/colormap-managua.png +0 -0
  229. package/src/lib/assets/icons/colormap-nipy_spectral.png +0 -0
  230. package/src/lib/assets/icons/colormap-ocean.png +0 -0
  231. package/src/lib/assets/icons/colormap-oranges.png +0 -0
  232. package/src/lib/assets/icons/colormap-orrd.png +0 -0
  233. package/src/lib/assets/icons/colormap-pastel2.png +0 -0
  234. package/src/lib/assets/icons/colormap-picnic.png +0 -0
  235. package/src/lib/assets/icons/colormap-pink.png +0 -0
  236. package/src/lib/assets/icons/colormap-piyg.png +0 -0
  237. package/src/lib/assets/icons/colormap-placeholder.png +0 -0
  238. package/src/lib/assets/icons/colormap-plasma.png +0 -0
  239. package/src/lib/assets/icons/colormap-portland.png +0 -0
  240. package/src/lib/assets/icons/colormap-prgn.png +0 -0
  241. package/src/lib/assets/icons/colormap-prism.png +0 -0
  242. package/src/lib/assets/icons/colormap-pubu.png +0 -0
  243. package/src/lib/assets/icons/colormap-pubugn.png +0 -0
  244. package/src/lib/assets/icons/colormap-puor.png +0 -0
  245. package/src/lib/assets/icons/colormap-purd.png +0 -0
  246. package/src/lib/assets/icons/colormap-purples.png +0 -0
  247. package/src/lib/assets/icons/colormap-rainbow.png +0 -0
  248. package/src/lib/assets/icons/colormap-rdbu.png +0 -0
  249. package/src/lib/assets/icons/colormap-rdgy.png +0 -0
  250. package/src/lib/assets/icons/colormap-rdpu.png +0 -0
  251. package/src/lib/assets/icons/colormap-rdylbu.png +0 -0
  252. package/src/lib/assets/icons/colormap-rdylgn.png +0 -0
  253. package/src/lib/assets/icons/colormap-reds.png +0 -0
  254. package/src/lib/assets/icons/colormap-seismic.png +0 -0
  255. package/src/lib/assets/icons/colormap-set1.png +0 -0
  256. package/src/lib/assets/icons/colormap-set2.png +0 -0
  257. package/src/lib/assets/icons/colormap-set3.png +0 -0
  258. package/src/lib/assets/icons/colormap-spectral.png +0 -0
  259. package/src/lib/assets/icons/colormap-spring.png +0 -0
  260. package/src/lib/assets/icons/colormap-summer.png +0 -0
  261. package/src/lib/assets/icons/colormap-tab10.png +0 -0
  262. package/src/lib/assets/icons/colormap-tab20.png +0 -0
  263. package/src/lib/assets/icons/colormap-tab20b.png +0 -0
  264. package/src/lib/assets/icons/colormap-tab20c.png +0 -0
  265. package/src/lib/assets/icons/colormap-terrain.png +0 -0
  266. package/src/lib/assets/icons/colormap-turbo.png +0 -0
  267. package/src/lib/assets/icons/colormap-twilight.png +0 -0
  268. package/src/lib/assets/icons/colormap-twilight_shifted.png +0 -0
  269. package/src/lib/assets/icons/colormap-vanimo.png +0 -0
  270. package/src/lib/assets/icons/colormap-viridis.png +0 -0
  271. package/src/lib/assets/icons/colormap-winter.png +0 -0
  272. package/src/lib/assets/icons/colormap-wistia.png +0 -0
  273. package/src/lib/assets/icons/colormap-ylgn.png +0 -0
  274. package/src/lib/assets/icons/colormap-ylgnbu-inv.png +0 -0
  275. package/src/lib/assets/icons/colormap-ylgnbu.png +0 -0
  276. package/src/lib/assets/icons/colormap-ylorbr.png +0 -0
  277. package/src/lib/assets/icons/colormap-ylorrd-inv.png +0 -0
  278. package/src/lib/assets/icons/colormap-ylorrd.png +0 -0
  279. package/src/lib/assets/interactive-segmentation-cursor.svg +1 -0
  280. package/src/lib/assets/invert.svg +1 -0
  281. package/src/lib/assets/isosurface.svg +7 -0
  282. package/src/lib/assets/mask.svg +1 -0
  283. package/src/lib/assets/paintbrush.svg +1 -0
  284. package/src/lib/assets/picture-segmentation.svg +43 -0
  285. package/src/lib/assets/polygon-vertices.svg +13 -0
  286. package/src/lib/assets/polyline.svg +3 -0
  287. package/src/lib/assets/redo.svg +39 -0
  288. package/src/lib/assets/region-editor.svg +37 -0
  289. package/src/lib/assets/region-move.svg +7 -0
  290. package/src/lib/assets/smooth.svg +56 -0
  291. package/src/lib/assets/spline-chart.svg +7 -0
  292. package/src/lib/assets/surface.svg +37 -0
  293. package/src/lib/assets/test/download-379.svg +1 -0
  294. package/src/lib/assets/test/download-98.svg +1 -0
  295. package/src/lib/assets/test/json-1.svg +1 -0
  296. package/src/lib/assets/test/load-53.svg +1 -0
  297. package/src/lib/assets/test/mask-44.svg +1 -0
  298. package/src/lib/assets/test/mask-download-44.svg +15 -0
  299. package/src/lib/assets/test/mask-save-44.svg +11 -0
  300. package/src/lib/assets/test/overlay-1.svg +1 -0
  301. package/src/lib/assets/test/overlay-4.svg +1 -0
  302. package/src/lib/assets/test/region-26.svg +1 -0
  303. package/src/lib/assets/test/save-56.svg +1 -0
  304. package/src/lib/assets/test/upload-43.svg +1 -0
  305. package/src/lib/assets/to-bezier.svg +15 -0
  306. package/src/lib/assets/to-polygon.svg +11 -0
  307. package/src/lib/assets/undo.svg +38 -0
  308. package/src/lib/assets/vertex-add.svg +12 -0
  309. package/src/lib/assets/vertex-delete.svg +12 -0
  310. package/src/lib/assets/wand.svg +54 -0
  311. package/src/lib/assets/zoom-box.svg +10 -0
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Bezier-curve helpers (no external dependency).
3
+ *
4
+ * JIT supports true bezier regions: a polygon's vertices are the editable
5
+ * *anchors*, and the smooth curve through them is derived here with the
6
+ * Catmull-Rom construction — the same algorithm paper.js uses in
7
+ * `path.smooth()`. The curve interpolates every anchor and
8
+ * each anchor's two handles are colinear (a smooth tangent).
9
+ *
10
+ * The OSD overlay renders the curve as a true cubic SVG path + draggable handles
11
+ * (see {@link bezierAnchorHandles}); GeoJSON export flattens the *same* cubics
12
+ * into a dense point list (see {@link bezierCurve}) so a viewer without bezier
13
+ * support (e.g. QuPath, which just draws the coordinate list) still shows the
14
+ * smooth shape. Using one algorithm for both keeps what JIT draws identical to
15
+ * what it exports.
16
+ *
17
+ * Pure functions: no DOM, no service state. Coordinates are image pixels.
18
+ */
19
+ export interface CurvePoints {
20
+ xs: number[];
21
+ ys: number[];
22
+ }
23
+ /** A vertex's two cubic-bezier control points (absolute coords) plus whether
24
+ * each side has a handle (open-path endpoints have only one). */
25
+ export interface AnchorHandle {
26
+ in: [number, number];
27
+ out: [number, number];
28
+ hasIn: boolean;
29
+ hasOut: boolean;
30
+ }
31
+ /**
32
+ * Per-anchor cubic-bezier control points using the Catmull-Rom construction
33
+ * (tension 1: control = anchor ± (next − prev) / 6). Matches paper.js
34
+ * `path.smooth()`: the resulting cubic interpolates every anchor and the two
35
+ * handles of each anchor are colinear. Coordinates are in the input space.
36
+ */
37
+ export declare function bezierAnchorHandles(xs: number[], ys: number[], closed: boolean): AnchorHandle[];
38
+ /** The Catmull-Rom handles as **relative** offsets `[dx, dy]` per anchor — used
39
+ * to initialise a region's editable handles when bezier is turned on. */
40
+ export declare function defaultHandleOffsets(xs: number[], ys: number[], closed: boolean): {
41
+ in: number[][];
42
+ out: number[][];
43
+ };
44
+ /** Absolute handles from stored relative offsets (anchor + offset). */
45
+ export declare function handlesFromOffsets(xs: number[], ys: number[], inOff: number[][], outOff: number[][], closed: boolean): AnchorHandle[];
46
+ /** A region's handles: from its stored (editable) offsets when present, else the
47
+ * Catmull-Rom default. The single source of truth for both rendering and export. */
48
+ export declare function resolveHandles(xs: number[], ys: number[], closed: boolean, inOff?: number[][], outOff?: number[][]): AnchorHandle[];
49
+ /**
50
+ * Flatten a cubic bezier (defined by explicit per-anchor handles) into a dense
51
+ * point list by sampling each segment. The curve passes through every anchor; a
52
+ * closed ring returns to its first point.
53
+ */
54
+ export declare function bezierCurveFromHandles(xs: number[], ys: number[], handles: AnchorHandle[], closed: boolean): CurvePoints;
55
+ /**
56
+ * Flatten the smooth Catmull-Rom bezier through the anchors (no custom handles).
57
+ * Falls back to the anchors when there are too few to form a curve.
58
+ */
59
+ export declare function bezierCurve(xs: number[], ys: number[], closed: boolean): CurvePoints;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Preset annotation classes (jit-ui#70).
3
+ *
4
+ * A class is a flat `{ name, color }` pair (v1: no hierarchy, no special-class semantics).
5
+ * The `PresetSet` is the per-user, server-persisted source of truth for region colours;
6
+ * see `class-color.util.ts` for the deterministic colour-resolution engine.
7
+ */
8
+ export type PresetSource = 'user' | 'default' | 'auto';
9
+ export interface ClassPreset {
10
+ /** The class name — matched against `Region.label`. */
11
+ name: string;
12
+ /** Hex colour, `#RRGGBB`. */
13
+ color: string;
14
+ /** Reserved for a future per-class overlay-visibility toggle. */
15
+ visible?: boolean;
16
+ /** Provenance; `'auto'` = added by opt-in fallback promotion. */
17
+ source?: PresetSource;
18
+ }
19
+ export type MatchMode = 'exact' | 'normalized';
20
+ export interface PresetSet {
21
+ /** Ordered list of preset classes. */
22
+ classes: ClassPreset[];
23
+ /** Colours used for classes not in `classes` (assigned deterministically). */
24
+ fallbackPalette: string[];
25
+ /** Opt-in (default false): add an unknown class to `classes` the first time it is seen. */
26
+ autoPromote: boolean;
27
+ /** Label matching against `Region.label` (default `'exact'`). */
28
+ matchMode: MatchMode;
29
+ }
30
+ /**
31
+ * Fallback palette for classes not present in the preset set — reasonably distinct hues.
32
+ * Colours are assigned by a stable hash of the class name, so the same unknown class always
33
+ * gets the same colour with no stored state.
34
+ */
35
+ export declare const DEFAULT_FALLBACK_PALETTE: string[];
36
+ /** A fresh default preset set (deep-copied so callers can mutate safely). */
37
+ export declare function defaultPresetSet(): PresetSet;
38
+ /** True when the set has no usable classes (e.g. the server returned an empty/blank record). */
39
+ export declare function isEmptyPresetSet(set: PresetSet | null | undefined): boolean;
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Pure geometry helpers extracted from PlotlyService.
3
+ *
4
+ * No DOM access, no service state, no `this` — every function is testable
5
+ * in isolation. Keep it that way: this module is the dumping ground for
6
+ * shape/mask/SVG-path utilities the wand, vertex eraser, and region editor
7
+ * share. If a helper grows a `this.shapes` reference, it doesn't belong here.
8
+ */
9
+ /** A bbox-relative binary mask (1 = filled, 0 = empty). */
10
+ export interface BBoxMask {
11
+ bx: number;
12
+ by: number;
13
+ bw: number;
14
+ bh: number;
15
+ mask: Uint8Array;
16
+ }
17
+ /** Parsed single-subpath polygon vertices. */
18
+ export interface PolygonVertices {
19
+ xpoints: number[];
20
+ ypoints: number[];
21
+ }
22
+ /**
23
+ * Parse a single-subpath `M x,y L x,y ... Z` path into vertex arrays.
24
+ *
25
+ * Returns null for paths we can't safely round-trip (multi-subpath, curves,
26
+ * fewer than three vertices). The wand only adopts shapes it produced or
27
+ * that Plotly's drawclosedpath produces, both of which are single-subpath
28
+ * polygons.
29
+ */
30
+ export declare function parseSvgPathPolygon(path: string): PolygonVertices | null;
31
+ /**
32
+ * Build a closed SVG path string `M x,y L x,y L ... Z` from vertex arrays.
33
+ * Returns '' for fewer than three vertices (degenerate).
34
+ */
35
+ export declare function polygonToSvgPath(xpoints: number[], ypoints: number[]): string;
36
+ /**
37
+ * Build an SVG path string from vertex arrays. Closed polygons end with `Z`,
38
+ * open polylines do not. Returns '' for fewer than two vertices (degenerate).
39
+ */
40
+ export declare function verticesToSvgPath(xs: number[], ys: number[], closed: boolean): string;
41
+ /**
42
+ * Compare two Plotly shape objects for "same region" — used by the wand to
43
+ * avoid appending duplicates when the user pushes the same find result more
44
+ * than once. Polygons compare by SVG path string, rectangles compare by
45
+ * (x0, y0, x1, y1).
46
+ */
47
+ export declare function shapesEqual(a: any, b: any): boolean;
48
+ /** Returns true if the two bbox-relative masks share at least one set pixel. */
49
+ export declare function masksOverlap(a: BBoxMask, b: BBoxMask): boolean;
50
+ /**
51
+ * Allocate a fresh accumulator covering both masks and OR them in. The
52
+ * resulting mask's bbox is the smallest rectangle containing both inputs.
53
+ */
54
+ export declare function unionMasks(a: BBoxMask, b: BBoxMask): BBoxMask;
55
+ /**
56
+ * Simplify a closed ring with the Douglas–Peucker algorithm (jit-ui#85):
57
+ * drop every vertex that lies within `epsilon` pixels (the "altitude
58
+ * threshold") of the line between its kept neighbours. Anchored at vertex 0
59
+ * (the ring is closed by appending it). Rings of ≤ 3 vertices, or a
60
+ * non-positive epsilon, are returned unchanged. Output keeps the closed-ring
61
+ * convention (no repeated closing point).
62
+ */
63
+ export declare function simplifyRing(xs: number[], ys: number[], epsilon: number): {
64
+ xs: number[];
65
+ ys: number[];
66
+ };
@@ -0,0 +1,132 @@
1
+ import { ShapeSelection } from './shape';
2
+ export declare class Region {
3
+ /** Stable, unique identity for selection and equality. Minted by
4
+ * PlotlyService when a region first enters the system. Never derived
5
+ * from array index — name collisions across delete/add cycles must
6
+ * not break PrimeNG row selection. */
7
+ id: number;
8
+ name: string;
9
+ bounds?: Rectangle | Polygon | MultiPolygon | null;
10
+ /** profile = an intensity-profile line ROI; rendered/dragged like a region but
11
+ * excluded from the Regions tab and exports. Use `isProfile()` to test it —
12
+ * it's the canonical marker that separates intensity lines (owned by the
13
+ * intensity tool, sampled into the inset) from annotation regions (owned by
14
+ * the Region Editor). Both backends (Plotly, OSD) honour it. */
15
+ kind?: 'profile';
16
+ color?: string;
17
+ label?: string;
18
+ /** True when the user set this region's colour explicitly (Region Editor Color
19
+ * column). Preset colour resolution (jit-ui#70) skips overridden regions so a
20
+ * manual colour is not clobbered when presets are (re)applied on load/import. */
21
+ colorOverridden?: boolean;
22
+ filename?: string;
23
+ /** Zero-based z-slice this region belongs to within a stack — mirrors
24
+ * QuPath's `geometry.plane.z` (a missing plane / default plane reads back as
25
+ * 0). Used to place/filter ROIs per slice; 0 for a plain single-plane image
26
+ * or a region drawn without a slice context (jit-ui#93). */
27
+ z: number;
28
+ shapeColor?: string | undefined;
29
+ bytesPerPixel: number;
30
+ /**
31
+ * resolution is the resolution at which the region
32
+ * was found. In order to get it in the full image
33
+ * coordinates it will normally be 0. However if
34
+ * there is a mistake with the resolution it may not
35
+ * be. We return the resolution here in order to be
36
+ * sure what it is. The server may need to be changed
37
+ * to ensure that results regions are always returned
38
+ * at resolution = 0
39
+ */
40
+ resolution: number;
41
+ cropped: boolean;
42
+ tileNumber: number;
43
+ tileCoordinates: number[] | null;
44
+ /** True for intensity-profile line ROIs (the intensity tool's lines). These are
45
+ * NOT annotation regions: they never appear in the Region Editor and editor
46
+ * operations (select/save/delete) must never touch them. */
47
+ isProfile(): boolean;
48
+ toString(): string;
49
+ /**
50
+ * Returns a ShapeSelection object that can be used to
51
+ * create a shape in Plotly.
52
+ * @param showRegionLabel
53
+ * @return ShapeSelection
54
+ */
55
+ getShape(showRegionLabel?: boolean): ShapeSelection;
56
+ isRectangle(bnds: any): bnds is Rectangle;
57
+ isPolygon(bnds: any): bnds is Polygon;
58
+ }
59
+ export declare class Rectangle {
60
+ x: number;
61
+ y: number;
62
+ width: number;
63
+ height: number;
64
+ }
65
+ export declare class Polygon {
66
+ npoints: number;
67
+ xpoints: number[];
68
+ ypoints: number[];
69
+ coordinates: number[][];
70
+ /** false for open polylines; true (default) for closed polygons */
71
+ closed: boolean;
72
+ /**
73
+ * When true the vertices are treated as bezier-spline **anchors** and the
74
+ * region is rendered/exported as a smooth curve through them. The vertices
75
+ * stay the editable anchors — toggling this flag is the toBezier
76
+ * (`true`) / toPolygon (`false`), which only add/remove the curve, never move
77
+ * the anchors. GeoJSON keeps the flattened curve as the geometry (so QuPath
78
+ * renders it) plus the anchors + handles + flag in properties (so JIT
79
+ * round-trips the editable bezier).
80
+ */
81
+ bezier: boolean;
82
+ /**
83
+ * Per-anchor cubic-bezier control-point offsets, **relative** to their anchor
84
+ * (so they translate with it). Present only for bezier regions; initialised
85
+ * from the Catmull-Rom construction (a smooth curve) when bezier is turned on,
86
+ * then individually editable by dragging the handles. `handlesIn[i]` /
87
+ * `handlesOut[i]` are `[dx, dy]` for vertex `i`.
88
+ */
89
+ handlesIn?: number[][];
90
+ handlesOut?: number[][];
91
+ /**
92
+ * Interior rings (holes) — jit-ui#85. Each ring is a list of `[x, y]`
93
+ * image-pixel pairs in the SAME closed-polygon convention as the exterior
94
+ * (`coordinates`): no repeated closing point. Present only on closed polygons.
95
+ * A point inside the exterior **and** inside any hole is OUTSIDE the region
96
+ * (even-odd rule). Absent/empty == a solid polygon (the prior behaviour), so
97
+ * every existing region is unaffected.
98
+ */
99
+ holes?: number[][][];
100
+ /**
101
+ * Per-hole bézier control-point offsets, parallel to {@link holes} (one entry per ring, each a
102
+ * list of `[dx, dy]` per ring vertex, **relative** to the vertex). Present only when `bezier` is
103
+ * on for a donut — seeded from the Catmull-Rom default and individually editable, exactly like
104
+ * the exterior {@link handlesIn}/{@link handlesOut}. So a donut smoothed to a bézier curves its
105
+ * holes too (jit-ui#102).
106
+ */
107
+ holeHandlesIn?: number[][][];
108
+ holeHandlesOut?: number[][][];
109
+ }
110
+ /**
111
+ * A region whose geometry is several disjoint parts — e.g. the result of merging
112
+ * two non-touching regions, or the inverse of a blob (jit-ui#85). Each part is a
113
+ * closed {@link Polygon} that may carry its own holes, so a MultiPolygon
114
+ * represents "sparse bits, some with donut holes" as a single region. Maps 1:1
115
+ * onto a GeoJSON `MultiPolygon` (and QuPath's geometry).
116
+ *
117
+ * A single-part MultiPolygon is equivalent to that Polygon; callers should
118
+ * prefer a plain {@link Polygon} for one connected part.
119
+ */
120
+ export declare class MultiPolygon {
121
+ /** One or more disjoint closed polygons (each may have holes). */
122
+ polygons: Polygon[];
123
+ }
124
+ export type Bounds = Rectangle | Polygon | {
125
+ x?: number;
126
+ y?: number;
127
+ width?: number;
128
+ height?: number;
129
+ npoints?: number;
130
+ xpoints?: number[];
131
+ ypoints?: number[];
132
+ };
@@ -0,0 +1,44 @@
1
+ import { Region } from './region';
2
+ import { Datum, Font, Shape, ShapeLabel, ShapeLine, XAxisName, YAxisName } from 'plotly.js-dist-min';
3
+ export declare class ShapeSelection implements Shape {
4
+ /** Stable, unique identity carried alongside the shape so it round-trips
5
+ * through Plotly's relayout untouched. Plotly preserves unknown
6
+ * properties on shape objects, so this survives the same way `legend`
7
+ * and `fileName` already do. */
8
+ id: number;
9
+ name: string;
10
+ fillcolor: string;
11
+ label: Partial<ShapeLabel>;
12
+ layer: 'below' | 'above';
13
+ legendgroup: string;
14
+ legendgrouptitle: {
15
+ text: string;
16
+ font?: Partial<Font>;
17
+ };
18
+ legendrank: number;
19
+ line: Partial<ShapeLine>;
20
+ opacity: number;
21
+ path: string;
22
+ showlegend: boolean;
23
+ templateitemname: string;
24
+ type: 'rect' | 'circle' | 'line' | 'path';
25
+ visible: boolean | 'legendonly';
26
+ x0: Datum;
27
+ x1: Datum;
28
+ xanchor: number | string;
29
+ xref: 'paper' | XAxisName;
30
+ xsizemode: 'scaled' | 'pixel';
31
+ y0: Datum;
32
+ y1: Datum;
33
+ yanchor: number | string;
34
+ yref: 'paper' | YAxisName;
35
+ ysizemode: 'scaled' | 'pixel';
36
+ editable: boolean;
37
+ legend: any;
38
+ fileName: string | undefined;
39
+ kind?: 'profile';
40
+ /**
41
+ * Returns a Region object based on the shape type.
42
+ */
43
+ getRegion(): Region;
44
+ }
@@ -0,0 +1,107 @@
1
+ import { Rectangle, Region } from './models/region';
2
+ import { ShapeSelection } from './models/shape';
3
+ export declare const COLORMAP_OPTIONS: {
4
+ label: string;
5
+ data: null;
6
+ children: {
7
+ label: string;
8
+ data: {
9
+ value: string;
10
+ src: string;
11
+ };
12
+ }[];
13
+ }[];
14
+ export declare const CONFIG: {
15
+ displaylogo: boolean;
16
+ responsive: boolean;
17
+ displayModeBar: boolean;
18
+ scrollZoom: boolean;
19
+ };
20
+ export declare const CONFIG_SURFACE: {
21
+ displaylogo: boolean;
22
+ responsive: boolean;
23
+ displayModeBar: boolean;
24
+ scrollZoom: boolean;
25
+ };
26
+ export declare class PlotUtilities {
27
+ /**
28
+ * Rounds all the point coordinates of a path ('M13.54,54.566L35.44,33.3L36.22,89.6Z')
29
+ * becomes 'M14,55L35,33L36,90Z'
30
+ * @param path
31
+ */
32
+ roundPathCoordinates(path: string): string;
33
+ /**
34
+ * Transform a 1d array into a matrix given a given width
35
+ * @param array Uint8Array
36
+ * @param elementsPerSubArray
37
+ */
38
+ arrayToMatrix(array: any[] | Uint8Array, elementsPerSubArray: number): any[];
39
+ /**
40
+ * coordinates are of the bottom left and upper right corners of the rectangle, The coordinates
41
+ * are taken given a yAxis that is up side down (as for all images). If Zoom is out of the image boundary,
42
+ * it will return the image size coordinates for the new rectangle.
43
+ * @param coordinates plotly coordinates ([Xaxis.range[0], xAxis.range[1], yAxis.range[0], yaxis.range[1]])
44
+ * @param trueImageSize true image size [0, x, 0, y]
45
+ */
46
+ getRectangle(coordinates: number[], trueImageSize: number[]): Rectangle;
47
+ /**
48
+ * given a dom object (found by id), return a Rectangle of the bounding element.
49
+ * @param div
50
+ */
51
+ getDomRectangle(div: string): Rectangle;
52
+ /**
53
+ * snap region to closest pixel in the coordinate (round the coordinates of the region)
54
+ * @param shape
55
+ * @private
56
+ */
57
+ snapRegion(shape: ShapeSelection): ShapeSelection;
58
+ /**
59
+ * Given a figure (path or rectangle), returns a polygon
60
+ * @param fig
61
+ */
62
+ getPolygon(fig: any): any;
63
+ /**
64
+ * TESTED
65
+ * Rounds a list of numbers
66
+ * @param a
67
+ */
68
+ round(a: number[]): number[];
69
+ /**
70
+ * TESTED
71
+ * Returns true of zoom is the same as image size
72
+ * @param rect Rectangle area
73
+ * @param trueImgSize
74
+ * @return true if rect is out of image size boundary
75
+ */
76
+ isZoomSameAsImgSize(rect: Rectangle, trueImgSize: number[]): boolean;
77
+ /**
78
+ * Save the json string to a file
79
+ * @param jsonString
80
+ */
81
+ saveToFile(jsonString: any, baseName?: string): void;
82
+ /**
83
+ * Function that imports ROIs from a geojson object
84
+ * @param geoJsonStr
85
+ * @return Region[]
86
+ */
87
+ importROIsFromGeoJson(geoJsonStr: string): Region[];
88
+ /**
89
+ * Function that returns a geojson object from a Plotly ROI
90
+ * @param rois
91
+ * @return FeatureCollection<Geometry, GeoJsonProperties>
92
+ */
93
+ exportROIsToGeoJson(rois: Region[]): string;
94
+ /**
95
+ * Convert GeoJSON interior rings into the neutral hole representation
96
+ * (`number[][]` per ring, no repeated closing point). Degenerate rings (< 3
97
+ * distinct points) are dropped. jit-ui#85.
98
+ */
99
+ /**
100
+ * Build a closed {@link Polygon} from a GeoJSON ring set: `rings[0]` is the
101
+ * exterior (closing point dropped), `rings[1..]` are interior holes. jit-ui#85.
102
+ */
103
+ private polygonFromRings;
104
+ private ringsToHoles;
105
+ rgbToHex(r: number, g: number, b: number): string;
106
+ hexToRgb(hex: string | undefined): number[];
107
+ }
@@ -0,0 +1,28 @@
1
+ import { ProcessingImage } from './processing-image';
2
+ import * as i0 from "@angular/core";
3
+ /**
4
+ * Converts between various image representations. Bridges image-js, browser
5
+ * canvas/image elements, and the neutral {@link ProcessingImage}. Generic image
6
+ * plumbing — no app/pipeline coupling.
7
+ */
8
+ export declare class ImageConverterService {
9
+ /**
10
+ * Convert an image-js Image instance to ProcessingImage.
11
+ * image-js stores pixel data in a typed array with shape (width*height*channels).
12
+ */
13
+ fromImageJs(image: any): ProcessingImage;
14
+ /** Convert from an HTMLCanvasElement. */
15
+ fromCanvas(canvas: HTMLCanvasElement): ProcessingImage;
16
+ /** Convert from an HTMLImageElement. */
17
+ fromHtmlImage(img: HTMLImageElement): ProcessingImage;
18
+ /** Convert ProcessingImage to a 2D array suitable for Plotly heatmap (grayscale). */
19
+ toPlotlyHeatmapZ(image: ProcessingImage): number[][];
20
+ /** Convert ProcessingImage to Plotly RGB arrays [r[][], g[][], b[][]]. */
21
+ toPlotlyRgbArrays(image: ProcessingImage): {
22
+ r: number[][];
23
+ g: number[][];
24
+ b: number[][];
25
+ };
26
+ static ɵfac: i0.ɵɵFactoryDeclaration<ImageConverterService, never>;
27
+ static ɵprov: i0.ɵɵInjectableDeclaration<ImageConverterService>;
28
+ }
@@ -0,0 +1,18 @@
1
+ import { ProcessingImage } from './processing-image';
2
+ /** Crop options in source-image pixels. Out-of-range values are clamped. */
3
+ export interface CropImageOptions {
4
+ x?: number;
5
+ y?: number;
6
+ width?: number;
7
+ height?: number;
8
+ /** Power-of-two downsample level applied to the crop (0 = full resolution). */
9
+ level?: number;
10
+ }
11
+ /**
12
+ * Crop a rectangular region out of a {@link ProcessingImage} (browser-side, the
13
+ * counterpart of the JIT server's Slide Crop), optionally downsampling the crop
14
+ * by `2^level`. The rectangle is in source pixels and clamped to the image, so
15
+ * out-of-range values snap to the valid region rather than throwing. Always
16
+ * returns a 4-channel (RGBA) image.
17
+ */
18
+ export declare function cropImage(image: ProcessingImage, opts?: CropImageOptions): ProcessingImage;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Unified image container used throughout the processing pipeline.
3
+ * Decouples pipeline logic from any specific library's image format.
4
+ */
5
+ export declare class ProcessingImage {
6
+ readonly width: number;
7
+ readonly height: number;
8
+ readonly channels: number;
9
+ readonly data: Uint8ClampedArray;
10
+ /** Create from browser ImageData. */
11
+ static fromImageData(imageData: ImageData): ProcessingImage;
12
+ constructor(width: number, height: number, channels: number, data: Uint8ClampedArray);
13
+ /** Convert to browser-native ImageData (RGBA). */
14
+ toImageData(): ImageData;
15
+ /** Convert to Blob for saving/downloading. */
16
+ toBlob(mime?: string): Promise<Blob>;
17
+ }
@@ -0,0 +1,34 @@
1
+ import { Provider } from '@angular/core';
2
+ /**
3
+ * A self-contained, isolated visualization backend chain for a component subtree.
4
+ *
5
+ * The chain services are `providedIn: 'root'` singletons, so by default the whole
6
+ * app shares one viewer's state (regions, image, channels, render handles) — which
7
+ * is correct for the single main viewer. A consumer that needs a SECOND, independent
8
+ * viewer (e.g. a modal that mounts `<visualizer>` over the live main view
9
+ * and must not clobber its regions/image) drops this into its component `providers`:
10
+ *
11
+ * ```ts
12
+ * @Component({
13
+ * ...,
14
+ * providers: [
15
+ * ...provideVisualization(), // isolated chain instance
16
+ * // plus the host ports + config for THIS viewer:
17
+ * { provide: IMAGE_STATE_PORT, useClass: MyImageStateAdapter },
18
+ * { provide: TILE_ACCESS_PORT, useClass: MyTileAccessAdapter },
19
+ * { provide: REGION_IO_PORT, useClass: MyRegionIoAdapter },
20
+ * { provide: VIZ_CONFIG, useValue: { slideCropServer: '' } },
21
+ * ],
22
+ * })
23
+ * ```
24
+ *
25
+ * Component-scoped providers shadow the root singletons for that subtree, so the
26
+ * embedded viewer gets its own router/Plotly/OSD/stores/tools while the rest of the
27
+ * app keeps the default root instance.
28
+ *
29
+ * Lists EVERY stateful service in the chain. Stateless collaborators (HttpClient,
30
+ * MessageService, WandService) deliberately resolve to root — they hold no
31
+ * per-viewer state, so sharing them is correct and keeps this list minimal. When a
32
+ * new stateful service joins the rendering chain, add it here too.
33
+ */
34
+ export declare function provideVisualization(): Provider[];
@@ -0,0 +1,61 @@
1
+ import { Region } from '../models/region';
2
+ /** A single closed ring (+ optional holes) in image-pixel coordinates. A region
3
+ * rasterizes as the union of its parts. Plain data so it survives a
4
+ * `postMessage` structured clone into the mask worker. */
5
+ export interface MaskPart {
6
+ xpoints: number[];
7
+ ypoints: number[];
8
+ holes?: number[][][];
9
+ }
10
+ /** A bbox-relative binary mask, as returned by `WandService.rasterizePolygon`. */
11
+ export interface BBoxMask {
12
+ bx: number;
13
+ by: number;
14
+ bw: number;
15
+ bh: number;
16
+ mask: Uint8Array;
17
+ }
18
+ /** Polygon-fill function (the wand's scanline rasterizer), injected so this
19
+ * module stays free of Angular/DOM and can run inside a worker. */
20
+ export type RasterizeFn = (xpoints: number[], ypoints: number[], imageWidth: number, imageHeight: number, holes?: number[][][]) => BBoxMask | null;
21
+ /**
22
+ * The largest mask we will allocate, in pixels. A single-channel 8-bit mask is
23
+ * one byte per pixel, so this is also its byte size. Whole-slide level-0 images
24
+ * (e.g. 119040×90112 ≈ 1.07e10 px) blow past both the JS typed-array length cap
25
+ * (~4.29e9) and available memory, so masks for images larger than this are
26
+ * rasterized at a proportionally downscaled resolution. ~100 MP ≈ 100 MB.
27
+ */
28
+ export declare const MAX_MASK_PIXELS = 100000000;
29
+ /** Downscale factor (≤ 1) to keep `width * height` within {@link MAX_MASK_PIXELS}.
30
+ * 1 when the image already fits. */
31
+ export declare function maskScaleFor(width: number, height: number): number;
32
+ /** Multiply every coordinate (and hole coordinate) of a region's parts by
33
+ * `scale`, for rasterizing into a downscaled mask. Returns the parts unchanged
34
+ * when `scale` is 1. */
35
+ export declare function scaleParts(parts: MaskPart[], scale: number): MaskPart[];
36
+ /** Flatten a region's geometry to plain rings. Rectangles become a 4-point ring;
37
+ * polygons keep their points + holes; multi-polygons expand to one part each. */
38
+ export declare function regionToParts(region: Region): MaskPart[];
39
+ /** A rasterized label mask plus the PNG bit depth it should be encoded at. */
40
+ export interface LabelMask {
41
+ data: Uint8Array | Uint16Array;
42
+ /** 8 for ≤255 distinct values, 16 for a multi-class mask with >255 regions. */
43
+ bitDepth: 8 | 16;
44
+ }
45
+ /**
46
+ * Rasterize regions (as plain parts) to a full image-size label mask (row-major,
47
+ * `W * H` samples; pixel `(x, y)` at `y * W + x`). Background is 0.
48
+ *
49
+ * - `'binary'` — every region pixel is 255 (standard 8-bit black/white mask:
50
+ * `> 0` = foreground; also directly viewable).
51
+ * - `'multiclass'` — each region gets a distinct 1-based id (its index + 1).
52
+ * Stays 8-bit for ≤255 regions; promotes to 16-bit beyond that. Ids are
53
+ * distinct up to the 16-bit ceiling (65535 regions); a selection larger than
54
+ * that exceeds the PNG's representable range and ids wrap (not a realistic
55
+ * hand-annotation case, but called out so the limit is explicit).
56
+ *
57
+ * Later regions paint over earlier ones where they overlap. `onProgress` is
58
+ * called after each region (1-based) so a caller can drive a progress bar.
59
+ * Returns null when nothing rasterises (no regions, zero/insane size).
60
+ */
61
+ export declare function regionsToMask(regions: MaskPart[][], imageWidth: number, imageHeight: number, mode: 'binary' | 'multiclass', rasterize: RasterizeFn, onProgress?: (done: number, total: number) => void): LabelMask | null;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Factory for the mask-export Web Worker, isolated in its own module so the
3
+ * `import.meta.url` reference (required by the bundler to locate the worker) is
4
+ * never pulled into the ts-jest CommonJS compile of the component — the unit
5
+ * tests `jest.mock` this module instead.
6
+ */
7
+ export declare function createMaskWorker(): Worker;