Pārlūkot izejas kodu

feat(processing): implement functionality to add mask to images in image processing module

sw 1 mēnesi atpakaļ
vecāks
revīzija
d627fc2b8d

+ 95 - 2
src/pages/view/components/viewers/stack.image.viewer.tsx

@@ -9,6 +9,8 @@ import { SystemMode } from '@/states/systemModeSlice';
 import store from '@/states/store';
 import { clearAction } from '@/states/view/functionAreaSlice';
 import { useDispatch } from 'react-redux';
+import { SplineROITool } from '@cornerstonejs/tools';
+import { eventTarget } from '@cornerstonejs/core';
 
 const {
   MagnifyTool,
@@ -25,6 +27,82 @@ const { MouseBindings } = csToolsEnums;
 let toolGroup: cornerstoneTools.Types.IToolGroup;
 let currentViewportId: string;
 
+function overlayRedRectangle() {
+  const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
+    .viewport as cornerstone.StackViewport;
+  const viewportElement = viewport.element;
+  const annotations = cornerstoneTools.annotation.state.getAnnotations(
+    'LinearSplineROI',
+    viewportElement
+  );
+
+  if (!annotations || annotations.length === 0) {
+    console.log('No ROI annotations found');
+    return;
+  }
+
+  const annotation = annotations[annotations.length - 1];
+  const points = annotation?.data?.handles?.points;
+
+  // 创建一个覆盖 Canvas
+  const canvas = document.createElement('canvas');
+  canvas.style.position = 'absolute';
+  canvas.width = viewportElement.clientWidth;
+  canvas.height = viewportElement.clientHeight;
+  viewportElement.firstChild?.appendChild(canvas);
+
+  const ctx = canvas.getContext('2d');
+  if (!ctx) {
+    throw new Error('Failed to get 2D context from canvas');
+  }
+  ctx.fillStyle = 'rgba(0, 0, 0, 1)';
+
+  // 将 ROI 坐标转换为 Canvas 坐标
+  if (!points) {
+    console.log('No points found in handles');
+    return;
+  }
+
+  // Convert all points to canvas coordinates
+  const z = viewport.getCurrentImageIdIndex() || 0;
+  const canvasPoints = points.map((point: Types.Point2 | Types.Point3) => {
+    const point3D: Types.Point3 =
+      point.length === 2 ? [point[0], point[1], z] : point;
+    return viewport.worldToCanvas(point3D);
+  });
+
+  // Log for debugging
+  console.log('Canvas Points:', canvasPoints);
+
+  // Draw the polygon
+  ctx.beginPath();
+  ctx.rect(0, 0, canvas.width, canvas.height); // Full canvas for evenodd rule
+  ctx.moveTo(canvasPoints[0][0], canvasPoints[0][1]); // Start at the first point
+  for (let i = 1; i < canvasPoints.length; i++) {
+    ctx.lineTo(canvasPoints[i][0], canvasPoints[i][1]); // Connect to subsequent points
+  }
+  ctx.closePath(); // Close the polygon
+  ctx.fill('evenodd'); // Fill with red
+}
+
+eventTarget.addEventListener(
+  cornerstoneTools.Enums.Events.ANNOTATION_COMPLETED,
+  (evt) => {
+    const { annotation } = evt.detail;
+    console.log('Annotation completed event:', annotation);
+    if (annotation.metadata.toolName === 'LinearSplineROI') {
+      console.log('SplineROITool annotation completed:', annotation);
+      overlayRedRectangle();
+      //取消工具激活状态
+      const toolGroup = ToolGroupManager.getToolGroup('STACK_TOOL_GROUP_ID');
+      if (!toolGroup) {
+        console.log('toolGroup not found');
+      }
+      toolGroup?.setToolPassive('LinearSplineROI', { removeAllBindings: true });
+    }
+  }
+);
+
 function registerTools(viewportId, renderingEngineId) {
   // Add tools to Cornerstone3D
   cornerstoneTools.addTool(MagnifyTool);
@@ -162,6 +240,22 @@ function deleteSelectedMark(): void {
   }
   viewport.render();
 }
+
+function addMask(): void {
+  // Implement the logic to add a mask
+  console.log('Adding Mask');
+  // Add the specific logic to add a mask here
+  cornerstoneTools.addTool(SplineROITool);
+  toolGroup.addTool(SplineROITool.toolName);
+  toolGroup.addToolInstance('LinearSplineROI', SplineROITool.toolName, {
+    spline: {
+      type: SplineROITool.SplineTypes.Linear,
+    },
+  });
+  toolGroup.setToolActive('LinearSplineROI', {
+    bindings: [{ mouseButton: MouseBindings.Primary }],
+  });
+}
 function HorizontalFlip(): void {
   const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
     .viewport as cornerstone.StackViewport;
@@ -509,8 +603,7 @@ const StackViewer = ({
           }
           break;
         case 'Crop Image':
-          // Implement the logic to crop the image
-          console.log('Cropping Image');
+          addMask();
           break;
         case 'Delete Digital Mask':
           // Implement the logic to delete the digital mask