@cornerstonejs/core
Version:
Cornerstone3D Core
131 lines (130 loc) • 5.9 kB
JavaScript
import vtkDataArray from '@kitware/vtk.js/Common/Core/DataArray.js';
import vtkImageData from '@kitware/vtk.js/Common/DataModel/ImageData.js';
import vtkColorTransferFunction from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction.js';
import { InterpolationType, VOILUTFunctionType } from '../../enums/index.js';
import createLinearRGBTransferFunction from '../../utilities/createLinearRGBTransferFunction.js';
import createSigmoidRGBTransferFunction from '../../utilities/createSigmoidRGBTransferFunction.js';
import getVOIRangeFromWindowLevel from '../../utilities/getVOIRangeFromWindowLevel.js';
import isPTPrescaledWithSUV from '../../utilities/isPTPrescaledWithSUV.js';
import { getImageDataMetadata } from '../../utilities/getImageDataMetadata.js';
import invertRgbTransferFunction from '../../utilities/invertRgbTransferFunction.js';
import { resolveColormap } from '../../utilities/colormap.js';
import { updateVTKImageDataWithCornerstoneImage } from '../../utilities/updateVTKImageDataWithCornerstoneImage.js';
export function createEmptyVTKImageData(args) {
const { dimensions, direction, numberOfComponents, origin, pixelArray, spacing, } = args;
const values = ArrayBuffer.isView(pixelArray) && !(pixelArray instanceof DataView)
? pixelArray
: Array.from(pixelArray);
const dataType = ArrayBuffer.isView(values) && !(values instanceof DataView)
? vtkDataArray.getDataType(values)
: undefined;
const scalarArray = vtkDataArray.newInstance({
...(dataType ? { dataType } : {}),
name: 'Pixels',
numberOfComponents,
values,
});
const imageData = vtkImageData.newInstance();
imageData.setDimensions(dimensions);
imageData.setSpacing(spacing);
imageData.setDirection(new Float32Array(Array.from(direction)));
imageData.setOrigin(origin);
imageData.getPointData().setScalars(scalarArray);
return imageData;
}
export function createVTKImageDataFromImage(image) {
const { dimensions, direction, numberOfComponents, origin, spacing } = getImageDataMetadata(image);
const pixelArray = image.voxelManager.getScalarData().slice();
const imageData = createEmptyVTKImageData({
dimensions,
direction: Array.from(direction),
numberOfComponents,
origin,
pixelArray,
spacing,
});
updateVTKImageDataWithCornerstoneImage(imageData, image);
return imageData;
}
export function updateVTKImageDataGeometryFromImage(imageData, image) {
const { direction, origin, spacing } = getImageDataMetadata(image);
imageData.setOrigin(origin);
imageData.setDirection(new Float32Array(Array.from(direction)));
imageData.setSpacing(spacing);
}
export function getDefaultImageVOIRange(image) {
if (isPTPrescaledWithSUV(image)) {
return { lower: 0, upper: 5 };
}
return getVOIRangeFromWindowLevel(image.windowWidth, image.windowCenter, image.voiLUTFunction);
}
export function getPlanarCameraState(renderer) {
const camera = renderer.getActiveCamera();
return {
focalPoint: [...camera.getFocalPoint()],
parallelScale: camera.getParallelScale(),
position: [...camera.getPosition()],
viewPlaneNormal: [...camera.getViewPlaneNormal()],
viewUp: [...camera.getViewUp()],
};
}
export function applyPlanarImagePresentation(args) {
const { actor, defaultVOIRange, defaultVOILUTFunction, props } = args;
const property = actor.getProperty();
const voiRange = props?.voiRange ?? defaultVOIRange;
if (props?.visible !== undefined) {
actor.setVisibility(props.visible);
}
if (props?.opacity !== undefined) {
property.setOpacity(props.opacity);
}
if (props?.interpolationType !== undefined) {
property.setInterpolationType(props.interpolationType);
}
if (!voiRange) {
return;
}
const transferFunction = createPlanarRGBTransferFunction({
colormap: props?.colormap,
invert: props?.invert,
voiRange,
voiLUTFunction: props?.voiLUTFunction ?? defaultVOILUTFunction,
});
property.setUseLookupTableScalarRange(true);
property.setRGBTransferFunction(0, transferFunction);
}
export function createPlanarRGBTransferFunction(args) {
const { colormap, invert, voiRange, voiLUTFunction } = args;
const transferFunction = colormap?.name !== undefined
? createColormapTransferFunction(colormap, voiRange)
: voiLUTFunction === VOILUTFunctionType.SAMPLED_SIGMOID
? createSigmoidRGBTransferFunction(voiRange)
: createLinearRGBTransferFunction(voiRange);
if (invert) {
invertRgbTransferFunction(transferFunction);
}
return transferFunction;
}
function createColormapTransferFunction(colormap, voiRange) {
const colormapName = colormap.name;
const colormapDefinition = colormapName
? resolveColormap(colormapName)
: undefined;
if (!colormapDefinition) {
throw new Error(`Colormap ${colormapName} not found`);
}
const transferFunction = vtkColorTransferFunction.newInstance();
transferFunction.applyColorMap(colormapDefinition);
transferFunction.setMappingRange(voiRange.lower, voiRange.upper);
return transferFunction;
}
export function applyPlanarCameraViewState(args) {
const { initialCamera, renderer, viewState } = args;
const camera = renderer.getActiveCamera();
const zoom = Math.max(viewState?.zoom ?? 1, 0.001);
const [panX, panY] = viewState?.pan ?? [0, 0];
camera.setParallelProjection(true);
camera.setParallelScale(initialCamera.parallelScale / zoom);
camera.setFocalPoint(initialCamera.focalPoint[0] + panX, initialCamera.focalPoint[1] + panY, initialCamera.focalPoint[2]);
camera.setPosition(initialCamera.position[0] + panX, initialCamera.position[1] + panY, initialCamera.position[2]);
}