irc_web/.svn/pristine/72/72a9bf76753bfee6fd04c9a74ee...

1456 lines
51 KiB
Plaintext

<template>
<div
id="canvas"
ref="canvas"
v-loading="loading"
element-loading-text="Loading..."
element-loading-background="rgba(0, 0, 0, 0.8)"
style="position:relative;"
class="cornerstone-element"
@contextmenu.prevent="onContextmenu"
@mousemove="sliderMousemove"
@mouseup="sliderMouseup"
>
<div v-show="dicomInfo.series" class="info-series">
<h2 style="color:#f44336;padding: 5px 0px;margin: 0;">{{ subjectCode }} {{ stack.taskBlindName }}</h2>
<div>Series: #{{ dicomInfo.series }}</div>
<div>Image: #{{ dicomInfo.frame }}</div>
<div>{{ dicomInfo.modality }}</div>
</div>
<div v-show="dicomInfo.series" class="info-image">
<div v-show="mousePosition.mo">
Pos: {{ parseInt(mousePosition.x) }}, {{ parseInt(mousePosition.y) }}
</div>
<div v-if="(dicomInfo.modality === 'CT' || dicomInfo.modality === 'DR' || dicomInfo.modality === 'CR') && mousePosition.mo">
Density: {{ mousePosition.mo }}HU
</div>
<div v-else-if="dicomInfo.modality === 'PET' && mousePosition.mo">
Density: {{ mousePosition.mo }}SUV
</div>
<div v-else-if="mousePosition.mo">
Density: {{ mousePosition.mo }}
</div>
<div>
W*H: {{ dicomInfo.size }}
<!-- <span v-show="dicomInfo.pixel">{{ dicomInfo.pixel }}mm</span> -->
</div>
<div>Zoom: {{ dicomInfo.zoom }}</div>
<!-- <div v-show="toolState.clipPlaying">FPS {{ dicomInfo.fps }}</div> -->
</div>
<div class="info-subject">
<div>{{ stack.description }}</div>
<!-- <div>{{ dicomInfo.hospital }}</div> -->
<!-- <div v-show="dicomInfo.pid">{{ dicomInfo.pid }}</div> -->
<!-- <div>{{ subjectCode }}</div> -->
<!-- <div>{{ dicomInfo.sex }} {{ dicomInfo.age }}</div> -->
<!-- <div v-show="dicomInfo.acc">ACC {{ dicomInfo.acc }}</div> -->
<!-- <div>{{ dicomInfo.time }}</div> -->
</div>
<div ref="sliderBox" class="my_slider_box" style="position: absolute;right: 1px;height: calc(100% - 100px);transform: translateY(-50%);top: calc(50% - 30px);width: 10px;background: #333;cursor: pointer">
<div :style="{top: height + '%'}" style="z-index:10;background: #9e9e9e;height: 20px;width: 100%;position: absolute;top: 0;cursor: move" @mousedown="sliderMousedown($event)" />
</div>
<div style="position: absolute;left: 50%;top: 15px;color: #f44336;">
{{ markers.top }}
</div>
<div style="position: absolute;top: 50%;right: 15px;color: #f44336;">
{{ markers.right }}
</div>
<div style="position: absolute;left: 50%;bottom: 15px;color: #f44336;">
{{ markers.bottom }}
</div>
<div style="position: absolute;top: 50%;left: 15px;color: #f44336;">
{{ markers.left }}
</div>
<div class="info-instance">
<div v-show="dicomInfo.location">Location: {{ dicomInfo.location }}</div>
<div v-show="dicomInfo.thick">Slice Thickness: {{ dicomInfo.thick }}mm</div>
<div v-show="dicomInfo.wwwc">WW/WL: {{ dicomInfo.wwwc }}</div>
</div>
<!-- <div
v-show="mousePosition.mo"
class="msg-div"
:style="{
top: mousePosition.y+ 'px',
left: mousePosition.x+ 'px',
}"
>
<span>{{ mousePosition.mo }} ({{ parseInt(mousePosition.x) }},{{ parseInt(mousePosition.y) }})</span>
</div> -->
</div>
</template>
<style>
.my_slider_box:after{
content: '';
position: absolute;
bottom: -20px;
left: 0;
height: 20px;
width: 100%;
background: #333;
}
</style>
<script>
// import { splitLesion } from '@/api/trials'
import requestPoolManager from '@/utils/request-pool'
import DicomEvent from '../components/DicomEvent'
import Vue from 'vue'
import { mapGetters } from 'vuex'
import Contextmenu from 'vue-contextmenujs'
Vue.use(Contextmenu)
import * as cornerstone from 'cornerstone-core'
import * as cornerstoneMath from 'cornerstone-math'
import * as cornerstoneTools from 'cornerstone-tools'
const scroll = cornerstoneTools.import('util/scrollToIndex')
import Hammer from 'hammerjs'
import LengthTool from '@/views/trials/trials-panel/reading/dicoms/tools/Length/LengthTool'
import BidirectionalTool from '@/views/trials/trials-panel/reading/dicoms/tools/Bidirectional/BidirectionalTool'
import ArrowAnnotateTool from '@/views/trials/trials-panel/reading/dicoms/tools/ArrowAnnotate/ArrowAnnotateTool'
// import OrientationMarkersTool from '@/views/trials/trials-panel/reading/dicoms/tools/OrientationMarkers/OrientationMarkersTool'
import ScaleOverlayTool from '@/views/trials/trials-panel/reading/dicoms/tools/ScaleOverlay/ScaleOverlayTool'
import getOrientationString from '@/views/trials/trials-panel/reading/dicoms/tools/OrientationMarkers/getOrientationString'
import invertOrientationString from '@/views/trials/trials-panel/reading/dicoms/tools/OrientationMarkers/invertOrientationString'
import calculateLongestAndShortestDiameters from '@/views/trials/trials-panel/reading/dicoms/tools/Bidirectional/calculateLongestAndShortestDiameters'
cornerstoneTools.external.cornerstone = cornerstone
cornerstoneTools.external.Hammer = Hammer
cornerstoneTools.external.cornerstoneMath = cornerstoneMath
cornerstoneTools.toolStyle.setToolWidth(1)
cornerstoneTools.toolColors.setToolColor('rgb(255, 0, 0)')
cornerstoneTools.toolColors.setActiveColor('rgb(0, 255, 0)')
// cornerstoneTools.init({ globalToolSyncEnabled: true })
cornerstoneTools.init()
export default {
name: 'CustomizeDicomCanvas',
props: {
isScrollSync: {
type: Boolean,
required: true
},
canvasIndex: {
type: Number,
required: true
}
// isCurrentTask: {
// type: Boolean,
// required: true
// },
// isBaseline: {
// type: Boolean,
// required: true
// },
// readingTaskState: {
// type: Number,
// required: true
// }
},
data() {
return {
loading: false,
canvas: {},
index: 0,
height: 0,
cornerstoneStyle: {},
stack: {
studyId: '',
seriesId: '',
instanceId: '',
seriesNumber: '',
imageIds: [],
currentImageIdIndex: 0,
firstImageLoading: false,
visitTaskId: '',
taskBlindName: ''
// preventCache: true
},
dicomInfo: {
hospital: '',
pid: '',
name: '',
sex: '',
age: '',
acc: '',
modality: '',
time: '',
series: '',
frame: '',
size: '',
pixel: 0,
thick: 0,
wwwc: '',
zoom: 0,
fps: 5
},
toolState: {
initialized: false,
activeTool: 'none',
dicomInfoVisible: false,
clipPlaying: false,
viewportInvert: false
},
loadImagePromise: null,
AnnotationSync: null,
allROIToolData: {},
type: '',
series: '',
ToolStateManager: null,
renderedMeasured: [],
measuredTools: ['Length', 'Bidirectional', 'ArrowAnnotate'],
measureData: [],
selectedLesion: null,
activeTool: 0, // 0:enable 1:passive 2:active
activeToolName: '',
isCurrentTask: false,
isBaseline: false,
readingTaskState: 2,
image: null,
CriterionType: 0,
digitPlaces: 2,
sliderInfo: {
oldB: null,
oldM: null,
isMove: false
},
oldPosition: {},
subjectCode: '',
isMsg: false,
mousePosition: { x: '', y: '', mo: '' },
orientationMarkers: [],
originalMarkers: [],
imageId: '',
markers: { top: '', right: '', bottom: '', left: '' }
}
},
computed: {
...mapGetters(['visitTaskList'])
},
mounted() {
this.subjectCode = this.$router.currentRoute.query.subjectCode
document.addEventListener('mouseup', () => {
this.sliderMouseup()
})
// document.addEventListener('mousemove', () => {
// this.sliderMousemove()
// })
var digitPlaces = localStorage.getItem('digitPlaces')
this.digitPlaces = digitPlaces ? Number(digitPlaces) : this.digitPlaces
this.type = this.$router.currentRoute.query.type ? this.$router.currentRoute.query.type : ''
this.CriterionType = parseInt(localStorage.getItem('CriterionType'))
this.canvas = this.$refs.canvas
this.canvas.addEventListener('cornerstonenewimage', this.onNewImage)
this.canvas.addEventListener(
'cornerstoneimagerendered',
this.onImageRendered
)
this.canvas.addEventListener(
'cornerstoneimageloaded',
this.onImageLoaded
)
this.canvas.addEventListener(
'cornerstonetoolsclipstopped',
this.onClipStopped
)
this.canvas.addEventListener(
'cornerstonetoolsmeasurementcompleted',
this.onMeasurementcompleted
)
this.canvas.addEventListener(
'cornerstonetoolsmeasurementmodified',
this.onMeasurementmodified
)
// this.canvas.addEventListener(
// 'cornerstonetoolsmeasurementremoved',
// this.onMeasurementremoved
// )
this.canvas.addEventListener('cornerstonetoolsmouseup', this.mouseUp)
this.canvas.addEventListener('cornerstonetoolsmousedown', this.mouseDown)
this.canvas.addEventListener('cornerstonetoolsmouseclick', this.mouseClick)
// this.canvas.addEventListener('click', this.cotextMenuClick)
this.canvas.addEventListener('cornerstonetoolsstackscroll', this.stackScrollCallback)
this.canvas.addEventListener('cornerstonetoolsmousemove', this.mouseMove)
this.canvas.addEventListener('mouseleave', () => {
this.mousePosition.mo = ''
})
// Store.$on('getMeasureData', () => {
// this.getMeasureData()
// console.log('getMeasureData')
// })
DicomEvent.$on('setReadingState', readingTaskState => {
if (readingTaskState === 2) {
this.activeTool = 0
}
this.readingTaskState = readingTaskState
cornerstone.updateImage(this.canvas, true)
})
},
beforeDestroy() {
// Store.$off('getMeasureData')
DicomEvent.$off('setReadingState')
},
methods: {
reloadCanvas() {
console.log('重新渲染')
cornerstone.resize(this.canvas)
},
mouseMove(e) {
const { element, image, currentPoints } = e.detail
const x = Math.round(currentPoints.image.x)
const y = Math.round(currentPoints.image.y)
const stats = {}
if (x >= 0 && y >= 0 && x < image.columns && y < image.rows) {
stats.x = x
stats.y = y
if (image.color) {
stats.storedPixels = this.getRGBPixels(element, x, y, 1, 1)
} else {
stats.storedPixels = cornerstone.getStoredPixels(
element,
x,
y,
1,
1
)
stats.sp = stats.storedPixels[0]
stats.mo = stats.sp * image.slope + image.intercept
}
}
this.mousePosition.x = currentPoints.canvas.x
this.mousePosition.y = currentPoints.canvas.y
this.mousePosition.mo = stats.mo
},
getRGBPixels(element, x, y, width, height) {
if (!element) {
return
}
x = Math.round(x)
y = Math.round(y)
const enabledElement = cornerstone.getEnabledElement(element)
const storedPixelData = []
let index = 0
const pixelData = enabledElement.image.getPixelData()
let spIndex, row, column
if (enabledElement.image.color) {
for (row = 0; row < height; row++) {
for (column = 0; column < width; column++) {
spIndex = ((row + y) * enabledElement.image.columns + (column + x)) * 4
const red = pixelData[spIndex]
const green = pixelData[spIndex + 1]
const blue = pixelData[spIndex + 2]
const alpha = pixelData[spIndex + 3]
storedPixelData[index++] = red
storedPixelData[index++] = green
storedPixelData[index++] = blue
storedPixelData[index++] = alpha
}
}
}
return storedPixelData
},
sliderMousedown(e) {
var boxHeight = this.$refs['sliderBox'].clientHeight
this.sliderInfo.oldB = parseInt(e.srcElement.style.top) * boxHeight / 100
this.sliderInfo.oldM = e.clientY
this.sliderInfo.isMove = true
},
sliderMousemove(e) {
if (!this.sliderInfo.isMove) return
var PX = this.sliderInfo.oldB - (this.sliderInfo.oldM - e.clientY)
var boxHeight = this.$refs['sliderBox'].clientHeight
if (PX < 0) return
if (PX > boxHeight) return
var height = PX * 100 / boxHeight
var index = Math.trunc(this.stack.imageIds.length * this.height / 100)
// if (!cornerstone.imageCache.getImageLoadObject(this.stack.imageIds[index])) return
this.height = height
if (this.stack.currentImageIdIndex !== index) {
scroll(this.canvas, index)
}
},
sliderMouseup(e) {
this.sliderInfo.isMove = false
},
getMeasureData() {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.stack.visitTaskId)
this.measureData = this.visitTaskList[idx].MeasureData
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
const imageId = this.stack.imageIds[this.stack.currentImageIdIndex]
ToolStateManager.clearImageIdToolState(imageId)
cornerstone.updateImage(this.canvas, true)
},
onContextmenu(event) {
if (this.isBaseline || this.readingTaskState >= 2 || this.CriterionType === 10) return false
const x = event.offsetX
const y = event.offsetY
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
var element = cornerstone.getEnabledElement(this.canvas)
var { imageId } = element.image
this.measuredTools.map(toolType => {
const toolState = ToolStateManager.getImageIdToolState(imageId, toolType)
if (!toolState) return
var toolObj = new cornerstoneTools[`${toolType}Tool`]()
var i = toolState.data.findIndex(data => toolObj.pointNearTool(this.canvas, data, { x, y }, 'mouse'))
if (i === -1) return false
var idx = this.measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === toolState.data[i].uuid)
var rowId = null
if (idx > -1) {
rowId = this.measureData[idx].RowId
}
if (rowId) {
this.selectedLesion = toolState.data[i]
this.$contextmenu({
items: [
{
label: 'Split',
divided: true,
onClick: () => {
this.handleSplit()
}
}
// {
// label: 'Merge',
// divided: true,
// children: [
// {
// label: 'T01'
// },
// {
// label: 'T02'
// },
// {
// label: 'T03'
// }
// ]
// }
],
event,
x: event.clientX,
y: event.clientY,
customClass: 'class-a',
zIndex: 3,
minWidth: 100
})
return false
} else {
return false
}
})
},
handleSplit() {
var idx = this.measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === this.selectedLesion.uuid)
if (idx > -1) {
// const loading = this.$loading({ fullscreen: true })
// var params = {
// visitTaskId: this.stack.visitTaskId,
// questionId: this.measureData[idx].QuestionId,
// rowId: this.measureData[idx].RowId
// }
DicomEvent.$emit('split', this.measureData[idx])
// splitLesion(params).then(res => {
// loading.close()
// DicomEvent.$emit('refreshVisitList')
// })
}
},
mouseUp(e) {
console.log('mouseUp')
this.image = e.detail.image
this.getToolStateInfo(e)
},
mouseDown(e) {
console.log('mouseDown')
this.image = e.detail.image
},
getToolStateInfo(e) {
const { element, currentPoints, image } = e.detail
var imageId = image.imageId
var instanceId = imageId.split('/')[imageId.split('/').length - 1]
instanceId = instanceId.split('.')[0]
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
this.measuredTools.map(toolType => {
const toolState = ToolStateManager.getImageIdToolState(e.detail.image.imageId, toolType)
if (toolState) {
var toolObj = new cornerstoneTools[`${toolType}Tool`]()
var i = toolState.data.findIndex(data => toolObj.pointNearTool(element, data, currentPoints.canvas, 'mouse'))
if (i > -1) {
const measureData = {}
measureData.studyId = this.stack.studyId
measureData.seriesId = this.stack.seriesId
measureData.instanceId = instanceId
measureData.data = toolState.data[i]
measureData.type = toolType
measureData.thick = this.dicomInfo.thick
var uuid = toolState.data[i].uuid
var idx = this.measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === uuid)
if (idx > -1) {
var questionInfo = this.measureData[idx]
this.$emit('modifyMeasureData', { measureData, questionInfo })
} else {
// this.$emit('setMeasureData', measureData)
}
}
}
})
},
stackScrollCallback(e) {
const { detail } = e
if (this.isScrollSync) {
this.$emit('scrollSync', { canvasIndex: this.canvasIndex, direction: detail.direction })
}
this.stack.currentImageIdIndex = e.detail.newImageIdIndex
// this.height = (this.stack.currentImageIdIndex) * 100 / (this.stack.imageIds.length - 1)
var priority = new Date(new Date().setHours(23, 59, 59, 999)).getTime()
requestPoolManager.loadAndCacheImagePlus(this.stack.imageIds[this.stack.currentImageIdIndex], this.stack.seriesId, priority)
.then(image => {
this.height = (this.stack.currentImageIdIndex) * 100 / (this.stack.imageIds.length - 1)
// 判断该序列是否下载完成
// var isLoaded = this.getSeriesLoadStatus()
// if (isLoaded === 0 || isLoaded === 1) {
// var maxStep = 5
// var index = e.detail.newImageIdIndex
// var frontLoadImage = this.stack.imageIds.slice(index <= maxStep ? 0 : index - maxStep, index <= maxStep ? index : maxStep)
// var rearLoadImage = this.stack.imageIds.slice(index + 1, index + maxStep)
// const priority = new Date(new Date().setHours(23, 59, 59, 999)).getTime()
// if (detail.direction === -1) {
// // 往前滚动
// console.log('往前滚动')
// for (let i = frontLoadImage - 1; i >= 0; i--) {
// requestPoolManager.loadAndCacheImagePlus(frontLoadImage[i], this.stack.seriesId, priority - 1)
// }
// for (let i = 0; i < rearLoadImage.length; i++) {
// requestPoolManager.loadAndCacheImagePlus(rearLoadImage[i], this.stack.seriesId, priority - 1)
// }
// }
// if (detail.direction === 1) {
// // 往后滚动
// console.log('往后滚动')
// for (let i = rearLoadImage - 1; i >= 0; i--) {
// requestPoolManager.loadAndCacheImagePlus(rearLoadImage[i], this.stack.seriesId, priority - 1)
// }
// for (let i = frontLoadImage - 1; i >= 0; i--) {
// requestPoolManager.loadAndCacheImagePlus(frontLoadImage[i], this.stack.seriesId, priority - 1)
// }
// }
// }
})
.catch((error) => {
console.log(error)
})
},
getSeriesLoadStatus() {
var status = -1
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.stack.visitTaskId)
if (idx === -1) return status
var studyList = this.visitTaskList[idx].StudyList
var studyIdx = studyList.findIndex(study => study.StudyId === this.stack.studyId)
if (studyIdx === -1) return status
var seriesList = studyList[studyIdx].SeriesList
var seriesIdx = seriesList.findIndex(series => series.seriesId === this.stack.seriesId)
if (seriesIdx === -1) return status
return seriesList[seriesIdx].loadStatus ? 1 : 0
},
renderMeasuredData(e) {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.stack.visitTaskId)
this.measureData = this.visitTaskList[idx].MeasureData
const { element } = e.detail
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
this.measureData.forEach(data => {
if (this.activeTool === 2 && this.readingTaskState < 2) {
if (this.activeToolName === data.MeasureData.type) {
cornerstoneTools.setToolActiveForElement(element, data.MeasureData.type, { mouseButtonMask: 1 })
} else {
cornerstoneTools.setToolPassiveForElement(element, data.MeasureData.type, { mouseButtonMask: 1 })
}
} else if (this.activeTool === 1 && this.readingTaskState < 2) {
cornerstoneTools.setToolPassiveForElement(element, data.MeasureData.type, { mouseButtonMask: 1 })
} else {
cornerstoneTools.setToolEnabledForElement(element, data.MeasureData.type, { mouseButtonMask: 1 })
}
if (this.stack.instanceId.includes(data.InstanceId) && data.MeasureData) {
const toolState = ToolStateManager.getImageIdToolState(e.detail.image.imageId, data.MeasureData.type)
if (toolState && toolState.data.length > 0) {
var idx = toolState.data.findIndex(item => item.uuid === data.MeasureData.data.uuid)
if (idx === -1) {
ToolStateManager.addImageIdToolState(e.detail.image.imageId, data.MeasureData.type, data.MeasureData.data)
}
} else {
ToolStateManager.addImageIdToolState(e.detail.image.imageId, data.MeasureData.type, data.MeasureData.data)
}
}
})
},
mouseClick(e) {
const { element, currentPoints } = e.detail
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
this.measuredTools.map(toolType => {
const toolState = ToolStateManager.getImageIdToolState(e.detail.image.imageId, toolType)
if (!toolState) return
var toolObj = new cornerstoneTools[`${toolType}Tool`]()
// toolState.data.forEach(data => {
// // data.color = ''
// })
var i = toolState.data.findIndex(data => toolObj.pointNearTool(element, data, currentPoints.canvas, 'mouse'))
if (i > -1) {
// 设置鼠标选中颜色rgb(0, 255, 0)
// toolState.data[i].color = ''
var idx = this.measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === toolState.data[i].uuid)
if (idx > -1) {
DicomEvent.$emit('setCollapseActive', this.measureData[idx])
}
// toolState.data[i].active = true
// cornerstone.updateImage(element)
}
})
},
loadImageStack(dicomSeries) {
return new Promise(resolve => {
this.isCurrentTask = dicomSeries.isCurrentTask
this.isBaseline = dicomSeries.isBaseline
this.readingTaskState = dicomSeries.readingTaskState
if (this.isCurrentTask && this.readingTaskState < 2) {
this.activeTool = 1
} else {
this.activeTool = 0
}
this.series = dicomSeries
this.stack.seriesId = dicomSeries.seriesId
this.stack.studyId = dicomSeries.studyId
this.stack.seriesNumber = dicomSeries.seriesNumber
this.stack.imageIds = dicomSeries.imageIds
this.stack.currentImageIdIndex = dicomSeries.imageIdIndex ? dicomSeries.imageIdIndex : 0
this.stack.firstImageLoading = true
this.stack.visitTaskId = dicomSeries.visitTaskId
this.stack.taskBlindName = dicomSeries.taskBlindName
this.stack.description = dicomSeries.description
// this.measuredData = dicomSeries.measuredData
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === dicomSeries.visitTaskId)
this.measureData = this.visitTaskList[idx].MeasureData
const imageId = this.stack.imageIds[this.stack.currentImageIdIndex]
var instanceId = imageId.split('/')[imageId.split('/').length - 1]
instanceId = instanceId.split('.')[0]
this.stack.instanceId = instanceId
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
ToolStateManager.clearImageIdToolState(dicomSeries.imageIds)
if (this.toolState.clipPlaying) this.toggleClipPlay()
this.toolState.viewportInvert = false
this.toolState.dicomInfoVisible = false
const element = this.$refs.canvas
cornerstone.enable(element)
element.tabIndex = 0
element.focus()
var scope = this
// cornerstone.imageCache.setMaximumSizeBytes(100000)
// this.loading = true
// const loading = this.$loading({ fullscreen: true })
// cornerstone.loadImage(this.stack.imageIds[this.stack.currentImageIdIndex])
// cornerstone.loadAndCacheImage(this.stack.imageIds[this.stack.currentImageIdIndex])
// .then(image => {
// loading.close()
// scope.onFirstImageLoaded(image)
// resolve()
// }).catch((error) => {
// loading.close()
// if (error.error && error.error.message) {
// this.$message.error(error.error.message)
// }
// resolve()
// })
// var priority = new Date(new Date().setHours(23, 59, 59, 999)).getTime()
// requestPoolManager.loadAndCacheImagePlus(this.stack.imageIds[this.stack.currentImageIdIndex], this.stack.seriesId, priority)
// cornerstone.loadAndCacheImage(this.stack.imageIds[this.stack.currentImageIdIndex])
// requestPoolManager.loadAndCacheImagePlus(this.stack.imageIds[this.stack.currentImageIdIndex], this.stack.seriesId, priority)
cornerstone.loadAndCacheImage(this.stack.imageIds[this.stack.currentImageIdIndex])
.then(image => {
// loading.close()
scope.onFirstImageLoaded(image)
// requestPoolManager.executeTask()
resolve()
})
.catch((error) => {
// loading.close()
if (error.error && error.error.message) {
this.$message.error(error.error.message)
}
resolve()
})
// requestPoolManager.executeTask()
})
},
onFirstImageLoaded(image) {
console.log('onFirstImageLoaded')
const element = this.$refs.canvas
var viewport = cornerstone.getDefaultViewportForImage(this.canvas, image)
cornerstone.displayImage(this.canvas, image, viewport)
if (!this.toolState.initialized) {
this.toolState.initialized = true
const toolButtons = document.querySelectorAll('[data-tool]')
// const scope = this
Array.from(toolButtons).forEach((toolBtn) => {
// Add the tool
const toolName = toolBtn.getAttribute('data-tool')
const apiTool = cornerstoneTools[`${toolName}Tool`]
if (apiTool) {
const toolAlreadyAddedToElement = cornerstoneTools.getToolForElement(element, apiTool)
if (!toolAlreadyAddedToElement) {
if (toolName === 'Length') {
cornerstoneTools.addToolForElement(element, LengthTool, { configuration: { handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true, digits: this.digitPlaces }})
} else if (toolName === 'Bidirectional') {
cornerstoneTools.addToolForElement(element, BidirectionalTool, { digits: this.digitPlaces })
} else if (toolName === 'ArrowAnnotate') {
cornerstoneTools.addToolForElement(element, ArrowAnnotateTool, { configuration: { allowEmptyLabel: true, handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true }})
} else {
cornerstoneTools.addToolForElement(element, apiTool)
}
}
}
})
if (!cornerstoneTools.getToolForElement(element, cornerstoneTools.StackScrollMouseWheelTool)) {
cornerstoneTools.addToolForElement(element, cornerstoneTools.StackScrollMouseWheelTool)
}
cornerstoneTools.setToolActiveForElement(element, 'StackScrollMouseWheel', {})
if (!cornerstoneTools.getToolForElement(element, ScaleOverlayTool)) {
cornerstoneTools.addToolForElement(element, ScaleOverlayTool)
}
cornerstoneTools.setToolActiveForElement(element, 'ScaleOverlay', {})
// if (!cornerstoneTools.getToolForElement(element, OrientationMarkersTool)) {
// cornerstoneTools.addToolForElement(element, OrientationMarkersTool)
// }
// cornerstoneTools.setToolActiveForElement(element, 'OrientationMarkers', { })
}
// cornerstoneTools.addStackStateManager(this.canvas, ['stack', 'stackPrefetch', 'playClip'])
cornerstoneTools.addStackStateManager(this.canvas, ['stack', 'playClip'])
cornerstoneTools.addToolState(this.canvas, 'stack', this.stack)
// cornerstoneTools.stackPrefetch.enable(this.canvas)
cornerstone.updateImage(element, true)
this.stack.firstImageLoading = false
this.toolState.dicomInfoVisible = true
var instanceId = image.imageId.split('/')[image.imageId.split('/').length - 1]
instanceId = instanceId.split('.')[0]
this.stack.instanceId = instanceId
this.resetWwwc()
},
onNewImage(e) {
console.log('cornerstonenewimage')
e.detail.enabledElement.options = {}
var data = e.detail.image.data
this.dicomInfo.hospital = data.string('x00080080')
// this.dicomInfo.pid = data.string('x00100020')
this.dicomInfo.pid = data.string('x00120040')
this.dicomInfo.name = data.string('x00100010')
this.dicomInfo.age = data.string('x00101010')
this.dicomInfo.sex = data.string('x00100040')
this.dicomInfo.acc = data.string('x00080050') // 登记号
this.dicomInfo.modality = data.string('x00080060')
this.dicomInfo.time = this.formatDicomDateTime(
data.string('x00080020'),
data.string('x00080030')
)
this.dicomInfo.series = data.string('x00200011')
this.dicomInfo.frame = `${this.stack.currentImageIdIndex + 1}/${
this.stack.imageIds.length
}`
this.dicomInfo.size = `${data.uint16('x00280010')}*${data.uint16(
'x00280011'
)}`
// var pixel = data.floatString('x00280030')
if (this.dicomInfo.pixel) {
this.dicomInfo.pixel = this.dicomInfo.pixel.toFixed(2)
}
this.dicomInfo.thick = data.floatString('x00180050') // 切片厚度
if (this.dicomInfo.thick) {
this.dicomInfo.thick = this.dicomInfo.thick.toFixed(2)
}
},
formatDicomDateTime(date, time) {
if (date) {
date = `${date.substr(0, 4)}-${date.substr(4, 2)}-${date.substr(6, 2)}`
}
if (time) { time = `${time.substr(0, 2)}:${time.substr(2, 2)}:${time.substr(4, 2)}` }
return time ? `${date} ${time}` : `${date} 00:00:00`
},
onImageLoaded(e) {
console.log('onImageLoaded')
},
onImageRendered(e) {
console.log('onImageRendered')
// const { element } = e.detail
var imageId = e.detail.image.imageId
var instanceId = imageId.split('/')[imageId.split('/').length - 1]
instanceId = instanceId.split('.')[0]
if (this.imageId !== instanceId) {
this.getOrientationMarker(e.detail.element)
this.imageId = instanceId
}
// this.$set(this.markers, 'top', this.orientationMarkers[0])
// this.$set(this.markers, 'right', this.orientationMarkers[1])
// this.$set(this.markers, 'bottom', this.orientationMarkers[2])
// this.$set(this.markers, 'left', this.orientationMarkers[3])
// this.markers.top = this.orientationMarkers[0]
// this.markers.right = this.orientationMarkers[1]
// this.markers.bottom = this.orientationMarkers[2]
// this.markers.left = this.orientationMarkers[3]
this.stack.instanceId = instanceId
var viewport = e.detail.viewport
this.dicomInfo.wwwc = `${Math.round(
viewport.voi.windowWidth
)}/${Math.round(viewport.voi.windowCenter)}` // 窗位
this.dicomInfo.zoom = viewport.scale.toFixed(2)
var data = e.detail.image.data
const position = data.string('x00200032')
this.dicomInfo.location = position ? Number(
position.split('\\')[position.split('\\').length - 1]
).toFixed(2) : ''
this.renderMeasuredData(e)
},
getOrientationMarker(element) {
const enabledElement = cornerstone.getEnabledElement(element)
const imagePlane = cornerstone.metaData.get(
'imagePlaneModule',
enabledElement.image.imageId
)
if (!imagePlane || !imagePlane.rowCosines || !imagePlane.columnCosines) {
return
}
const row = getOrientationString(imagePlane.rowCosines)
const column = getOrientationString(imagePlane.columnCosines)
const oppositeRow = invertOrientationString(row)
const oppositeColumn = invertOrientationString(column)
const markers = {
top: oppositeColumn,
bottom: column,
left: oppositeRow,
right: row
}
if (!markers) {
return
}
this.orientationMarkers = [oppositeColumn, row, column, oppositeRow]
this.originalMarkers = [oppositeColumn, row, column, oppositeRow]
this.setMarkers()
},
onMeasurementcompleted(e) {
// 测量完成
console.log('completed')
this.activeTool = 1
this.activeToolName = ''
// cornerstoneTools.setToolPassiveForElement(element, e.detail.toolName)
var element = cornerstone.getEnabledElement(this.canvas)
var { imageId } = element.image
// var imageId = this.stack.imageIds[this.stack.currentImageIdIndex]
var instanceId = imageId.split('/')[imageId.split('/').length - 1]
instanceId = instanceId.split('.')[0]
if (e.detail.toolName === 'Length' || e.detail.toolName === 'ArrowAnnotate') {
const measureData = {}
measureData.studyId = this.stack.studyId
measureData.seriesId = this.stack.seriesId
measureData.instanceId = instanceId
measureData.data = e.detail.measurementData
measureData.type = e.detail.toolName
measureData.thick = this.dicomInfo.thick
console.log(e.detail.measurementData)
this.$emit('setMeasureData', measureData)
cornerstoneTools.setToolPassiveForElement(this.canvas, e.detail.toolName)
} else if (e.detail.toolName === 'Bidirectional') {
const {
longestDiameter,
shortestDiameter
} = calculateLongestAndShortestDiameters(e.detail.measurementData, element.image, this.digitPlaces)
const measureData = {}
measureData.studyId = this.stack.studyId
measureData.seriesId = this.stack.seriesId
measureData.instanceId = instanceId
measureData.data = e.detail.measurementData
measureData.type = e.detail.toolName
measureData.thick = this.dicomInfo.thick
measureData.data.longestDiameter = longestDiameter
measureData.data.shortestDiameter = shortestDiameter
this.$emit('setMeasureData', measureData)
cornerstoneTools.setToolPassiveForElement(this.canvas, e.detail.toolName)
}
},
onMeasurementremoved(e) {
},
onMeasurementmodified(e) {
// 移动
console.log('modified')
},
measurementMouseUpHandler(e) {
console.log('measurementMouseUp')
},
// updateImage(obj) {
// // const element = this.$refs.canvas
// // this.measuredData = obj.measuredData
// // const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
// // var imageId = `wadouri:/api/instance/content/${obj.instanceId}`
// // ToolStateManager.clearImageIdToolState(imageId)
// // cornerstone.updateImage(element, true)
// },
updateImage(instanceId) {
var i = this.visitTaskList.findIndex(i => i.VisitTaskId === this.stack.visitTaskId)
this.measureData = this.visitTaskList[i].MeasureData
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
var element = cornerstone.getEnabledElement(this.canvas)
var { imageId } = element.image
ToolStateManager.clearImageIdToolState(imageId)
cornerstone.updateImage(element, true)
},
removeToolState(measureData) {
var i = this.visitTaskList.findIndex(i => i.VisitTaskId === this.stack.visitTaskId)
this.measureData = this.visitTaskList[i].MeasureData
var idx = this.measureData.findIndex(item => item.MeasureData && item.MeasureData.data.uuid === measureData.data.uuid)
if (idx > -1) {
this.measureData.splice(idx, 1)
var element = cornerstone.getEnabledElement(this.canvas)
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
var { imageId } = element.image
ToolStateManager.clearImageIdToolState(imageId)
cornerstone.updateImage(element, true)
}
},
getToolForElement(toolName) {
var isExist = false
for (var i = 0; i < cornerstoneTools.store.state.tools.length; i++) {
if (cornerstoneTools.store.state.tools[i].name === toolName) {
isExist = true
break
}
}
return isExist
},
onClipStopped() {
this.toolState.clipPlaying = false
},
onKeyPress(e) {
var key = e.detail.keyCode
var keys = { PageUp: 33, PageDown: 34, End: 35, Home: 36 } // Left: 37, Up: 38, Right: 39, Down: 40
if (key < keys.PageUp || key > keys.Home) return
if (key === keys.Home) this.scrollPage(-9999)
else if (key === keys.PageUp) this.scrollPage(-1)
else if (key === keys.PageDown) this.scrollPage(1)
else if (key === keys.End) this.scrollPage(9999)
},
resizeCanvas() {
cornerstone.resize(this.canvas, true)
},
activateCanvas() {
this.canvas.tabIndex = 0
this.canvas.focus()
},
resetViewport() {
this.toolState.viewportInvert = false
var image = cornerstone.getImage(this.canvas)
cornerstone.setViewport(
this.canvas,
cornerstone.getDefaultViewportForImage(this.canvas, image)
)
},
toggleDicomInfo() {
this.toolState.dicomInfoVisible = !this.toolState.dicomInfoVisible
if (this.toolState.dicomInfoVisible) {
cornerstoneTools.orientationMarkers.enable(this.canvas)
} else cornerstoneTools.orientationMarkers.disable(this.canvas)
cornerstone.updateImage(this.canvas)
},
setColormap(colormap) {
const viewport = cornerstone.getViewport(this.canvas)
viewport.colormap = colormap
cornerstone.setViewport(this.canvas, viewport)
cornerstone.updateImage(this.canvas, true)
if (!colormap) {
this.resetRenderCanvase(this.canvas)
}
},
resetRenderCanvase(element) {
const enabledElement = cornerstone.getEnabledElement(element)
enabledElement.renderingTools.colormapId = undefined
enabledElement.renderingTools.colorLut = undefined
const renderCanvas = enabledElement.renderingTools.renderCanvas
const canvasContext = renderCanvas.getContext('2d')
canvasContext.fillStyle = 'white'
canvasContext.fillRect(0, 0, renderCanvas.width, renderCanvas.height)
const renderCanvasData = canvasContext.getImageData(
0,
0,
renderCanvas.width,
renderCanvas.height
)
enabledElement.renderingTools.renderCanvasContext = canvasContext
enabledElement.renderingTools.renderCanvasData = renderCanvasData
},
scrollPage(offset) {
var index = this.stack.currentImageIdIndex + offset
this.index = this.stack.currentImageIdIndex + offset
if (index < 0) index = 0
else if (index >= this.stack.imageIds.length) {
index = this.stack.imageIds.length - 1
}
if (index !== this.stack.currentImageIdIndex) {
scroll(this.canvas, index)
}
},
toggleClipPlay() {
if (this.toolState.clipPlaying) {
cornerstoneTools.stopClip(this.canvas)
this.toolState.clipPlaying = false
return
}
this.toolState.clipPlaying = true
cornerstoneTools.playClip(this.canvas, this.dicomInfo.fps)
cornerstoneTools.getToolState(
this.canvas,
'playClip'
).data[0].loop = false
},
setFps(fps) {
this.dicomInfo.fps = fps
},
resetWwwc() {
this.toolState.viewportInvert = false
var viewport = cornerstone.getViewport(this.canvas)
viewport.invert = false
var image = cornerstone.getImage(this.canvas)
viewport.voi.windowWidth = image.windowWidth
viewport.voi.windowCenter = image.windowCenter
cornerstone.setViewport(this.canvas, viewport)
},
setWwwc(ww, wc) {
var viewport = cornerstone.getViewport(this.canvas)
viewport.voi.windowWidth = ww
viewport.voi.windowCenter = wc
cornerstone.setViewport(this.canvas, viewport)
},
toggleInvert() {
this.toolState.viewportInvert = !this.toolState.viewportInvert
var viewport = cornerstone.getViewport(this.canvas)
viewport.invert = this.toolState.viewportInvert
cornerstone.setViewport(this.canvas, viewport)
},
activateZoom() {
cornerstoneTools.addTool(cornerstoneTools.ZoomTool, {
configuration: {
invert: false,
preventZoomOutsideImage: false,
minScale: 0.1,
maxScale: 20.0
}
})
cornerstoneTools.setToolActive('Zoom', { mouseButtonMask: 1 })
this.toolState.activeTool = 'zoom'
},
resetRotate() {
this.orientationMarkers = [...this.originalMarkers]
this.setMarkers()
var viewport = cornerstone.getViewport(this.canvas)
viewport.hflip = false
viewport.vflip = false
viewport.rotation = 0
cornerstone.setViewport(this.canvas, viewport)
},
setMarkers() {
var markers = [...this.orientationMarkers]
for (const key in this.markers) {
var v = markers.shift(0)
this.markers[key] = v
}
},
setRotate(hflip, vflip, angle, type) {
var markers = [...this.orientationMarkers]
if (type === 2) {
// 垂直翻转
this.orientationMarkers[1] = markers[3]
this.orientationMarkers[3] = markers[1]
} else if (type === 3) {
// 水平翻转
this.orientationMarkers[0] = markers[2]
this.orientationMarkers[2] = markers[0]
} else if (type === 4) {
// 左转90度
this.orientationMarkers = markers.slice(1, 4).concat(markers[0])
} else if (type === 5) {
// 右转90度
this.orientationMarkers = [markers[3]].concat(markers.slice(0, 3))
}
this.setMarkers()
var viewport = cornerstone.getViewport(this.canvas)
if (hflip) viewport.hflip = !viewport.hflip
if (vflip) viewport.vflip = !viewport.vflip
if (angle !== 0) viewport.rotation += angle
cornerstone.setViewport(this.canvas, viewport)
},
saveImage() {
var uid = cornerstone.getImage(this.canvas).data.string('x00080018')
cornerstoneTools.SaveAs(this.canvas, `${uid}.png`)
},
fitToWindow() {
if (this.stack.seriesNumber) {
cornerstone.fitToWindow(this.canvas)
}
},
fitToImage() {
if (this.stack.seriesNumber) {
const enabledElement = cornerstone.getEnabledElement(this.canvas)
enabledElement.viewport.scale = 1
cornerstone.updateImage(this.canvas)
}
},
removeLabel(item) {
const promise = scroll(this.canvas, item.data.imageIdIndex)
const scope = this
Promise.all([promise]).then(res => {
cornerstoneTools.removeToolState(scope.canvas, item.type, item.data)
cornerstone.updateImage(scope.canvas)
})
},
setToolPassive(toolName) {
// 它们的数据可以被操作,但不能创建。
cornerstoneTools.setToolPassiveForElement(this.canvas, toolName)
this.activeTool = 1
this.activeToolName = ''
},
setToolActive(toolName) {
this.activeTool = 2
// cornerstoneTools.setToolPassiveForElement(this.canvas, 'Bidirectional')
// this.measuredTools.forEach(toolName => {
// console.log(toolName)
// cornerstoneTools.setToolPassiveForElement(this.canvas, toolName)
// })
this.activeToolName = toolName
this.$nextTick(() => {
// console.log(cornerstoneTools.isToolActiveForElement(this.canvas, 'Bidirectional'))
cornerstoneTools.setToolActiveForElement(this.canvas, toolName, {
mouseButtonMask: 1
})
})
},
setToolEnabled(toolName) {
this.activeToolName = ''
// 工具将呈现,但不会对输入作出反应
cornerstoneTools.setToolEnabledForElement(this.canvas, toolName)
this.activeTool = 0
this.readingTaskState = 2
},
setAllToolsPassive() {
cornerstoneTools.store.state.tools.forEach((tool) => {
cornerstoneTools.setToolPassiveForElement(this.canvas, tool.name)
})
},
addTargetElement(synchronizer) {
synchronizer.addTarget(this.$refs.canvas)
},
removeTarget(synchronizer) {
synchronizer.removeTarget(this.$refs.canvas)
},
addSourceElement(synchronizer) {
synchronizer.addSource(this.$refs.canvas)
},
removeSource(synchronizer) {
synchronizer.removeSource(this.$refs.canvas)
},
activeReferenceLine(synchronizer) {
if (
!cornerstoneTools.getToolForElement(
this.canvas,
cornerstoneTools.ReferenceLinesTool
)
) {
cornerstoneTools.addToolForElement(
this.canvas,
cornerstoneTools.ReferenceLinesTool
)
}
cornerstoneTools.setToolEnabledForElement(this.canvas, 'ReferenceLines', {
synchronizationContext: synchronizer
})
// cornerstoneTools.addTool(cornerstoneTools.CrosshairsTool)
// cornerstoneTools.setToolActive('Crosshairs', {
// mouseButtonMask: 1,
// synchronizationContext: synchronizer
// })
},
disabledReferenceLine(synchronizer) {
synchronizer.enabled = false
synchronizer.remove(this.canvas)
cornerstoneTools.setToolDisabledForElement(this.canvas, 'ReferenceLines')
// cornerstoneTools.setToolDisabledForElement(this.canvas, 'Crosshairs')
},
activeViewPortToolSync(synchronizer, toolName) {
synchronizer.add(this.canvas)
synchronizer.enabled = true
if (
!cornerstoneTools.getToolForElement(
this.canvas,
cornerstoneTools[`${toolName}Tool`]
)
) {
cornerstoneTools.addToolForElement(
this.canvas,
cornerstoneTools[`${toolName}Tool`]
)
}
cornerstoneTools.setToolActiveForElement(this.canvas, toolName, {
mouseButtonMask: 1,
synchronizationContext: synchronizer
})
},
disabledViewPortToolSync(synchronizer, toolName) {
synchronizer.enabled = false
synchronizer.remove(this.canvas)
cornerstoneTools.setToolDisabledForElement(this.canvas, toolName)
},
activeImageSync(synchronizer) {
synchronizer.add(this.$refs.canvas)
synchronizer.enabled = true
return false
},
disabledImageSync(synchronizer) {
synchronizer.remove(this.$refs.canvas)
synchronizer.enabled = false
return false
},
activeAnnotationSync(synchronizer) {
this.AnnotationSync = synchronizer
synchronizer.add(this.$refs.canvas)
synchronizer.enabled = true
},
disabledAnnotationSync(synchronizer) {
this.AnnotationSync = null
synchronizer.enabled = false
synchronizer.remove(this.$refs.canvas)
this.setAllToolsPassive()
},
getToolSate() {
const toolROITypes = [
'Probe',
'EllipticalRoi',
'RectangleRoi',
'ArrowAnnotate',
'Length',
'CobbAngle',
'Angle',
'Bidirectional',
'FreehandRoi'
]
for (let i = 0; i < toolROITypes.length; i++) {
const toolROIType = toolROITypes[i]
const toolROIData = JSON.stringify(
cornerstoneTools.getToolState(this.canvas, toolROIType)
)
if (toolROIData !== undefined) {
this.allROIToolData[toolROITypes[i]] = JSON.parse(toolROIData)
}
}
}
}
}
</script>
<style lang="scss" scoped>
.context-menu-wrapper{
position: absolute;
ul{
list-style: none;
margin: 0px;
padding: 0px;
background: #343333;
color: #fff;
margin: 0;
border: 1px solid #2a2a2a;
border-radius: 3px;
height: auto;
min-height: 50px;
line-height: 1.5em;
width:80px;
box-sizing: border-box;
}
.menu{
li {
padding: 2px 5px;
position: relative;
border-bottom: 1px solid #666;
div{
padding: 5px;
}
}
.submenu{
position: absolute;
left: 77px;
top: -1px;
background: #343333;
color: #fff;
display: none;
li {
padding: 2px 5px;
border-bottom: 1px solid #666;
div{
padding: 5px;
}
}
}
}
.menu li:hover{
background-color: #ff5722;
.submenu{
display:block;
}
}
.menu_active{
cursor: pointer;
}
.menu_disabled{
cursor: not-allowed;
}
}
.info-series {
position: absolute;
left: 10px;
top: 10px;
text-align: left;
color: #ddd;
font-size: 12px;
/* z-index: 1; */
}
.info-image {
position: absolute;
left: 10px;
bottom: 10px;
text-align: left;
color: #ddd;
font-size: 12px;
/* z-index: 1; */
}
.info-subject {
position: absolute;
right: 15px;
top: 10px;
text-align: right;
color: #ddd;
font-size: 12px;
/* z-index: 1; */
}
.info-instance {
position: absolute;
right: 15px;
bottom: 10px;
text-align: right;
color: #ddd;
font-size: 12px;
/* z-index: 1; */
}
.load-indicator {
position: absolute;
left: 10px;
top: 10px;
text-align: left;
/* z-index: 1; */
}
.magnifyTool {
border: 2px solid #ffffff;
border-radius: 50%;
display: none;
cursor: none;
}
.menu__item {
display: block;
line-height: 20px;
text-align: center;
margin: 10px;
cursor: default;
}
.menu__item:hover {
color: #ff0000;
}
.menu {
height: auto;
width: auto;
position: absolute;
font-size: 14px;
text-align: left;
border-radius: 10px;
border: 1px solid #c21111;
background-color: #ffffff;
}
li:hover {
background-color: #e0e0e2;
color: white;
}
.msg-div {
position: absolute;
z-index: 10;
background-color: rgba(255, 255, 255, 0.5);
color: #000;
padding: 5px 20px;
}
</style>