@@ -24,46 +24,32 @@ function setupSyncedBrush(imageDataObject, element) {
24
24
25
25
// If you want to load a segmentation labelmap, you would want to load
26
26
// it into this array at this point.
27
- const threeDimensionalPixelData = new Uint8ClampedArray ( numVolumePixels ) ;
27
+ const threeDimensionalPixelData = new Uint16Array ( numVolumePixels ) ;
28
28
29
29
const buffer = threeDimensionalPixelData . buffer ;
30
-
31
- // Slice buffer into 2d-sized pieces, which are added to Cornerstone ToolData
32
- const toolType = 'brush' ;
33
- const segmentationIndex = 0 ;
34
30
const imageIds = imageDataObject . imageIds ;
35
- if ( imageIds . length !== depth ) {
31
+ const numberOfFrames = imageIds . length ;
32
+
33
+ if ( numberOfFrames !== depth ) {
36
34
throw new Error ( 'Depth should match the number of imageIds' ) ;
37
35
}
38
36
39
- const { globalImageIdSpecificToolStateManager } = cornerstoneTools ;
40
-
41
- for ( let i = 0 ; i < imageIds . length ; i ++ ) {
42
- const imageId = imageIds [ i ] ;
43
- const byteOffset = width * height * i ;
44
- const length = width * height ;
45
- const slicePixelData = new Uint8ClampedArray ( buffer , byteOffset , length ) ;
46
-
47
- const toolData = [ ] ;
48
- toolData [ segmentationIndex ] = {
49
- pixelData : slicePixelData ,
50
- invalidated : true ,
51
- } ;
52
-
53
- const toolState =
54
- globalImageIdSpecificToolStateManager . saveImageIdToolState ( imageId ) || { } ;
37
+ const segmentationModule = cornerstoneTools . getModule ( 'segmentation' ) ;
55
38
56
- toolState [ toolType ] = {
57
- data : toolData ,
58
- } ;
39
+ segmentationModule . setters . labelmap3DByFirstImageId (
40
+ imageIds [ 0 ] ,
41
+ buffer ,
42
+ 0 ,
43
+ [ ] ,
44
+ numberOfFrames ,
45
+ undefined ,
46
+ 0
47
+ ) ;
59
48
60
- globalImageIdSpecificToolStateManager . restoreImageIdToolState (
61
- imageId ,
62
- toolState
63
- ) ;
64
- }
49
+ segmentationModule . setters . colorLUT ( 0 , [ [ 255 , 0 , 0 , 255 ] ] ) ;
65
50
66
51
// Create VTK Image Data with buffer as input
52
+
67
53
const labelMap = vtkImageData . newInstance ( ) ;
68
54
69
55
// right now only support 256 labels
@@ -100,9 +86,6 @@ const ROOT_URL =
100
86
: window . location . hostname ;
101
87
102
88
const imageIds = [
103
- //'dicomweb://s3.amazonaws.com/lury/PTCTStudy/1.3.6.1.4.1.25403.52237031786.3872.20100510032220.10.dcm',
104
- //'dicomweb://s3.amazonaws.com/lury/PTCTStudy/1.3.6.1.4.1.25403.52237031786.3872.20100510032220.11.dcm',
105
- //'dicomweb://s3.amazonaws.com/lury/PTCTStudy/1.3.6.1.4.1.25403.52237031786.3872.20100510032220.12.dcm',
106
89
`dicomweb://${ ROOT_URL } /PTCTStudy/1.3.6.1.4.1.25403.52237031786.3872.20100510032221.1.dcm` ,
107
90
`dicomweb://${ ROOT_URL } /PTCTStudy/1.3.6.1.4.1.25403.52237031786.3872.20100510032221.2.dcm` ,
108
91
`dicomweb://${ ROOT_URL } /PTCTStudy/1.3.6.1.4.1.25403.52237031786.3872.20100510032221.3.dcm` ,
@@ -120,8 +103,6 @@ const promises = imageIds.map(imageId => {
120
103
return cornerstone . loadAndCacheImage ( imageId ) ;
121
104
} ) ;
122
105
123
- const BaseBrushTool = cornerstoneTools . import ( 'base/BaseBrushTool' ) ;
124
-
125
106
class VTKCornerstonePaintingSyncExample extends Component {
126
107
state = {
127
108
volumes : null ,
@@ -147,10 +128,13 @@ class VTKCornerstonePaintingSyncExample extends Component {
147
128
} ;
148
129
149
130
const imageDataObject = getImageData ( imageIds , displaySetInstanceUid ) ;
150
- const labelMapInputData = setupSyncedBrush ( imageDataObject ) ;
131
+ const labelMapInputData = setupSyncedBrush (
132
+ imageDataObject ,
133
+ this . cornerstoneElements [ 0 ]
134
+ ) ;
151
135
152
- this . onMeasurementModified = event => {
153
- if ( event . type !== EVENTS . MEASUREMENT_MODIFIED ) {
136
+ this . onMeasurementsChanged = event => {
137
+ if ( event . type !== EVENTS . LABELMAP_MODIFIED ) {
154
138
return ;
155
139
}
156
140
@@ -161,6 +145,7 @@ class VTKCornerstonePaintingSyncExample extends Component {
161
145
162
146
loadImageData ( imageDataObject ) . then ( ( ) => {
163
147
const { actor } = createActorMapper ( imageDataObject . vtkImageData ) ;
148
+
164
149
this . setState ( {
165
150
vtkImageData : imageDataObject . vtkImageData ,
166
151
volumes : [ actor ] ,
@@ -175,14 +160,33 @@ class VTKCornerstonePaintingSyncExample extends Component {
175
160
) ;
176
161
}
177
162
178
- invalidateBrush = ( ) => {
163
+ onPaintEnd = ( ) => {
179
164
const element = this . cornerstoneElements [ 0 ] ;
180
165
const enabledElement = cornerstone . getEnabledElement ( element ) ;
181
- const enabledElementUid = enabledElement . uuid ;
166
+ const { getters, setters } = cornerstoneTools . getModule ( 'segmentation' ) ;
167
+ const labelmap3D = getters . labelmap3D ( element ) ;
168
+ const stackState = cornerstoneTools . getToolState ( element , 'stack' ) ;
169
+ const { rows, columns } = enabledElement . image ;
170
+
171
+ if ( ! stackState || ! labelmap3D ) {
172
+ return ;
173
+ }
174
+
175
+ const stackData = stackState . data [ 0 ] ;
176
+ const numberOfFrames = stackData . imageIds . length ;
177
+
178
+ // TODO -> Can do more efficiently if we can grab the strokeBuffer from vtk-js.
179
+ for ( let i = 0 ; i < numberOfFrames ; i ++ ) {
180
+ const labelmap2D = getters . labelmap2DByImageIdIndex (
181
+ labelmap3D ,
182
+ i ,
183
+ rows ,
184
+ columns
185
+ ) ;
186
+ setters . updateSegmentsOnLabelmap2D ( labelmap2D ) ;
187
+ }
182
188
183
- // Note: This calls updateImage internally
184
- // TODO: Find out why it's not very quick to update...
185
- BaseBrushTool . invalidateBrushOnEnabledElement ( enabledElementUid ) ;
189
+ cornerstone . updateImage ( element ) ;
186
190
} ;
187
191
188
192
rerenderAllVTKViewports = ( ) => {
@@ -233,7 +237,7 @@ class VTKCornerstonePaintingSyncExample extends Component {
233
237
< h1 > Syncing VTK Labelmap with Cornerstone Brush Tool Data</ h1 >
234
238
< p >
235
239
This example demonstrates how to keep painting in VTK, which is
236
- performed in 3D, in sync with Cornerstone' s tool data, which is
240
+ performed in 3D, in sync with Cornerstone' s tool data, which is
237
241
accessed in 2D.
238
242
</ p >
239
243
< p >
@@ -278,7 +282,7 @@ class VTKCornerstonePaintingSyncExample extends Component {
278
282
paintFilterBackgroundImageData = { this . state . vtkImageData }
279
283
paintFilterLabelMapImageData = { this . state . labelMapInputData }
280
284
painting = { this . state . focusedWidgetId === 'PaintWidget' }
281
- onPaint = { this . invalidateBrush }
285
+ onPaintEnd = { this . onPaintEnd }
282
286
onCreated = { this . saveComponentReference ( 0 ) }
283
287
/>
284
288
) }
@@ -287,8 +291,13 @@ class VTKCornerstonePaintingSyncExample extends Component {
287
291
{ this . state . cornerstoneViewportData && (
288
292
< CornerstoneViewport
289
293
activeTool = { 'Brush' }
294
+ availableTools = { [
295
+ { name : 'Brush' , mouseButtonMasks : [ 1 ] } ,
296
+ { name : 'StackScrollMouseWheel' } ,
297
+ { name : 'StackScrollMultiTouch' } ,
298
+ ] }
290
299
viewportData = { this . state . cornerstoneViewportData }
291
- onMeasurementModified = { this . onMeasurementModified }
300
+ onMeasurementsChanged = { this . onMeasurementsChanged }
292
301
onElementEnabled = { this . saveCornerstoneElements ( 0 ) }
293
302
/>
294
303
) }
0 commit comments