copper3d 3.0.1 → 3.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.
- package/README.md +197 -875
- package/dist/Utils/segmentation/CanvasState.d.ts +31 -0
- package/dist/Utils/segmentation/CanvasState.js +167 -0
- package/dist/Utils/segmentation/CanvasState.js.map +1 -0
- package/dist/Utils/segmentation/DragOperator.d.ts +10 -2
- package/dist/Utils/segmentation/DragOperator.js +16 -8
- package/dist/Utils/segmentation/DragOperator.js.map +1 -1
- package/dist/Utils/segmentation/DrawToolCore.d.ts +64 -35
- package/dist/Utils/segmentation/DrawToolCore.js +332 -584
- package/dist/Utils/segmentation/DrawToolCore.js.map +1 -1
- package/dist/Utils/segmentation/NrrdTools.d.ts +117 -353
- package/dist/Utils/segmentation/NrrdTools.js +622 -1081
- package/dist/Utils/segmentation/NrrdTools.js.map +1 -1
- package/dist/Utils/segmentation/RenderingUtils.d.ts +73 -0
- package/dist/Utils/segmentation/RenderingUtils.js +180 -0
- package/dist/Utils/segmentation/RenderingUtils.js.map +1 -0
- package/dist/Utils/segmentation/core/MaskVolume.js +23 -2
- package/dist/Utils/segmentation/core/MaskVolume.js.map +1 -1
- package/dist/Utils/segmentation/core/UndoManager.d.ts +1 -1
- package/dist/Utils/segmentation/core/UndoManager.js +1 -1
- package/dist/Utils/segmentation/core/index.d.ts +1 -3
- package/dist/Utils/segmentation/core/index.js +0 -1
- package/dist/Utils/segmentation/core/index.js.map +1 -1
- package/dist/Utils/segmentation/core/types.d.ts +384 -0
- package/dist/Utils/segmentation/core/types.js +25 -24
- package/dist/Utils/segmentation/core/types.js.map +1 -1
- package/dist/Utils/segmentation/coreTools/GuiState.d.ts +22 -0
- package/dist/Utils/segmentation/coreTools/GuiState.js +48 -0
- package/dist/Utils/segmentation/coreTools/GuiState.js.map +1 -0
- package/dist/Utils/segmentation/coreTools/NrrdState.d.ts +25 -0
- package/dist/Utils/segmentation/coreTools/NrrdState.js +85 -0
- package/dist/Utils/segmentation/coreTools/NrrdState.js.map +1 -0
- package/dist/Utils/segmentation/coreTools/divControlTools.d.ts +1 -1
- package/dist/Utils/segmentation/coreTools/divControlTools.js +1 -1
- package/dist/Utils/segmentation/coreTools/divControlTools.js.map +1 -1
- package/dist/Utils/segmentation/coreTools/gui.d.ts +12 -12
- package/dist/Utils/segmentation/coreTools/gui.js +81 -107
- package/dist/Utils/segmentation/coreTools/gui.js.map +1 -1
- package/dist/Utils/segmentation/eventRouter/EventRouter.d.ts +2 -1
- package/dist/Utils/segmentation/eventRouter/EventRouter.js +15 -10
- package/dist/Utils/segmentation/eventRouter/EventRouter.js.map +1 -1
- package/dist/Utils/segmentation/eventRouter/types.d.ts +3 -3
- package/dist/Utils/segmentation/tools/BaseTool.d.ts +8 -5
- package/dist/Utils/segmentation/tools/BaseTool.js +1 -2
- package/dist/Utils/segmentation/tools/BaseTool.js.map +1 -1
- package/dist/Utils/segmentation/tools/ContrastTool.d.ts +3 -6
- package/dist/Utils/segmentation/tools/ContrastTool.js.map +1 -1
- package/dist/Utils/segmentation/tools/CrosshairTool.d.ts +11 -1
- package/dist/Utils/segmentation/tools/CrosshairTool.js +50 -25
- package/dist/Utils/segmentation/tools/CrosshairTool.js.map +1 -1
- package/dist/Utils/segmentation/tools/DataLoader.d.ts +33 -0
- package/dist/Utils/segmentation/tools/DataLoader.js +159 -0
- package/dist/Utils/segmentation/tools/DataLoader.js.map +1 -0
- package/dist/Utils/segmentation/tools/DragSliceTool.d.ts +3 -10
- package/dist/Utils/segmentation/tools/DragSliceTool.js +63 -53
- package/dist/Utils/segmentation/tools/DragSliceTool.js.map +1 -1
- package/dist/Utils/segmentation/tools/DrawingTool.d.ts +85 -0
- package/dist/Utils/segmentation/tools/DrawingTool.js +270 -0
- package/dist/Utils/segmentation/tools/DrawingTool.js.map +1 -0
- package/dist/Utils/segmentation/tools/EraserTool.js +8 -8
- package/dist/Utils/segmentation/tools/EraserTool.js.map +1 -1
- package/dist/Utils/segmentation/tools/ImageStoreHelper.d.ts +13 -33
- package/dist/Utils/segmentation/tools/ImageStoreHelper.js +39 -82
- package/dist/Utils/segmentation/tools/ImageStoreHelper.js.map +1 -1
- package/dist/Utils/segmentation/tools/LayerChannelManager.d.ts +52 -0
- package/dist/Utils/segmentation/tools/LayerChannelManager.js +175 -0
- package/dist/Utils/segmentation/tools/LayerChannelManager.js.map +1 -0
- package/dist/Utils/segmentation/tools/PanTool.d.ts +47 -0
- package/dist/Utils/segmentation/tools/PanTool.js +90 -0
- package/dist/Utils/segmentation/tools/PanTool.js.map +1 -0
- package/dist/Utils/segmentation/tools/SliceRenderPipeline.d.ts +80 -0
- package/dist/Utils/segmentation/tools/SliceRenderPipeline.js +355 -0
- package/dist/Utils/segmentation/tools/SliceRenderPipeline.js.map +1 -0
- package/dist/Utils/segmentation/tools/SphereTool.d.ts +223 -10
- package/dist/Utils/segmentation/tools/SphereTool.js +512 -47
- package/dist/Utils/segmentation/tools/SphereTool.js.map +1 -1
- package/dist/Utils/segmentation/tools/ToolHost.d.ts +74 -0
- package/dist/Utils/segmentation/tools/ToolHost.js +10 -0
- package/dist/Utils/segmentation/tools/ToolHost.js.map +1 -0
- package/dist/Utils/segmentation/tools/ZoomTool.d.ts +2 -6
- package/dist/Utils/segmentation/tools/ZoomTool.js +3 -3
- package/dist/Utils/segmentation/tools/ZoomTool.js.map +1 -1
- package/dist/Utils/segmentation/tools/index.d.ts +8 -6
- package/dist/Utils/segmentation/tools/index.js +10 -1
- package/dist/Utils/segmentation/tools/index.js.map +1 -1
- package/dist/Utils/workers/reformatSaveDataWorker.d.ts +1 -1
- package/dist/bundle.esm.js +3729 -3017
- package/dist/bundle.umd.js +3729 -3017
- package/dist/index.d.ts +6 -3
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/types/Utils/segmentation/CanvasState.d.ts +31 -0
- package/dist/types/Utils/segmentation/DragOperator.d.ts +10 -2
- package/dist/types/Utils/segmentation/DrawToolCore.d.ts +64 -35
- package/dist/types/Utils/segmentation/NrrdTools.d.ts +117 -353
- package/dist/types/Utils/segmentation/RenderingUtils.d.ts +73 -0
- package/dist/types/Utils/segmentation/core/UndoManager.d.ts +1 -1
- package/dist/types/Utils/segmentation/core/index.d.ts +1 -3
- package/dist/types/Utils/segmentation/core/types.d.ts +384 -0
- package/dist/types/Utils/segmentation/coreTools/GuiState.d.ts +22 -0
- package/dist/types/Utils/segmentation/coreTools/NrrdState.d.ts +25 -0
- package/dist/types/Utils/segmentation/coreTools/divControlTools.d.ts +1 -1
- package/dist/types/Utils/segmentation/coreTools/gui.d.ts +12 -12
- package/dist/types/Utils/segmentation/eventRouter/EventRouter.d.ts +2 -1
- package/dist/types/Utils/segmentation/eventRouter/types.d.ts +3 -3
- package/dist/types/Utils/segmentation/tools/BaseTool.d.ts +8 -5
- package/dist/types/Utils/segmentation/tools/ContrastTool.d.ts +3 -6
- package/dist/types/Utils/segmentation/tools/CrosshairTool.d.ts +11 -1
- package/dist/types/Utils/segmentation/tools/DataLoader.d.ts +33 -0
- package/dist/types/Utils/segmentation/tools/DragSliceTool.d.ts +3 -10
- package/dist/types/Utils/segmentation/tools/DrawingTool.d.ts +85 -0
- package/dist/types/Utils/segmentation/tools/ImageStoreHelper.d.ts +13 -33
- package/dist/types/Utils/segmentation/tools/LayerChannelManager.d.ts +52 -0
- package/dist/types/Utils/segmentation/tools/PanTool.d.ts +47 -0
- package/dist/types/Utils/segmentation/tools/SliceRenderPipeline.d.ts +80 -0
- package/dist/types/Utils/segmentation/tools/SphereTool.d.ts +223 -10
- package/dist/types/Utils/segmentation/tools/ToolHost.d.ts +74 -0
- package/dist/types/Utils/segmentation/tools/ZoomTool.d.ts +2 -6
- package/dist/types/Utils/segmentation/tools/index.d.ts +8 -6
- package/dist/types/Utils/workers/reformatSaveDataWorker.d.ts +1 -1
- package/dist/types/index.d.ts +6 -3
- package/package.json +1 -1
- package/dist/Utils/segmentation/CommToolsData.d.ts +0 -177
- package/dist/Utils/segmentation/CommToolsData.js +0 -548
- package/dist/Utils/segmentation/CommToolsData.js.map +0 -1
- package/dist/Utils/segmentation/core/MigrationUtils.d.ts +0 -97
- package/dist/Utils/segmentation/core/MigrationUtils.js +0 -163
- package/dist/Utils/segmentation/core/MigrationUtils.js.map +0 -1
- package/dist/Utils/segmentation/coreTools/coreType.d.ts +0 -363
- package/dist/Utils/segmentation/coreTools/coreType.js +0 -3
- package/dist/Utils/segmentation/coreTools/coreType.js.map +0 -1
- package/dist/types/Utils/segmentation/CommToolsData.d.ts +0 -177
- package/dist/types/Utils/segmentation/core/MigrationUtils.d.ts +0 -97
- package/dist/types/Utils/segmentation/coreTools/coreType.d.ts +0 -363
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EraserTool.js","sourceRoot":"","sources":["../../../../src/Utils/segmentation/tools/EraserTool.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAE9C,MAAM,OAAO,UAAW,SAAQ,QAAQ;IAEtC;;;;;OAKG;IACH,cAAc;QACZ,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAE,CAAS,EAAE,MAAc,EAAE,EAAE;;YACxD,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,aAAa,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"EraserTool.js","sourceRoot":"","sources":["../../../../src/Utils/segmentation/tools/EraserTool.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,19 +2,16 @@
|
|
|
2
2
|
* ImageStoreHelper - Cross-axis image storage
|
|
3
3
|
*
|
|
4
4
|
* Extracted from DrawToolCore.ts:
|
|
5
|
-
* -
|
|
5
|
+
* - syncLayerSliceData
|
|
6
6
|
*
|
|
7
7
|
* Phase 3: MaskVolume is the sole storage backend. All IPaintImages params removed.
|
|
8
8
|
*/
|
|
9
9
|
import { BaseTool } from "./BaseTool";
|
|
10
10
|
import type { ToolContext } from "./BaseTool";
|
|
11
|
-
|
|
12
|
-
setEmptyCanvasSize: (axis?: "x" | "y" | "z") => void;
|
|
13
|
-
drawImageOnEmptyImage: (canvas: HTMLCanvasElement) => void;
|
|
14
|
-
}
|
|
11
|
+
import type { ImageStoreHostDeps } from "./ToolHost";
|
|
15
12
|
export declare class ImageStoreHelper extends BaseTool {
|
|
16
13
|
private callbacks;
|
|
17
|
-
constructor(ctx: ToolContext, callbacks:
|
|
14
|
+
constructor(ctx: ToolContext, callbacks: ImageStoreHostDeps);
|
|
18
15
|
/**
|
|
19
16
|
* Get MaskVolume for a specific layer.
|
|
20
17
|
* Delegates to the volumes stored in protectedData.maskData.
|
|
@@ -23,40 +20,23 @@ export declare class ImageStoreHelper extends BaseTool {
|
|
|
23
20
|
* @returns MaskVolume for the given layer, or layer1 as fallback
|
|
24
21
|
*/
|
|
25
22
|
private getVolumeForLayer;
|
|
26
|
-
/**
|
|
27
|
-
* Get MaskVolume for the currently active layer.
|
|
28
|
-
*/
|
|
29
|
-
private getCurrentVolume;
|
|
30
23
|
/**
|
|
31
24
|
* Get the canvas element for a specific layer.
|
|
32
25
|
*/
|
|
33
26
|
private getCanvasForLayer;
|
|
34
27
|
/**
|
|
35
|
-
*
|
|
36
|
-
*/
|
|
37
|
-
storeImageToAxis(_index: number, _imageData: ImageData, _axis?: "x" | "y" | "z"): void;
|
|
38
|
-
/**
|
|
39
|
-
* Retrieve the drawn image for a given axis and slice.
|
|
28
|
+
* Vertically flip an ImageData buffer in-place (swap rows top↔bottom).
|
|
40
29
|
*
|
|
41
|
-
*
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
} | undefined;
|
|
47
|
-
/**
|
|
48
|
-
* Store all layer images for the current slice (cross-axis sync).
|
|
49
|
-
*
|
|
50
|
-
* Phase 2: Also writes into the current layer's MaskVolume.
|
|
51
|
-
*/
|
|
52
|
-
storeAllImages(index: number, layer: string): void;
|
|
53
|
-
/**
|
|
54
|
-
* Store a single layer's canvas data to its MaskVolume.
|
|
55
|
-
* Reads from the individual layer canvas (not master) and uses RGB→channel reverse lookup.
|
|
30
|
+
* Used to compensate for the Z-axis direction reversal between sagittal
|
|
31
|
+
* and coronal views. On coronal, Z runs along the canvas j-axis (vertical),
|
|
32
|
+
* and the display flip (scale(1,-1)) reverses Z relative to sagittal's
|
|
33
|
+
* horizontal Z mapping. This row-swap aligns the Z ordering so that
|
|
34
|
+
* MaskVolume stores data in a consistent coordinate system.
|
|
56
35
|
*/
|
|
57
|
-
|
|
36
|
+
private flipImageDataVertically;
|
|
58
37
|
/**
|
|
59
|
-
*
|
|
38
|
+
* Sync the current layer canvas to its MaskVolume slice and notify the parent
|
|
39
|
+
* via getMask. This is the primary write path after any draw/erase operation.
|
|
60
40
|
*/
|
|
61
|
-
|
|
41
|
+
syncLayerSliceData(index: number, layer: string): void;
|
|
62
42
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* ImageStoreHelper - Cross-axis image storage
|
|
3
3
|
*
|
|
4
4
|
* Extracted from DrawToolCore.ts:
|
|
5
|
-
* -
|
|
5
|
+
* - syncLayerSliceData
|
|
6
6
|
*
|
|
7
7
|
* Phase 3: MaskVolume is the sole storage backend. All IPaintImages params removed.
|
|
8
8
|
*/
|
|
@@ -25,16 +25,10 @@ export class ImageStoreHelper extends BaseTool {
|
|
|
25
25
|
const vol = volumes[layer];
|
|
26
26
|
if (vol)
|
|
27
27
|
return vol;
|
|
28
|
-
const firstLayerId = this.ctx.nrrd_states.layers[0];
|
|
28
|
+
const firstLayerId = this.ctx.nrrd_states.image.layers[0];
|
|
29
29
|
console.warn(`ImageStoreHelper: unknown layer "${layer}", falling back to "${firstLayerId}"`);
|
|
30
30
|
return volumes[firstLayerId];
|
|
31
31
|
}
|
|
32
|
-
/**
|
|
33
|
-
* Get MaskVolume for the currently active layer.
|
|
34
|
-
*/
|
|
35
|
-
getCurrentVolume() {
|
|
36
|
-
return this.getVolumeForLayer(this.ctx.gui_states.layer);
|
|
37
|
-
}
|
|
38
32
|
/**
|
|
39
33
|
* Get the canvas element for a specific layer.
|
|
40
34
|
*/
|
|
@@ -44,76 +38,74 @@ export class ImageStoreHelper extends BaseTool {
|
|
|
44
38
|
return target.canvas;
|
|
45
39
|
return this.ctx.protectedData.canvases.drawingCanvasLayerMaster;
|
|
46
40
|
}
|
|
47
|
-
// =====
|
|
41
|
+
// ===== ImageData Flip Helpers =====
|
|
48
42
|
/**
|
|
49
|
-
*
|
|
50
|
-
*/
|
|
51
|
-
storeImageToAxis(_index, _imageData, _axis) {
|
|
52
|
-
// No-op: MaskVolume is the primary storage, updated in storeAllImages
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Retrieve the drawn image for a given axis and slice.
|
|
43
|
+
* Vertically flip an ImageData buffer in-place (swap rows top↔bottom).
|
|
56
44
|
*
|
|
57
|
-
*
|
|
45
|
+
* Used to compensate for the Z-axis direction reversal between sagittal
|
|
46
|
+
* and coronal views. On coronal, Z runs along the canvas j-axis (vertical),
|
|
47
|
+
* and the display flip (scale(1,-1)) reverses Z relative to sagittal's
|
|
48
|
+
* horizontal Z mapping. This row-swap aligns the Z ordering so that
|
|
49
|
+
* MaskVolume stores data in a consistent coordinate system.
|
|
58
50
|
*/
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
volume.renderLabelSliceInto(sliceIndex, axis, imageData, channelVis);
|
|
71
|
-
return { index: sliceIndex, image: imageData };
|
|
72
|
-
}
|
|
51
|
+
flipImageDataVertically(imageData) {
|
|
52
|
+
const { width, height, data } = imageData;
|
|
53
|
+
const rowSize = width * 4; // RGBA = 4 bytes per pixel
|
|
54
|
+
const temp = new Uint8ClampedArray(rowSize);
|
|
55
|
+
for (let y = 0; y < Math.floor(height / 2); y++) {
|
|
56
|
+
const topOffset = y * rowSize;
|
|
57
|
+
const bottomOffset = (height - 1 - y) * rowSize;
|
|
58
|
+
// Swap top row and bottom row
|
|
59
|
+
temp.set(data.subarray(topOffset, topOffset + rowSize));
|
|
60
|
+
data.copyWithin(topOffset, bottomOffset, bottomOffset + rowSize);
|
|
61
|
+
data.set(temp, bottomOffset);
|
|
73
62
|
}
|
|
74
|
-
catch (err) {
|
|
75
|
-
console.warn(`filterDrawedImage: Failed to read slice ${sliceIndex} on ${axis}:`, err);
|
|
76
|
-
}
|
|
77
|
-
return undefined;
|
|
78
63
|
}
|
|
79
|
-
// =====
|
|
64
|
+
// ===== Sync Layer Slice Data =====
|
|
80
65
|
/**
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
* Phase 2: Also writes into the current layer's MaskVolume.
|
|
66
|
+
* Sync the current layer canvas to its MaskVolume slice and notify the parent
|
|
67
|
+
* via getMask. This is the primary write path after any draw/erase operation.
|
|
84
68
|
*/
|
|
85
|
-
|
|
69
|
+
syncLayerSliceData(index, layer) {
|
|
86
70
|
const nrrd = this.ctx.nrrd_states;
|
|
87
71
|
// Read from the individual layer canvas (NOT master) to preserve layer isolation
|
|
88
72
|
const layerCanvas = this.getCanvasForLayer(layer);
|
|
89
|
-
if (!nrrd.
|
|
73
|
+
if (!nrrd.flags.loadingMaskData && !this.ctx.gui_states.mode.sphere) {
|
|
90
74
|
this.callbacks.setEmptyCanvasSize();
|
|
91
75
|
this.callbacks.drawImageOnEmptyImage(layerCanvas);
|
|
92
76
|
}
|
|
93
77
|
const imageData = this.ctx.protectedData.ctxes.emptyCtx.getImageData(0, 0, this.ctx.protectedData.canvases.emptyCanvas.width, this.ctx.protectedData.canvases.emptyCanvas.height);
|
|
78
|
+
// Coronal (axis='y') Z-flip: the Z dimension runs vertically on coronal
|
|
79
|
+
// but horizontally on sagittal, with opposite screen directions.
|
|
80
|
+
// Flip ImageData vertically before writing to MaskVolume so that
|
|
81
|
+
// cross-view rendering (sagittal↔coronal) is consistent.
|
|
82
|
+
// Same pattern as SphereTool.canvasToVoxelCenter('y') Z-flip.
|
|
83
|
+
if (this.ctx.protectedData.axis === 'y') {
|
|
84
|
+
this.flipImageDataVertically(imageData);
|
|
85
|
+
}
|
|
94
86
|
// Write label data into 1-channel MaskVolume with RGB→channel reverse lookup
|
|
95
87
|
try {
|
|
96
88
|
const volume = this.getVolumeForLayer(layer);
|
|
97
89
|
if (volume) {
|
|
98
|
-
const activeChannel = this.ctx.gui_states.activeChannel || 1;
|
|
90
|
+
const activeChannel = this.ctx.gui_states.layerChannel.activeChannel || 1;
|
|
99
91
|
// Phase 4 Fix: Pass channel visibility map to preserve hidden channels
|
|
100
|
-
const channelVis = this.ctx.gui_states.channelVisibility[layer];
|
|
92
|
+
const channelVis = this.ctx.gui_states.layerChannel.channelVisibility[layer];
|
|
101
93
|
volume.setSliceLabelsFromImageData(index, imageData, this.ctx.protectedData.axis, activeChannel, channelVis);
|
|
102
94
|
}
|
|
103
95
|
}
|
|
104
96
|
catch (err) {
|
|
105
97
|
// Volume not ready — skip
|
|
106
98
|
}
|
|
107
|
-
if (!nrrd.
|
|
99
|
+
if (!nrrd.flags.loadingMaskData && !this.ctx.gui_states.mode.sphere) {
|
|
108
100
|
// Extract raw slice data from MaskVolume and notify parent
|
|
109
101
|
try {
|
|
110
102
|
const volume = this.getVolumeForLayer(layer);
|
|
111
103
|
if (volume) {
|
|
112
104
|
const axis = this.ctx.protectedData.axis;
|
|
113
|
-
const sliceIndex = this.ctx.nrrd_states.
|
|
105
|
+
const sliceIndex = this.ctx.nrrd_states.view.currentSliceIndex;
|
|
114
106
|
const { data: sliceData, width, height } = volume.getSliceUint8(sliceIndex, axis);
|
|
115
|
-
const activeChannel = this.ctx.gui_states.activeChannel || 1;
|
|
116
|
-
this.ctx.
|
|
107
|
+
const activeChannel = this.ctx.gui_states.layerChannel.activeChannel || 1;
|
|
108
|
+
this.ctx.callbacks.onMaskChanged(sliceData, layer, activeChannel, sliceIndex, axis, width, height, this.ctx.nrrd_states.flags.clearAllFlag);
|
|
117
109
|
}
|
|
118
110
|
}
|
|
119
111
|
catch (_a) {
|
|
@@ -121,40 +113,5 @@ export class ImageStoreHelper extends BaseTool {
|
|
|
121
113
|
}
|
|
122
114
|
}
|
|
123
115
|
}
|
|
124
|
-
// ===== Store Per-Layer Images =====
|
|
125
|
-
/**
|
|
126
|
-
* Store a single layer's canvas data to its MaskVolume.
|
|
127
|
-
* Reads from the individual layer canvas (not master) and uses RGB→channel reverse lookup.
|
|
128
|
-
*/
|
|
129
|
-
storeEachLayerImage(index, layer) {
|
|
130
|
-
const layerCanvas = this.getCanvasForLayer(layer);
|
|
131
|
-
this.callbacks.setEmptyCanvasSize();
|
|
132
|
-
this.callbacks.drawImageOnEmptyImage(layerCanvas);
|
|
133
|
-
const imageData = this.ctx.protectedData.ctxes.emptyCtx.getImageData(0, 0, this.ctx.protectedData.canvases.emptyCanvas.width, this.ctx.protectedData.canvases.emptyCanvas.height);
|
|
134
|
-
try {
|
|
135
|
-
const volume = this.getVolumeForLayer(layer);
|
|
136
|
-
if (volume) {
|
|
137
|
-
const activeChannel = this.ctx.gui_states.activeChannel || 1;
|
|
138
|
-
// Phase 4 Fix: Pass channel visibility map to preserve hidden channels
|
|
139
|
-
const channelVis = this.ctx.gui_states.channelVisibility[layer];
|
|
140
|
-
volume.setSliceLabelsFromImageData(index, imageData, this.ctx.protectedData.axis, activeChannel, channelVis);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
catch (_a) {
|
|
144
|
-
// Volume not ready — skip
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Extract ImageData from canvas (MaskVolume storage is handled in storeAllImages).
|
|
149
|
-
*/
|
|
150
|
-
storeImageToLayer(_index, canvas) {
|
|
151
|
-
if (!this.ctx.nrrd_states.loadMaskJson) {
|
|
152
|
-
this.callbacks.setEmptyCanvasSize();
|
|
153
|
-
this.callbacks.drawImageOnEmptyImage(canvas);
|
|
154
|
-
}
|
|
155
|
-
const imageData = this.ctx.protectedData.ctxes.emptyCtx.getImageData(0, 0, this.ctx.protectedData.canvases.emptyCanvas.width, this.ctx.protectedData.canvases.emptyCanvas.height);
|
|
156
|
-
// No longer stores to paintedImages - MaskVolume is primary storage
|
|
157
|
-
return imageData;
|
|
158
|
-
}
|
|
159
116
|
}
|
|
160
117
|
//# sourceMappingURL=ImageStoreHelper.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageStoreHelper.js","sourceRoot":"","sources":["../../../../src/Utils/segmentation/tools/ImageStoreHelper.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"ImageStoreHelper.js","sourceRoot":"","sources":["../../../../src/Utils/segmentation/tools/ImageStoreHelper.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { BaseTool } from "./BaseTool";
|
|
2
|
+
import type { ToolContext } from "./BaseTool";
|
|
3
|
+
import type { ChannelValue, RGBAColor, ChannelColorMap } from "../core";
|
|
4
|
+
import type { SphereType } from "./SphereTool";
|
|
5
|
+
import type { LayerChannelHostDeps } from "./ToolHost";
|
|
6
|
+
/**
|
|
7
|
+
* Manages layer/channel state: active selection, visibility, and channel colors.
|
|
8
|
+
*
|
|
9
|
+
* Extracted from NrrdTools.ts to reduce its size.
|
|
10
|
+
* Follows the same BaseTool + ToolContext + Callbacks pattern as other tools.
|
|
11
|
+
*/
|
|
12
|
+
export declare class LayerChannelManager extends BaseTool {
|
|
13
|
+
private callbacks;
|
|
14
|
+
constructor(ctx: ToolContext, callbacks: LayerChannelHostDeps);
|
|
15
|
+
/****************************Active Layer/Channel****************************************************/
|
|
16
|
+
setActiveLayer(layerId: string): void;
|
|
17
|
+
getActiveLayer(): string;
|
|
18
|
+
setActiveChannel(channel: ChannelValue): void;
|
|
19
|
+
getActiveChannel(): number;
|
|
20
|
+
/**
|
|
21
|
+
* Set the active sphere type and sync brush/fill color.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* nrrdTools.setActiveSphereType('nipple');
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
setActiveSphereType(type: SphereType): void;
|
|
29
|
+
getActiveSphereType(): SphereType;
|
|
30
|
+
/****************************Visibility****************************************************/
|
|
31
|
+
setLayerVisible(layerId: string, visible: boolean): void;
|
|
32
|
+
isLayerVisible(layerId: string): boolean;
|
|
33
|
+
setChannelVisible(layerId: string, channel: ChannelValue, visible: boolean): void;
|
|
34
|
+
isChannelVisible(layerId: string, channel: ChannelValue): boolean;
|
|
35
|
+
getLayerVisibility(): Record<string, boolean>;
|
|
36
|
+
getChannelVisibility(): Record<string, Record<number, boolean>>;
|
|
37
|
+
hasLayerData(layerId: string): boolean;
|
|
38
|
+
/****************************Channel Colors****************************************************/
|
|
39
|
+
setChannelColor(layerId: string, channel: number, color: RGBAColor): void;
|
|
40
|
+
getChannelColor(layerId: string, channel: number): RGBAColor;
|
|
41
|
+
getChannelHexColor(layerId: string, channel: number): string;
|
|
42
|
+
getChannelCssColor(layerId: string, channel: number): string;
|
|
43
|
+
setChannelColors(layerId: string, colorMap: Partial<ChannelColorMap>): void;
|
|
44
|
+
setAllLayersChannelColor(channel: number, color: RGBAColor): void;
|
|
45
|
+
resetChannelColors(layerId?: string, channel?: number): void;
|
|
46
|
+
/****************************Private Helpers****************************************************/
|
|
47
|
+
/**
|
|
48
|
+
* Sync brush/fill color from the active layer's volume channel color.
|
|
49
|
+
* Falls back to global CHANNEL_HEX_COLORS if volume not available.
|
|
50
|
+
*/
|
|
51
|
+
private syncBrushColor;
|
|
52
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { BaseTool } from "./BaseTool";
|
|
2
|
+
import { CHANNEL_HEX_COLORS, rgbaToHex, rgbaToCss } from "../core";
|
|
3
|
+
import { SPHERE_CHANNEL_MAP } from "./SphereTool";
|
|
4
|
+
/**
|
|
5
|
+
* Manages layer/channel state: active selection, visibility, and channel colors.
|
|
6
|
+
*
|
|
7
|
+
* Extracted from NrrdTools.ts to reduce its size.
|
|
8
|
+
* Follows the same BaseTool + ToolContext + Callbacks pattern as other tools.
|
|
9
|
+
*/
|
|
10
|
+
export class LayerChannelManager extends BaseTool {
|
|
11
|
+
constructor(ctx, callbacks) {
|
|
12
|
+
super(ctx);
|
|
13
|
+
this.callbacks = callbacks;
|
|
14
|
+
}
|
|
15
|
+
/****************************Active Layer/Channel****************************************************/
|
|
16
|
+
setActiveLayer(layerId) {
|
|
17
|
+
this.ctx.gui_states.layerChannel.layer = layerId;
|
|
18
|
+
this.syncBrushColor();
|
|
19
|
+
}
|
|
20
|
+
getActiveLayer() {
|
|
21
|
+
return this.ctx.gui_states.layerChannel.layer;
|
|
22
|
+
}
|
|
23
|
+
setActiveChannel(channel) {
|
|
24
|
+
this.ctx.gui_states.layerChannel.activeChannel = channel;
|
|
25
|
+
this.syncBrushColor();
|
|
26
|
+
}
|
|
27
|
+
getActiveChannel() {
|
|
28
|
+
return this.ctx.gui_states.layerChannel.activeChannel;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Set the active sphere type and sync brush/fill color.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* nrrdTools.setActiveSphereType('nipple');
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
setActiveSphereType(type) {
|
|
39
|
+
this.ctx.gui_states.mode.activeSphereType = type;
|
|
40
|
+
// Apply color side-effect: update fillColor/brushColor from sphere channel map
|
|
41
|
+
const mapping = SPHERE_CHANNEL_MAP[type];
|
|
42
|
+
if (mapping) {
|
|
43
|
+
const volume = this.callbacks.getVolumeForLayer(mapping.layer);
|
|
44
|
+
const color = volume
|
|
45
|
+
? rgbaToHex(volume.getChannelColor(mapping.channel))
|
|
46
|
+
: (CHANNEL_HEX_COLORS[mapping.channel] || '#00ff00');
|
|
47
|
+
this.ctx.gui_states.drawing.fillColor = color;
|
|
48
|
+
this.ctx.gui_states.drawing.brushColor = color;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
getActiveSphereType() {
|
|
52
|
+
return this.ctx.gui_states.mode.activeSphereType;
|
|
53
|
+
}
|
|
54
|
+
/****************************Visibility****************************************************/
|
|
55
|
+
setLayerVisible(layerId, visible) {
|
|
56
|
+
this.ctx.gui_states.layerChannel.layerVisibility[layerId] = visible;
|
|
57
|
+
this.callbacks.reloadMasksFromVolume();
|
|
58
|
+
}
|
|
59
|
+
isLayerVisible(layerId) {
|
|
60
|
+
var _a;
|
|
61
|
+
return (_a = this.ctx.gui_states.layerChannel.layerVisibility[layerId]) !== null && _a !== void 0 ? _a : true;
|
|
62
|
+
}
|
|
63
|
+
setChannelVisible(layerId, channel, visible) {
|
|
64
|
+
if (this.ctx.gui_states.layerChannel.channelVisibility[layerId]) {
|
|
65
|
+
this.ctx.gui_states.layerChannel.channelVisibility[layerId][channel] = visible;
|
|
66
|
+
}
|
|
67
|
+
this.callbacks.reloadMasksFromVolume();
|
|
68
|
+
}
|
|
69
|
+
isChannelVisible(layerId, channel) {
|
|
70
|
+
var _a, _b;
|
|
71
|
+
return (_b = (_a = this.ctx.gui_states.layerChannel.channelVisibility[layerId]) === null || _a === void 0 ? void 0 : _a[channel]) !== null && _b !== void 0 ? _b : true;
|
|
72
|
+
}
|
|
73
|
+
getLayerVisibility() {
|
|
74
|
+
return Object.assign({}, this.ctx.gui_states.layerChannel.layerVisibility);
|
|
75
|
+
}
|
|
76
|
+
getChannelVisibility() {
|
|
77
|
+
const result = {};
|
|
78
|
+
for (const layerId of this.ctx.nrrd_states.image.layers) {
|
|
79
|
+
result[layerId] = Object.assign({}, this.ctx.gui_states.layerChannel.channelVisibility[layerId]);
|
|
80
|
+
}
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
83
|
+
hasLayerData(layerId) {
|
|
84
|
+
const volume = this.ctx.protectedData.maskData.volumes[layerId];
|
|
85
|
+
if (!volume) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
return volume.hasData();
|
|
89
|
+
}
|
|
90
|
+
/****************************Channel Colors****************************************************/
|
|
91
|
+
setChannelColor(layerId, channel, color) {
|
|
92
|
+
const volume = this.ctx.protectedData.maskData.volumes[layerId];
|
|
93
|
+
if (!volume) {
|
|
94
|
+
console.warn(`setChannelColor: unknown layer "${layerId}"`);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
volume.setChannelColor(channel, color);
|
|
98
|
+
if (layerId === this.ctx.gui_states.layerChannel.layer && channel === this.ctx.gui_states.layerChannel.activeChannel) {
|
|
99
|
+
this.syncBrushColor();
|
|
100
|
+
}
|
|
101
|
+
this.callbacks.reloadMasksFromVolume();
|
|
102
|
+
this.callbacks.onChannelColorChanged(layerId, channel, color);
|
|
103
|
+
}
|
|
104
|
+
getChannelColor(layerId, channel) {
|
|
105
|
+
const volume = this.ctx.protectedData.maskData.volumes[layerId];
|
|
106
|
+
if (!volume) {
|
|
107
|
+
return { r: 0, g: 255, b: 0, a: 255 };
|
|
108
|
+
}
|
|
109
|
+
return volume.getChannelColor(channel);
|
|
110
|
+
}
|
|
111
|
+
getChannelHexColor(layerId, channel) {
|
|
112
|
+
return rgbaToHex(this.getChannelColor(layerId, channel));
|
|
113
|
+
}
|
|
114
|
+
getChannelCssColor(layerId, channel) {
|
|
115
|
+
return rgbaToCss(this.getChannelColor(layerId, channel));
|
|
116
|
+
}
|
|
117
|
+
setChannelColors(layerId, colorMap) {
|
|
118
|
+
const volume = this.ctx.protectedData.maskData.volumes[layerId];
|
|
119
|
+
if (!volume) {
|
|
120
|
+
console.warn(`setChannelColors: unknown layer "${layerId}"`);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
for (const [ch, color] of Object.entries(colorMap)) {
|
|
124
|
+
volume.setChannelColor(Number(ch), color);
|
|
125
|
+
}
|
|
126
|
+
if (layerId === this.ctx.gui_states.layerChannel.layer) {
|
|
127
|
+
this.syncBrushColor();
|
|
128
|
+
}
|
|
129
|
+
this.callbacks.reloadMasksFromVolume();
|
|
130
|
+
}
|
|
131
|
+
setAllLayersChannelColor(channel, color) {
|
|
132
|
+
for (const layerId of this.ctx.nrrd_states.image.layers) {
|
|
133
|
+
const volume = this.ctx.protectedData.maskData.volumes[layerId];
|
|
134
|
+
if (volume) {
|
|
135
|
+
volume.setChannelColor(channel, color);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (channel === this.ctx.gui_states.layerChannel.activeChannel) {
|
|
139
|
+
this.syncBrushColor();
|
|
140
|
+
}
|
|
141
|
+
this.callbacks.reloadMasksFromVolume();
|
|
142
|
+
}
|
|
143
|
+
resetChannelColors(layerId, channel) {
|
|
144
|
+
const layers = layerId ? [layerId] : this.ctx.nrrd_states.image.layers;
|
|
145
|
+
for (const lid of layers) {
|
|
146
|
+
const volume = this.ctx.protectedData.maskData.volumes[lid];
|
|
147
|
+
if (volume) {
|
|
148
|
+
volume.resetChannelColors(channel);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
this.syncBrushColor();
|
|
152
|
+
this.callbacks.reloadMasksFromVolume();
|
|
153
|
+
}
|
|
154
|
+
/****************************Private Helpers****************************************************/
|
|
155
|
+
/**
|
|
156
|
+
* Sync brush/fill color from the active layer's volume channel color.
|
|
157
|
+
* Falls back to global CHANNEL_HEX_COLORS if volume not available.
|
|
158
|
+
*/
|
|
159
|
+
syncBrushColor() {
|
|
160
|
+
const channel = this.ctx.gui_states.layerChannel.activeChannel || 1;
|
|
161
|
+
const layer = this.ctx.gui_states.layerChannel.layer;
|
|
162
|
+
const volume = this.ctx.protectedData.maskData.volumes[layer];
|
|
163
|
+
if (volume) {
|
|
164
|
+
const hex = rgbaToHex(volume.getChannelColor(channel));
|
|
165
|
+
this.ctx.gui_states.drawing.fillColor = hex;
|
|
166
|
+
this.ctx.gui_states.drawing.brushColor = hex;
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
const hex = CHANNEL_HEX_COLORS[channel] || '#00ff00';
|
|
170
|
+
this.ctx.gui_states.drawing.fillColor = hex;
|
|
171
|
+
this.ctx.gui_states.drawing.brushColor = hex;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=LayerChannelManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LayerChannelManager.js","sourceRoot":"","sources":["../../../../src/Utils/segmentation/tools/LayerChannelManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PanTool - Right-click pan/drag navigation
|
|
3
|
+
*
|
|
4
|
+
* Extracted from DrawToolCore.paintOnCanvas() closure.
|
|
5
|
+
* Handles right-click drag to reposition the canvas view.
|
|
6
|
+
*/
|
|
7
|
+
import { BaseTool } from "./BaseTool";
|
|
8
|
+
import type { ToolContext } from "./BaseTool";
|
|
9
|
+
import type { PanHostDeps } from "./ToolHost";
|
|
10
|
+
export declare class PanTool extends BaseTool {
|
|
11
|
+
/** Right mouse button currently held */
|
|
12
|
+
private rightClicked;
|
|
13
|
+
/** Pan drag offset X (clientX − canvas.offsetLeft at drag start) */
|
|
14
|
+
private panMoveInnerX;
|
|
15
|
+
/** Pan drag offset Y (clientY − canvas.offsetTop at drag start) */
|
|
16
|
+
private panMoveInnerY;
|
|
17
|
+
private callbacks;
|
|
18
|
+
/**
|
|
19
|
+
* Bound handler reference for pointermove so we can add/remove it.
|
|
20
|
+
* Arrow function preserves `this` binding.
|
|
21
|
+
*/
|
|
22
|
+
private readonly boundPointerMove;
|
|
23
|
+
constructor(ctx: ToolContext, callbacks: PanHostDeps);
|
|
24
|
+
/** Whether a pan drag is currently active */
|
|
25
|
+
get isActive(): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Called on right-click pointerdown.
|
|
28
|
+
* Captures initial offsets and registers pointermove listener.
|
|
29
|
+
*/
|
|
30
|
+
onPointerDown(e: MouseEvent): void;
|
|
31
|
+
/**
|
|
32
|
+
* Called on pointerup (button === 2).
|
|
33
|
+
* Cleans up listeners and restores cursor.
|
|
34
|
+
*/
|
|
35
|
+
onPointerUp(e: MouseEvent, defaultCursor: string): void;
|
|
36
|
+
/**
|
|
37
|
+
* Called on pointerleave while pan is active.
|
|
38
|
+
* Resets state and removes listener.
|
|
39
|
+
*/
|
|
40
|
+
onPointerLeave(): void;
|
|
41
|
+
/** Reset pan state (called when paintOnCanvas re-initializes) */
|
|
42
|
+
reset(): void;
|
|
43
|
+
/**
|
|
44
|
+
* Pointermove handler — updates canvas position during drag.
|
|
45
|
+
*/
|
|
46
|
+
private handlePointerMove;
|
|
47
|
+
}
|