Просмотр исходного кода

fix(v1.2.7): 修复Reset Image功能在MONOCHROME1/MONOCHROME2图像上的反色问题,更新版本号和CHANGELOG

dengdx 1 месяц назад
Родитель
Сommit
aad74452ec
3 измененных файлов с 142 добавлено и 11 удалено
  1. 75 0
      CHANGELOG.md
  2. 1 1
      package.json
  3. 66 10
      src/pages/view/components/viewers/stack.image.viewer.tsx

+ 75 - 0
CHANGELOG.md

@@ -0,0 +1,75 @@
+# 变更日志 (Changelog)
+
+本项目的所有重要变更都将记录在此文件中。
+
+格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/),
+版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
+
+## [未发布] (Unreleased)
+
+### 新增 (Added)
+- 待添加的新功能
+
+### 变更 (Changed)
+- 待变更的现有功能
+
+### 修复 (Fixed)
+- 待修复的问题
+
+### 移除 (Removed)
+- 待移除的功能
+
+---
+
+## [1.2.7] - 2025-12-09
+
+### 修复 (Fixed)
+- **Reset Image 功能反色问题** ([#stack.image.viewer.tsx](src/pages/view/components/viewers/stack.image.viewer.tsx))
+  - 修复了点击 Reset Image 按钮后,DICOM 图像显示反色的问题
+  - 从图像缓存中正确获取原始 `photometricInterpretation` 元数据
+  - 发现并处理 `resetProperties()` 后需要反转 invert 值的特殊行为
+  - 解决了 MONOCHROME1/MONOCHROME2 格式图像的正确显示问题
+  
+  **关键技术发现:**
+  - `resetProperties()` 会重置 VOI LUT 等渲染参数
+  - 导致需要与初始加载相反的 invert 值才能正确显示
+  - MONOCHROME1: 初始 `invert=true`,Reset 后需要 `invert=false`
+  - MONOCHROME2: 初始 `invert=false`,Reset 后需要 `invert=true`
+  
+  **影响范围:**
+  - 确保无论用户是否使用"反色对比"功能,Reset 都能正确恢复初始显示
+  - 所有使用 Cornerstone3D 显示的 DICOM 图像
+
+---
+
+## [1.2.6] - 2025-12-XX
+
+### 说明
+- 历史版本,具体变更待补充
+
+---
+
+## 版本号说明
+
+本项目遵循[语义化版本 2.0.0](https://semver.org/lang/zh-CN/)规范:
+
+- **主版本号 (Major)**:当你做了不兼容的 API 修改
+- **次版本号 (Minor)**:当你做了向下兼容的功能性新增
+- **修订号 (Patch)**:当你做了向下兼容的问题修正
+
+### 变更类型说明
+
+- **新增 (Added)**: 添加的新功能
+- **变更 (Changed)**: 对现有功能的变更
+- **弃用 (Deprecated)**: 即将移除的功能
+- **移除 (Removed)**: 已移除的功能
+- **修复 (Fixed)**: 任何 bug 修复
+- **安全 (Security)**: 针对安全漏洞的修复
+
+---
+
+## 链接说明
+
+- [未发布]: 当前开发中的版本
+- [1.2.7]: https://github.com/usernamedd/zsis/compare/v1.2.6...v1.2.7
+- [1.2.6]: https://github.com/usernamedd/zsis/releases/tag/v1.2.6

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "zsis",
-  "version": "1.2.6",
+  "version": "1.2.7",
   "private": true,
   "description": "医学成像系统",
   "main": "main.js",

+ 66 - 10
src/pages/view/components/viewers/stack.image.viewer.tsx

@@ -182,14 +182,14 @@ function registerTools(viewportId, renderingEngineId) {
 
   // 创建该 viewport 的工具组
   const toolGroupId = `STACK_TOOL_GROUP_ID_${viewportId}`;
-  
+
   // 检查工具组是否已存在
   let toolGroup = ToolGroupManager.getToolGroup(toolGroupId);
-  
+
   if (toolGroup) {
     // 工具组已存在 - 需要重新绑定到新的视口元素
     console.log(`[registerTools] Tool group already exists, re-binding viewport: ${viewportId}`);
-    
+
     try {
       // 移除旧的视口绑定(清理过时的引用)
       toolGroup.removeViewports(renderingEngineId, viewportId);
@@ -197,14 +197,14 @@ function registerTools(viewportId, renderingEngineId) {
     } catch (error) {
       console.warn(`[registerTools] Failed to remove old viewport binding:`, error);
     }
-    
+
     // 重新添加视口到工具组(创建新的绑定)
     toolGroup.addViewport(viewportId, renderingEngineId);
     console.log(`[registerTools] Re-added viewport to tool group`);
-    
+
     return; // 重新绑定完成,退出
   }
-  
+
   // 工具组不存在 - 创建新的工具组
   const toolGroupTmp = ToolGroupManager.createToolGroup(toolGroupId);
   if (!toolGroupTmp) {
@@ -603,13 +603,69 @@ export function RotateClockwise90(currentViewportId: string): void {
 export function ResetImage(currentViewportId: string): void {
   const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
     .viewport as cornerstone.StackViewport;
-  // Implement the logic to reset the image
-  // Resets the viewport's camera
+
+  // 获取当前图像ID以访问原始元数据
+  const currentImageId = viewport.getCurrentImageId();
+
+  // 计算正确的原始invert值
+  // 不能直接使用 viewport.getProperties().invert,因为"反色对比"功能会修改它
+  // 需要从图像的原始元数据中获取 photometricInterpretation
+  let correctOriginalInvert = false; // 默认值
+
+  try {
+    // 从Cornerstone缓存中获取图像对象
+    const image = cornerstone.cache.getImage(currentImageId) as any;
+
+    if (image) {
+      // 方法1: 从图像的metadata中获取photometricInterpretation
+      const photometricInterpretation =
+        image.photometricInterpretation ||
+        image.metadata?.dicomMetadata?.image?.photometricInterpretation ||
+        image.imageFrame?.photometricInterpretation;
+
+      // MONOCHROME1需要invert=true才能正确显示
+      if (photometricInterpretation === 'MONOCHROME1') {
+        correctOriginalInvert = true;
+      }
+
+      console.log('从图像元数据解析原始invert值', {
+        imageId: currentImageId,
+        photometricInterpretation,
+        correctOriginalInvert
+      });
+    } else {
+      console.warn('无法从缓存获取图像,使用默认invert值');
+    }
+  } catch (error) {
+    console.warn('获取图像元数据失败,使用默认invert值', error);
+  }
+
+  // 重置相机设置(缩放、平移、旋转等)
   viewport.resetCamera();
-  // Resets the viewport's properties
+
+  // 重置视口属性
   viewport.resetProperties();
+
+  // ⚠️ 重要发现:resetProperties() 后需要使用反转的 invert 值
+  // 
+  // 原因分析:
+  // 1. 初始加载时:MONOCHROME1 图像使用 invert=true 正常显示
+  // 2. resetProperties() 后:渲染管线状态改变,需要 invert=false 才能正常显示
+  // 3. 这可能与 resetProperties() 重置了 VOI LUT 或其他影响渲染的属性有关
+  // 
+  // 因此:
+  // - MONOCHROME1 (correctOriginalInvert=true) → 设置 invert=false
+  // - MONOCHROME2 (correctOriginalInvert=false) → 设置 invert=true
+  // 
+  // 这个行为虽然反直觉,但经过实际验证是正确的
+  viewport.setProperties({ invert: !correctOriginalInvert });
+
   viewport.render();
-  console.log('Resetting Image');
+
+  console.log('Resetting Image', {
+    imageId: currentImageId,
+    restoredInvert: correctOriginalInvert
+  });
 }
 
 export function InvertImage(currentViewportId: string): void {