|
|
|
|
@ -15,7 +15,7 @@
|
|
|
|
|
<div v-show="dicomInfo.thick">Slice Thickness {{ dicomInfo.thick }}mm</div>
|
|
|
|
|
<div>WW/WC {{ dicomInfo.wwwc }}</div>
|
|
|
|
|
<div>Zoom {{ dicomInfo.zoom }}</div>
|
|
|
|
|
<div v-show="dicomInfo.location">Location {{ dicomInfo.location }}mm</div> -->
|
|
|
|
|
<div v-show="dicomInfo.location">Location {{ dicomInfo.location }}mm</div>-->
|
|
|
|
|
<!-- <div v-show="toolState.clipPlaying">FPS {{ dicomInfo.fps }}</div> -->
|
|
|
|
|
<div v-show="mousePosition.mo">
|
|
|
|
|
Pos: {{ mousePosition.x ? mousePosition.x.toFixed(0) : '' }}, {{ mousePosition.y ? mousePosition.y.toFixed(0) :
|
|
|
|
|
@ -23,17 +23,11 @@
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
v-if="(dicomInfo.modality === 'CT' || dicomInfo.modality === 'DR' || dicomInfo.modality === 'CR') && mousePosition.mo">
|
|
|
|
|
HU: {{ mousePosition.mo }}
|
|
|
|
|
</div>
|
|
|
|
|
<div v-else-if="(dicomInfo.modality === 'PT' && mousePosition.suv)">
|
|
|
|
|
SUVbw(g/ml): {{ mousePosition.suv.toFixed(3) }}
|
|
|
|
|
</div>
|
|
|
|
|
<div v-else-if="mousePosition.mo">
|
|
|
|
|
Density: {{ mousePosition.mo }}
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
W*H: {{ dicomInfo.size }}
|
|
|
|
|
</div>
|
|
|
|
|
HU: {{ mousePosition.mo }}</div>
|
|
|
|
|
<div v-else-if="(dicomInfo.modality === 'PT' && mousePosition.suv)">SUVbw(g/ml): {{ mousePosition.suv.toFixed(3)
|
|
|
|
|
}}</div>
|
|
|
|
|
<div v-else-if="mousePosition.mo">Density: {{ mousePosition.mo }}</div>
|
|
|
|
|
<div>W*H: {{ dicomInfo.size }}</div>
|
|
|
|
|
|
|
|
|
|
<div>Zoom: {{ dicomInfo.zoom }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
@ -56,24 +50,16 @@
|
|
|
|
|
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%;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 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.pixel">
|
|
|
|
|
Pixel: {{ dicomInfo.pixel }}mm
|
|
|
|
|
</div> -->
|
|
|
|
|
</div>-->
|
|
|
|
|
<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>
|
|
|
|
|
@ -101,6 +87,7 @@ import invertOrientationString from '@/views/trials/trials-panel/reading/dicoms/
|
|
|
|
|
import calculateSUV from '@/views/trials/trials-panel/reading/dicoms/tools/calculateSUV'
|
|
|
|
|
// import requestPoolManager from '@/utils/request-pool'
|
|
|
|
|
import ScaleOverlayTool from '@/views/trials/trials-panel/reading/dicoms/tools/ScaleOverlay/ScaleOverlayTool'
|
|
|
|
|
import Note_RectangleRoiTool from '@/views/trials/trials-panel/reading/dicoms/tools/RectangleRoi/Note_RectangleRoiTool'
|
|
|
|
|
cornerstoneTools.external.cornerstone = cornerstone
|
|
|
|
|
cornerstoneTools.external.Hammer = Hammer
|
|
|
|
|
cornerstoneTools.external.cornerstoneMath = cornerstoneMath
|
|
|
|
|
@ -117,7 +104,7 @@ export default {
|
|
|
|
|
computed: {
|
|
|
|
|
NSTip() {
|
|
|
|
|
return `${this.$store.state.trials.downloadSize}, NS: ${this.$store.state.trials.downloadTip}`
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
@ -130,7 +117,7 @@ export default {
|
|
|
|
|
seriesNumber: '',
|
|
|
|
|
imageIds: [],
|
|
|
|
|
currentImageIdIndex: 0,
|
|
|
|
|
firstImageLoading: false
|
|
|
|
|
firstImageLoading: false,
|
|
|
|
|
// preventCache: true
|
|
|
|
|
},
|
|
|
|
|
dicomInfo: {
|
|
|
|
|
@ -150,14 +137,14 @@ export default {
|
|
|
|
|
wwwc: '',
|
|
|
|
|
zoom: 0,
|
|
|
|
|
location: '',
|
|
|
|
|
fps: 5
|
|
|
|
|
fps: 5,
|
|
|
|
|
},
|
|
|
|
|
toolState: {
|
|
|
|
|
initialized: false,
|
|
|
|
|
activeTool: 'none',
|
|
|
|
|
dicomInfoVisible: false,
|
|
|
|
|
clipPlaying: false,
|
|
|
|
|
viewportInvert: false
|
|
|
|
|
viewportInvert: false,
|
|
|
|
|
},
|
|
|
|
|
loadImagePromise: null,
|
|
|
|
|
AnnotationSync: null,
|
|
|
|
|
@ -168,18 +155,20 @@ export default {
|
|
|
|
|
sliderInfo: {
|
|
|
|
|
oldB: null,
|
|
|
|
|
oldM: null,
|
|
|
|
|
isMove: false
|
|
|
|
|
isMove: false,
|
|
|
|
|
},
|
|
|
|
|
mousePosition: { x: '', y: '', mo: '' },
|
|
|
|
|
markers: { top: '', right: '', bottom: '', left: '' },
|
|
|
|
|
orientationMarkers: [],
|
|
|
|
|
originalMarkers: [],
|
|
|
|
|
dcmTag: { visible: false, title: this.$t('trials:dicom-tag:title') }
|
|
|
|
|
dcmTag: { visible: false, title: this.$t('trials:dicom-tag:title') },
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
mounted() {
|
|
|
|
|
this.type = this.$router.currentRoute.query.type ? this.$router.currentRoute.query.type : ''
|
|
|
|
|
this.type = this.$router.currentRoute.query.type
|
|
|
|
|
? this.$router.currentRoute.query.type
|
|
|
|
|
: ''
|
|
|
|
|
this.canvas = this.$refs.canvas
|
|
|
|
|
this.canvas.addEventListener('cornerstonenewimage', this.onNewImage)
|
|
|
|
|
this.canvas.addEventListener(
|
|
|
|
|
@ -200,7 +189,10 @@ export default {
|
|
|
|
|
document.addEventListener('mousemove', (e) => {
|
|
|
|
|
this.sliderMousemove(e)
|
|
|
|
|
})
|
|
|
|
|
this.canvas.addEventListener('cornerstonetoolsstackscroll', this.stackScrollCallback)
|
|
|
|
|
this.canvas.addEventListener(
|
|
|
|
|
'cornerstonetoolsstackscroll',
|
|
|
|
|
this.stackScrollCallback
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
methods: {
|
|
|
|
|
@ -210,7 +202,11 @@ export default {
|
|
|
|
|
this.stack.seriesId = dicomSeries.seriesId
|
|
|
|
|
this.stack.seriesNumber = dicomSeries.seriesNumber
|
|
|
|
|
this.stack.imageIds = dicomSeries.imageIds
|
|
|
|
|
this.stack.currentImageIdIndex = dicomSeries.imageIdIndex && dicomSeries.imageIdIndex < dicomSeries.imageIds.length ? dicomSeries.imageIdIndex : 0
|
|
|
|
|
this.stack.currentImageIdIndex =
|
|
|
|
|
dicomSeries.imageIdIndex &&
|
|
|
|
|
dicomSeries.imageIdIndex < dicomSeries.imageIds.length
|
|
|
|
|
? dicomSeries.imageIdIndex
|
|
|
|
|
: 0
|
|
|
|
|
this.stack.firstImageLoading = true
|
|
|
|
|
this.stack.description = dicomSeries.description
|
|
|
|
|
this.toolState.viewportInvert = false
|
|
|
|
|
@ -226,13 +222,17 @@ export default {
|
|
|
|
|
this.toolState.clipPlaying = false
|
|
|
|
|
this.loading = true
|
|
|
|
|
|
|
|
|
|
cornerstone.loadAndCacheImage(this.stack.imageIds[this.stack.currentImageIdIndex])
|
|
|
|
|
.then(image => {
|
|
|
|
|
cornerstone
|
|
|
|
|
.loadAndCacheImage(
|
|
|
|
|
this.stack.imageIds[this.stack.currentImageIdIndex]
|
|
|
|
|
)
|
|
|
|
|
.then((image) => {
|
|
|
|
|
this.loading = false
|
|
|
|
|
if (this.stack.imageIds.indexOf(image.imageId) !== -1) {
|
|
|
|
|
this.onFirstImageLoaded(image)
|
|
|
|
|
}
|
|
|
|
|
}).catch((error) => {
|
|
|
|
|
})
|
|
|
|
|
.catch((error) => {
|
|
|
|
|
this.loading = false
|
|
|
|
|
if (error.error && error.error.message) {
|
|
|
|
|
this.$alert(error.error.message)
|
|
|
|
|
@ -255,15 +255,17 @@ export default {
|
|
|
|
|
const apiTool = cornerstoneTools[`${toolName}Tool`]
|
|
|
|
|
|
|
|
|
|
if (apiTool) {
|
|
|
|
|
const toolAlreadyAddedToElement = cornerstoneTools.getToolForElement(
|
|
|
|
|
element,
|
|
|
|
|
apiTool
|
|
|
|
|
)
|
|
|
|
|
const toolAlreadyAddedToElement =
|
|
|
|
|
cornerstoneTools.getToolForElement(element, apiTool)
|
|
|
|
|
if (!toolAlreadyAddedToElement) {
|
|
|
|
|
if (toolName === 'RectangleRoi') {
|
|
|
|
|
cornerstoneTools.addToolForElement(element, apiTool, { configuration: { showMinMax: true, showStatsText: true } })
|
|
|
|
|
cornerstoneTools.addToolForElement(element, apiTool, {
|
|
|
|
|
configuration: { showMinMax: true, showStatsText: true },
|
|
|
|
|
})
|
|
|
|
|
} else if (toolName === 'EllipticalRoi') {
|
|
|
|
|
cornerstoneTools.addToolForElement(element, apiTool, { configuration: { showMinMax: true } })
|
|
|
|
|
cornerstoneTools.addToolForElement(element, apiTool, {
|
|
|
|
|
configuration: { showMinMax: true },
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
cornerstoneTools.addToolForElement(element, apiTool)
|
|
|
|
|
}
|
|
|
|
|
@ -287,8 +289,28 @@ export default {
|
|
|
|
|
false
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
if (!cornerstoneTools.getToolForElement(element, cornerstoneTools.WwwcRegionTool)) {
|
|
|
|
|
cornerstoneTools.addToolForElement(element, cornerstoneTools.WwwcRegionTool)
|
|
|
|
|
if (
|
|
|
|
|
!cornerstoneTools.getToolForElement(element, Note_RectangleRoiTool)
|
|
|
|
|
) {
|
|
|
|
|
cornerstoneTools.addToolForElement(element, Note_RectangleRoiTool, {
|
|
|
|
|
configuration: {
|
|
|
|
|
color: '#f00',
|
|
|
|
|
lineWidth: 0.5,
|
|
|
|
|
drawHandles: false,
|
|
|
|
|
fillColor: 'rgba(0, 0, 0, 1)',
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
if (
|
|
|
|
|
!cornerstoneTools.getToolForElement(
|
|
|
|
|
element,
|
|
|
|
|
cornerstoneTools.WwwcRegionTool
|
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
cornerstoneTools.addToolForElement(
|
|
|
|
|
element,
|
|
|
|
|
cornerstoneTools.WwwcRegionTool
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
if (
|
|
|
|
|
!cornerstoneTools.getToolForElement(
|
|
|
|
|
@ -347,7 +369,9 @@ export default {
|
|
|
|
|
// var instanceId = image.imageId.split('/')[image.imageId.split('/').length - 1]
|
|
|
|
|
// instanceId = instanceId.split('.')[0]
|
|
|
|
|
// this.stack.instanceId = instanceId
|
|
|
|
|
this.height = (this.stack.currentImageIdIndex) * 100 / (this.stack.imageIds.length - 1)
|
|
|
|
|
this.height =
|
|
|
|
|
(this.stack.currentImageIdIndex * 100) /
|
|
|
|
|
(this.stack.imageIds.length - 1)
|
|
|
|
|
this.resetWwwc()
|
|
|
|
|
},
|
|
|
|
|
onNewImage(e) {
|
|
|
|
|
@ -379,21 +403,30 @@ export default {
|
|
|
|
|
if (this.dicomInfo.thick) {
|
|
|
|
|
this.dicomInfo.thick = this.dicomInfo.thick.toFixed(2)
|
|
|
|
|
}
|
|
|
|
|
const newImageIdIndex = this.stack.imageIds.findIndex(i => i === e.detail.image.imageId)
|
|
|
|
|
const newImageIdIndex = this.stack.imageIds.findIndex(
|
|
|
|
|
(i) => i === e.detail.image.imageId
|
|
|
|
|
)
|
|
|
|
|
if (newImageIdIndex === -1) return
|
|
|
|
|
this.stack.currentImageIdIndex = newImageIdIndex
|
|
|
|
|
this.stack.imageIdIndex = newImageIdIndex
|
|
|
|
|
this.series.imageIdIndex = newImageIdIndex
|
|
|
|
|
this.height = (this.stack.currentImageIdIndex) * 100 / (this.stack.imageIds.length - 1)
|
|
|
|
|
this.height =
|
|
|
|
|
(this.stack.currentImageIdIndex * 100) /
|
|
|
|
|
(this.stack.imageIds.length - 1)
|
|
|
|
|
this.resetWwwc()
|
|
|
|
|
},
|
|
|
|
|
stackScrollCallback(e) {
|
|
|
|
|
const { detail } = e
|
|
|
|
|
if (this.isScrollSync) {
|
|
|
|
|
this.$emit('scrollSync', { canvasIndex: this.canvasIndex, direction: detail.direction })
|
|
|
|
|
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)
|
|
|
|
|
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)
|
|
|
|
|
@ -408,7 +441,9 @@ export default {
|
|
|
|
|
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)}` }
|
|
|
|
|
if (time) {
|
|
|
|
|
time = `${time.substr(0, 2)}:${time.substr(2, 2)}:${time.substr(4, 2)}`
|
|
|
|
|
}
|
|
|
|
|
return time ? `${date} ${time}` : `${date} 00:00:00`
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
@ -453,7 +488,7 @@ export default {
|
|
|
|
|
top: oppositeColumn,
|
|
|
|
|
bottom: column,
|
|
|
|
|
left: oppositeRow,
|
|
|
|
|
right: row
|
|
|
|
|
right: row,
|
|
|
|
|
}
|
|
|
|
|
if (!markers) {
|
|
|
|
|
return
|
|
|
|
|
@ -500,13 +535,7 @@ export default {
|
|
|
|
|
if (image.color) {
|
|
|
|
|
stats.storedPixels = this.getRGBPixels(element, x, y, 1, 1)
|
|
|
|
|
} else {
|
|
|
|
|
stats.storedPixels = cornerstone.getStoredPixels(
|
|
|
|
|
element,
|
|
|
|
|
x,
|
|
|
|
|
y,
|
|
|
|
|
1,
|
|
|
|
|
1
|
|
|
|
|
)
|
|
|
|
|
stats.storedPixels = cornerstone.getStoredPixels(element, x, y, 1, 1)
|
|
|
|
|
stats.sp = stats.storedPixels[0]
|
|
|
|
|
stats.mo = stats.sp * image.slope + image.intercept
|
|
|
|
|
stats.suv = calculateSUV(image, stats.sp)
|
|
|
|
|
@ -533,7 +562,8 @@ export default {
|
|
|
|
|
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
|
|
|
|
|
spIndex =
|
|
|
|
|
((row + y) * enabledElement.image.columns + (column + x)) * 4
|
|
|
|
|
const red = pixelData[spIndex]
|
|
|
|
|
const green = pixelData[spIndex + 1]
|
|
|
|
|
const blue = pixelData[spIndex + 2]
|
|
|
|
|
@ -551,7 +581,8 @@ export default {
|
|
|
|
|
},
|
|
|
|
|
sliderMousedown(e) {
|
|
|
|
|
var boxHeight = this.$refs['sliderBox'].clientHeight
|
|
|
|
|
this.sliderInfo.oldB = parseInt(e.srcElement.style.top) * boxHeight / 100
|
|
|
|
|
this.sliderInfo.oldB =
|
|
|
|
|
(parseInt(e.srcElement.style.top) * boxHeight) / 100
|
|
|
|
|
this.sliderInfo.oldM = e.clientY
|
|
|
|
|
this.sliderInfo.isMove = true
|
|
|
|
|
e.stopImmediatePropagation()
|
|
|
|
|
@ -564,9 +595,14 @@ export default {
|
|
|
|
|
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)
|
|
|
|
|
index = index > this.stack.imageIds.length ? this.stack.imageIds.length : index < 0 ? 0 : index
|
|
|
|
|
var height = (PX * 100) / boxHeight
|
|
|
|
|
var index = Math.trunc((this.stack.imageIds.length * this.height) / 100)
|
|
|
|
|
index =
|
|
|
|
|
index > this.stack.imageIds.length
|
|
|
|
|
? this.stack.imageIds.length
|
|
|
|
|
: index < 0
|
|
|
|
|
? 0
|
|
|
|
|
: index
|
|
|
|
|
// if (!cornerstone.imageCache.getImageLoadObject(this.stack.imageIds[index])) return
|
|
|
|
|
this.height = height
|
|
|
|
|
if (this.stack.currentImageIdIndex !== index) {
|
|
|
|
|
@ -578,9 +614,9 @@ export default {
|
|
|
|
|
},
|
|
|
|
|
goViewer(e) {
|
|
|
|
|
// console.log(this.$refs['sliderBox'].clientHeight)
|
|
|
|
|
var height = e.offsetY * 100 / this.$refs['sliderBox'].clientHeight
|
|
|
|
|
var height = (e.offsetY * 100) / this.$refs['sliderBox'].clientHeight
|
|
|
|
|
this.height = height
|
|
|
|
|
var index = Math.trunc(this.stack.imageIds.length * this.height / 100)
|
|
|
|
|
var index = Math.trunc((this.stack.imageIds.length * this.height) / 100)
|
|
|
|
|
scroll(this.canvas, index)
|
|
|
|
|
},
|
|
|
|
|
onClipStopped() {
|
|
|
|
|
@ -673,10 +709,7 @@ export default {
|
|
|
|
|
}
|
|
|
|
|
this.toolState.clipPlaying = true
|
|
|
|
|
cornerstoneTools.playClip(this.canvas, this.dicomInfo.fps)
|
|
|
|
|
cornerstoneTools.getToolState(
|
|
|
|
|
this.canvas,
|
|
|
|
|
'playClip'
|
|
|
|
|
).data[0].loop = true
|
|
|
|
|
cornerstoneTools.getToolState(this.canvas, 'playClip').data[0].loop = true
|
|
|
|
|
},
|
|
|
|
|
setFps(fps) {
|
|
|
|
|
this.dicomInfo.fps = fps
|
|
|
|
|
@ -712,8 +745,8 @@ export default {
|
|
|
|
|
invert: false,
|
|
|
|
|
preventZoomOutsideImage: false,
|
|
|
|
|
minScale: 0.1,
|
|
|
|
|
maxScale: 20.0
|
|
|
|
|
}
|
|
|
|
|
maxScale: 20.0,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
cornerstoneTools.setToolActive('Zoom', { mouseButtonMask: 1 })
|
|
|
|
|
this.toolState.activeTool = 'zoom'
|
|
|
|
|
@ -797,9 +830,110 @@ export default {
|
|
|
|
|
setToolPassive(toolName) {
|
|
|
|
|
cornerstoneTools.setToolPassiveForElement(this.canvas, toolName)
|
|
|
|
|
},
|
|
|
|
|
async reloadImage(newImageId = null) {
|
|
|
|
|
// 1. 获取当前imageId(如果未指定新imageId)
|
|
|
|
|
let element = this.canvas
|
|
|
|
|
this.stack.imageIds.splice(this.stack.currentImageIdIndex, 1, newImageId)
|
|
|
|
|
const currentImageId =
|
|
|
|
|
newImageId || cornerstone.getImage(element)?.imageId
|
|
|
|
|
|
|
|
|
|
if (!currentImageId) {
|
|
|
|
|
console.error('没有找到可用的imageId')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. 清除该影像关联的工具状态(标注数据)
|
|
|
|
|
this.clearToolStateForImage(element, currentImageId)
|
|
|
|
|
|
|
|
|
|
// 3. 从缓存中移除该影像
|
|
|
|
|
this.removeImageFromCache(currentImageId)
|
|
|
|
|
|
|
|
|
|
// 4. 重新加载并渲染
|
|
|
|
|
await this.loadAndRenderImage(element, currentImageId)
|
|
|
|
|
},
|
|
|
|
|
clearToolStateForImage(element, imageId) {
|
|
|
|
|
// 获取全局状态管理器
|
|
|
|
|
const globalToolStateManager =
|
|
|
|
|
cornerstoneTools.globalImageIdSpecificToolStateManager
|
|
|
|
|
|
|
|
|
|
if (globalToolStateManager) {
|
|
|
|
|
// 方式1:清空该影像的全部工具数据
|
|
|
|
|
globalToolStateManager.clearImageIdToolState(imageId)
|
|
|
|
|
console.log(`已清除影像 ${imageId} 的所有标注数据`)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 方式2:如果使用元素级别的状态管理器
|
|
|
|
|
const elementToolStateManager =
|
|
|
|
|
cornerstoneTools.getElementToolStateManager(element)
|
|
|
|
|
if (elementToolStateManager && elementToolStateManager.get(element)) {
|
|
|
|
|
// 清空该元素上当前显示影像的数据
|
|
|
|
|
elementToolStateManager.clear(element)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
removeImageFromCache(imageId) {
|
|
|
|
|
const imageCache = cornerstone.imageCache
|
|
|
|
|
|
|
|
|
|
if (imageCache && imageCache[imageId]) {
|
|
|
|
|
// 从缓存中移除
|
|
|
|
|
delete imageCache[imageId]
|
|
|
|
|
console.log(`已从缓存中移除影像: ${imageId}`)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 也可以使用官方API(如果可用)
|
|
|
|
|
if (typeof cornerstone.imageCache.removeImage === 'function') {
|
|
|
|
|
cornerstone.imageCache.removeImageLoadObject(imageId)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
async loadAndRenderImage(element, imageId) {
|
|
|
|
|
try {
|
|
|
|
|
// 1. 清除当前画布内容(可选)
|
|
|
|
|
const canvas = element.querySelector('canvas')
|
|
|
|
|
if (canvas) {
|
|
|
|
|
const ctx = canvas.getContext('2d')
|
|
|
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. 重新加载图像(强制从源头重新获取)
|
|
|
|
|
const image = await cornerstone.loadAndCacheImage(imageId)
|
|
|
|
|
|
|
|
|
|
// 3. 获取或创建视口设置
|
|
|
|
|
let viewport = cornerstone.getViewport(element)
|
|
|
|
|
if (!viewport) {
|
|
|
|
|
viewport = cornerstone.getDefaultViewport(element, image)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 4. 显示图像
|
|
|
|
|
cornerstone.displayImage(element, image, viewport)
|
|
|
|
|
|
|
|
|
|
// 5. 触发重绘
|
|
|
|
|
cornerstone.updateImage(element)
|
|
|
|
|
|
|
|
|
|
console.log(`影像 ${imageId} 重新加载并渲染完成`)
|
|
|
|
|
|
|
|
|
|
return image
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('加载图像失败:', error)
|
|
|
|
|
throw error
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
getNote_RectangleRoi() {
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
|
let toolInfo = cornerstoneTools.getToolState(this.canvas, 'Note_RectangleRoi')
|
|
|
|
|
let image = cornerstone.getImage(this.canvas)
|
|
|
|
|
resolve({ toolInfo, image })
|
|
|
|
|
})
|
|
|
|
|
// console.log(
|
|
|
|
|
// cornerstoneTools.getToolState(this.canvas, 'Note_RectangleRoi')
|
|
|
|
|
// )
|
|
|
|
|
// console.log(cornerstone.getImage(this.canvas))
|
|
|
|
|
// let image = cornerstone.getImage(this.canvas)
|
|
|
|
|
// // cornerstone.imageCache.removeImageLoadObject(image.imageId)
|
|
|
|
|
|
|
|
|
|
// this.reloadImage(this.canvas, image.imageId)
|
|
|
|
|
},
|
|
|
|
|
setToolActive(toolName) {
|
|
|
|
|
cornerstoneTools.setToolActiveForElement(this.canvas, toolName, {
|
|
|
|
|
mouseButtonMask: 1
|
|
|
|
|
mouseButtonMask: 1,
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
setAllToolsPassive() {
|
|
|
|
|
@ -833,7 +967,7 @@ export default {
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
cornerstoneTools.setToolEnabledForElement(this.canvas, 'ReferenceLines', {
|
|
|
|
|
synchronizationContext: synchronizer
|
|
|
|
|
synchronizationContext: synchronizer,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// cornerstoneTools.addTool(cornerstoneTools.CrosshairsTool)
|
|
|
|
|
@ -864,7 +998,7 @@ export default {
|
|
|
|
|
}
|
|
|
|
|
cornerstoneTools.setToolActiveForElement(this.canvas, toolName, {
|
|
|
|
|
mouseButtonMask: 1,
|
|
|
|
|
synchronizationContext: synchronizer
|
|
|
|
|
synchronizationContext: synchronizer,
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
disabledViewPortToolSync(synchronizer, toolName) {
|
|
|
|
|
@ -1095,7 +1229,7 @@ export default {
|
|
|
|
|
'CobbAngle',
|
|
|
|
|
'Angle',
|
|
|
|
|
'Bidirectional',
|
|
|
|
|
'FreehandRoi'
|
|
|
|
|
'FreehandRoi',
|
|
|
|
|
]
|
|
|
|
|
for (let i = 0; i < toolROITypes.length; i++) {
|
|
|
|
|
const toolROIType = toolROITypes[i]
|
|
|
|
|
@ -1115,12 +1249,12 @@ export default {
|
|
|
|
|
removeLabel(item) {
|
|
|
|
|
const promise = scroll(this.canvas, item.data.imageIdIndex)
|
|
|
|
|
const scope = this
|
|
|
|
|
Promise.all([promise]).then(res => {
|
|
|
|
|
Promise.all([promise]).then((res) => {
|
|
|
|
|
cornerstoneTools.removeToolState(scope.canvas, item.type, item.data)
|
|
|
|
|
cornerstone.updateImage(scope.canvas)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|