基于cornerstone3D的dicom影像浏览器 第五章 在Displayer四个角落显示信息

发布于:2025-09-06 ⋅ 阅读:(19) ⋅ 点赞:(0)

先看效果

dicom四个角落显示信息

1.在displayer.vue文件中引入对应的依赖

import { vec3 } from "gl-matrix";
import {
  RenderingEngine,
  getRenderingEngine,
  Enums,
  utilities as csUtils,
} from "@cornerstonejs/core";
const { IMAGE_RENDERED, CAMERA_MODIFIED } = Enums.Events;
import { utilities } from "@cornerstonejs/tools";
const { getOrientationStringLPS, invertOrientationStringLPS } =
  utilities.orientation;

2.监听事件

mounted() {
    ...

    this.$refs.displayer.addEventListener(IMAGE_RENDERED, this.onImageRendered);
    this.$refs.displayer.addEventListener(
      CAMERA_MODIFIED,
      this.onCameraModified
    );
    ...
  },

3.相关函数

methods:{

    onImageRendered() {
      if (!this.state.series) return;
      this.drawText();
    },
    onCameraModified(event) {
      if (!this.state.series) return;
      const markers = this.getOrientationMarkers({
        image: this.state.image,
        camera: event.detail.camera,
        rotation: event.detail.rotation,
      });
      this.orientation.top = markers.top;
      this.orientation.bottom = markers.bottom;
      this.orientation.left = markers.left;
      this.orientation.right = markers.right;
    },
    drawText() {
      const canvas = this.$refs.displayer.querySelector(".cornerstone-canvas");
      const context = canvas.getContext("2d");
      const cvs_w = canvas.clientWidth;
      const cvs_h = canvas.clientHeight;

      const mtx = context.getTransform();
      context.resetTransform();

      context.font = "14px Arial";
      context.fillStyle = "white";
      context.textAlign = "left";
      context.textBaseline = "top";

      const idx = this.state.viewport.getCurrentImageIdIndex();

      const imageId = this.state.imageIds[idx];
      const image = this.state.series.GetImageById(imageId);

      let x = 5;
      let y = 5;
      let h = 17;
      let val;

      // 左上角 left-top
      // 姓名
      val = image.PatientName;
      context.fillText(val, x, y);
      y += h;
      // PatientId
      val = image.PatientID;
      context.fillText(val, x, y);
      y += h;
      // 年龄(或者生日)+性别
      val = image.AgeAndSex;
      if (val) {
        context.fillText(val, x, y);
        y += h;
      }
      // Image Comments
      val = image.ImageComments;
      if (val) {
        context.fillText(val, x, y);
        y += h;
      }

      // 左下角 left-bottom
      y = cvs_h - h;
      // 医院名
      val = image.HospitalName;
      if (val) {
        context.fillText(val, x, y);
        y -= h;
      }
      // 图像时间
      val = image.ContentDate + " " + image.ContentTime;
      if (val) {
        context.fillText(val, x, y);
        y -= h;
      }
      // Study Description
      val = image.StudyDesc;
      if (val) {
        context.fillText(val, x, y);
        y -= h;
      }
      //series Description
      val = image.SeriesDesc;
      if (val) {
        context.fillText(val, x, y);
        y -= h;
      }
      //患者方向
      val = image.PatientPosition;
      if (val) {
        context.fillText(val, x, y);
        y -= h;
      }

      // 右上角 right-top
      const rmargin = 5;
      y = 5;
      const range = this.state.viewport.getProperties().voiRange || {
        lower: -1024,
        upper: 1024,
      };
      const wwwl = csUtils.windowLevel.toWindowLevel(range.lower, range.upper);
      val = "WL:" + wwwl.windowCenter.toFixed(0);
      val += " WW:" + wwwl.windowWidth.toFixed(0);
      x = cvs_w - rmargin - context.measureText(val).width;
      context.fillText(val, x, y);
      y += h;
      // Image No-Count
      val = "Im:" + (idx + 1) + "/" + this.state.series.GetCount();
      x = cvs_w - rmargin - context.measureText(val).width;
      context.fillText(val, x, y);
      y += h;
      // Series No
      val = image.SeriesNo;
      if (val) {
        x = cvs_w - rmargin - context.measureText(val).width;
        context.fillText(val, x, y);
        y += h;
      }
      // modality
      val = image.DeviceName;
      if (val) {
        x = cvs_w - rmargin - context.measureText(val).width;
        context.fillText(val, x, y);
      }

      // 右下角 right-bottom
      y = cvs_h - h;
      // Thickness-Location
      val = image.ThicknessLocation;
      if (val) {
        x = cvs_w - rmargin - context.measureText(val).width;
        context.fillText(val, x, y);
        y -= h;
      }

      // 曝光参数
      val = image.Exposure;
      if (val) {
        x = cvs_w - rmargin - context.measureText(val).width;
        context.fillText(val, x, y);
        y -= h;
      }
      // 拍片参数
      val = image.TrTe;
      if (val) {
        x = cvs_w - rmargin - context.measureText(val).width;
        context.fillText(val, x, y);
        y -= h;
      }
      // Zoom
      const imageData = this.state.viewport.getImageData();
      const camera = this.state.viewport.getCamera();
      let spacing = [1, 1, 1];
      if (imageData) {
        spacing = imageData.spacing;
      }
      const t = cvs_h * spacing[1] * 0.5;
      const scale = t / camera.parallelScale;
      val = "Zoom:" + scale.toFixed(2);
      x = cvs_w - rmargin - context.measureText(val).width;
      context.fillText(val, x, y);

      context.setTransform(mtx);
    },
    getOrientationMarkers({ camera, rotation }) {
      // const { rotation, previousCamera, camera } = detail;
      let flipVertical = camera.flipVertical || false;
      let flipHorizontal = camera.flipHorizontal || false;
      let newRotation = rotation || 0;
      let rowCosines, columnCosines;

      const { viewUp, viewPlaneNormal } = camera;

      const viewRight = vec3.create();
      vec3.cross(viewRight, viewUp, viewPlaneNormal);

      columnCosines = [-viewUp[0], -viewUp[1], -viewUp[2]];
      rowCosines = viewRight;

      const rowString = getOrientationStringLPS(rowCosines);
      const columnString = getOrientationStringLPS(columnCosines);
      const oppositeRowString = invertOrientationStringLPS(rowString);
      const oppositeColumnString = invertOrientationStringLPS(columnString);

      const markers = {
        top: oppositeColumnString,
        left: oppositeRowString,
        right: rowString,
        bottom: columnString,
      };

      // If any vertical or horizontal flips are applied, change the orientation strings ahead of
      // the rotation applications
      if (flipVertical) {
        markers.top = invertOrientationStringLPS(markers.top);
        markers.bottom = invertOrientationStringLPS(markers.bottom);
      }

      if (flipHorizontal) {
        markers.left = invertOrientationStringLPS(markers.left);
        markers.right = invertOrientationStringLPS(markers.right);
      }

      // Swap the labels accordingly if the viewport has been rotated
      // This could be done in a more complex way for intermediate rotation values (e.g. 45 degrees)
      if (newRotation === 90 || newRotation === -270) {
        return {
          top: markers.left,
          left: invertOrientationStringLPS(markers.top),
          right: invertOrientationStringLPS(markers.bottom),
          bottom: markers.right, // left
        };
      } else if (newRotation === -90 || newRotation === 270) {
        return {
          top: invertOrientationStringLPS(markers.left),
          left: markers.top,
          bottom: markers.left,
          right: markers.bottom,
        };
      } else if (newRotation === 180 || newRotation === -180) {
        return {
          top: invertOrientationStringLPS(markers.top),
          left: invertOrientationStringLPS(markers.left),
          bottom: invertOrientationStringLPS(markers.bottom),
          right: invertOrientationStringLPS(markers.right),
        };
      }

      return markers;
    },
}


网站公告

今日签到

点亮在社区的每一天
去签到