@cornerstonejs/core
Version:
Cornerstone3D Core
158 lines (157 loc) • 5.38 kB
JavaScript
import vtkImageData from '@kitware/vtk.js/Common/DataModel/ImageData.js';
import imageIdToURI from '../../utilities/imageIdToURI.js';
import VoxelManager from '../../utilities/VoxelManager.js';
import { vtkStreamingOpenGLTexture } from '../../RenderingEngine/vtkClasses/index.js';
import cache from '../cache.js';
export class ImageVolume {
get numTimePoints() {
return typeof this.numDimensionGroups === 'number'
? this.numDimensionGroups
: 1;
}
constructor(props) {
this._imageIdsIndexMap = new Map();
this._imageURIsIndexMap = new Map();
this.cornerstoneImageMetaData = null;
this.isPreScaled = false;
this.numFrames = null;
const { imageIds, scaling, dimensions, spacing, origin, direction, dataType, volumeId, referencedVolumeId, metadata, referencedImageIds, additionalDetails, voxelManager, numberOfComponents, } = props;
if (!dataType) {
throw new Error('Data type is required, please provide a data type as string such as "Uint8Array", "Float32Array", etc.');
}
let { imageData } = props;
this.suppressWarnings = true;
this.imageIds = imageIds;
this.volumeId = volumeId;
this.metadata = metadata;
this.dimensions = dimensions;
this.spacing = spacing;
this.origin = origin;
this.direction = direction;
this.dataType = dataType;
this.hasPixelSpacing =
Number.isFinite(spacing[0]) &&
spacing[0] > 0 &&
Number.isFinite(spacing[1]) &&
spacing[1] > 0;
this.vtkOpenGLTexture = vtkStreamingOpenGLTexture.newInstance();
this.vtkOpenGLTexture.setVolumeId(volumeId);
this.voxelManager =
voxelManager ??
VoxelManager.createImageVolumeVoxelManager({
dimensions,
imageIds,
numberOfComponents,
id: volumeId,
});
this.numVoxels =
this.dimensions[0] * this.dimensions[1] * this.dimensions[2];
if (!imageData) {
imageData = vtkImageData.newInstance();
imageData.setDimensions(dimensions);
imageData.setSpacing(spacing);
imageData.setDirection(direction);
imageData.setOrigin(origin);
}
imageData.set({
dataType: dataType,
voxelManager: this.voxelManager,
id: volumeId,
numberOfComponents: numberOfComponents || 1,
}, this.suppressWarnings);
imageData.set({
hasScalarVolume: false,
}, this.suppressWarnings);
this.imageData = imageData;
this.numFrames = this._getNumFrames();
this._reprocessImageIds();
if (scaling) {
this.scaling = scaling;
}
if (referencedVolumeId) {
this.referencedVolumeId = referencedVolumeId;
}
if (referencedImageIds) {
this.referencedImageIds = referencedImageIds;
}
if (additionalDetails) {
this.additionalDetails = additionalDetails;
}
}
get sizeInBytes() {
return this.voxelManager.sizeInBytes;
}
get imageIds() {
return this._imageIds;
}
set imageIds(newImageIds) {
this._imageIds = newImageIds;
this._reprocessImageIds();
}
_reprocessImageIds() {
this._imageIdsIndexMap.clear();
this._imageURIsIndexMap.clear();
this._imageIds.forEach((imageId, i) => {
const imageURI = imageIdToURI(imageId);
this._imageIdsIndexMap.set(imageId, i);
this._imageURIsIndexMap.set(imageURI, i);
});
}
isDynamicVolume() {
if (this.numTimePoints) {
return this.numTimePoints > 1;
}
return false;
}
getImageIdIndex(imageId) {
return this._imageIdsIndexMap.get(imageId);
}
getImageIdByIndex(imageIdIndex) {
return this._imageIds[imageIdIndex];
}
getImageURIIndex(imageURI) {
return this._imageURIsIndexMap.get(imageURI);
}
load(callback) {
}
destroy() {
this.imageData.delete();
this.imageData = null;
this.voxelManager.clear();
this.vtkOpenGLTexture.releaseGraphicsResources();
this.vtkOpenGLTexture.delete();
}
invalidate() {
for (let i = 0; i < this.imageIds.length; i++) {
this.vtkOpenGLTexture.setUpdatedFrame(i);
}
this.imageData.modified();
}
modified() {
this.imageData.modified();
this.vtkOpenGLTexture.modified();
this.numFrames = this._getNumFrames();
}
removeFromCache() {
cache.removeVolumeLoadObject(this.volumeId);
}
getScalarDataLength() {
return this.voxelManager.getScalarDataLength();
}
_getNumFrames() {
if (!this.isDynamicVolume()) {
return this.imageIds.length;
}
return this.numTimePoints;
}
imageIdIndexToFrameIndex(imageIdIndex) {
return imageIdIndex % this.numFrames;
}
getCornerstoneImages() {
const { imageIds } = this;
return imageIds.map((imageId) => {
return cache.getImage(imageId);
});
}
}
export default ImageVolume;