UNPKG

@thewtex/vtk.js-esm

Version:

Visualization Toolkit for the Web

206 lines (165 loc) 5.95 kB
import macro from '../../macro.js'; import vtkImageData from './ImageData.js'; import vtkDataArray from '../Core/DataArray.js'; var vtkErrorMacro = macro.vtkErrorMacro; // see itk.js/PixelTypes.js var ITKPixelTypes = { Unknown: 0, Scalar: 1, RGB: 2, RGBA: 3, Offset: 4, Vector: 5, Point: 6, CovariantVector: 7, SymmetricSecondRankTensor: 8, DiffusionTensor3D: 9, Complex: 10, FixedArray: 11, Array: 12, Matrix: 13, VariableLengthVector: 14, VariableSizeMatrix: 15 }; /** * Converts an itk.js image to a vtk.js image. * * Requires an itk.js image as input. */ function convertItkToVtkImage(itkImage) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var vtkImage = { origin: [0, 0, 0], spacing: [1, 1, 1] }; var dimensions = [1, 1, 1]; var direction = [1, 0, 0, 0, 1, 0, 0, 0, 1]; for (var idx = 0; idx < itkImage.imageType.dimension; ++idx) { vtkImage.origin[idx] = itkImage.origin[idx]; vtkImage.spacing[idx] = itkImage.spacing[idx]; dimensions[idx] = itkImage.size[idx]; for (var col = 0; col < itkImage.imageType.dimension; ++col) { // ITK (and VTKMath) use a row-major index axis, but the direction // matrix on the vtkImageData is a webGL matrix, which uses a // column-major data layout. Transpose the direction matrix from // itkImage when instantiating that vtkImageData direction matrix. direction[col + idx * 3] = itkImage.direction.data[idx + col * itkImage.imageType.dimension]; } } // Create VTK Image Data var imageData = vtkImageData.newInstance(vtkImage); // Create VTK point data -- the data associated with the pixels / voxels var pointData = vtkDataArray.newInstance({ name: options.scalarArrayName || 'Scalars', values: itkImage.data, numberOfComponents: itkImage.imageType.components }); imageData.setDirection(direction); imageData.setDimensions.apply(imageData, dimensions); // Always associate multi-component pixel types with vtk.js point data // scalars to facilitate multi-component volume rendering imageData.getPointData().setScalars(pointData); // Associate the point data that are 3D vectors / tensors // Refer to itk-js/src/PixelTypes.js for numerical values switch (itkImage.imageType.pixelType) { case ITKPixelTypes.Scalar: break; case ITKPixelTypes.RGB: break; case ITKPixelTypes.RGBA: break; case ITKPixelTypes.Offset: break; case ITKPixelTypes.Vector: if (itkImage.imageType.dimension === 3 && itkImage.imageType.components === 3) { imageData.getPointData().setVectors(pointData); } break; case ITKPixelTypes.Point: break; case ITKPixelTypes.CovariantVector: if (itkImage.imageType.dimension === 3 && itkImage.imageType.components === 3) { imageData.getPointData().setVectors(pointData); } break; case ITKPixelTypes.SymmetricSecondRankTensor: if (itkImage.imageType.dimension === 3 && itkImage.imageType.components === 6) { imageData.getPointData().setTensors(pointData); } break; case ITKPixelTypes.DiffusionTensor3D: if (itkImage.imageType.dimension === 3 && itkImage.imageType.components === 6) { imageData.getPointData().setTensors(pointData); } break; case ITKPixelTypes.Complex: break; case ITKPixelTypes.FixedArray: break; case ITKPixelTypes.Array: break; case ITKPixelTypes.Matrix: break; case ITKPixelTypes.VariableLengthVector: break; case ITKPixelTypes.VariableSizeMatrix: break; default: vtkErrorMacro("Cannot handle unexpected ITK.js pixel type ".concat(itkImage.imageType.pixelType)); return null; } return imageData; } var vtkArrayTypeToItkComponentType = new Map([['Uint8Array', 'uint8_t'], ['Int8Array', 'int8_t'], ['Uint16Array', 'uint16_t'], ['Int16Array', 'int16_t'], ['Uint32Array', 'uint32_t'], ['Int32Array', 'int32_t'], ['Float32Array', 'float'], ['Float64Array', 'double']]); /** * Converts a vtk.js image to an itk.js image. * * Requires a vtk.js image as input. */ function convertVtkToItkImage(vtkImage) { var copyData = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var itkImage = { imageType: { dimension: 3, pixelType: ITKPixelTypes.Scalar, componentType: '', components: 1 }, name: 'name', origin: vtkImage.getOrigin(), spacing: vtkImage.getSpacing(), direction: { data: [1, 0, 0, 0, 1, 0, 0, 0, 1] }, size: vtkImage.getDimensions() }; var direction = vtkImage.getDirection(); var dimension = itkImage.size.length; itkImage.imageType.dimension = dimension; itkImage.direction.rows = dimension; itkImage.direction.columns = dimension; // Transpose the direction matrix from column-major to row-major for (var idx = 0; idx < dimension; ++idx) { for (var idy = 0; idy < dimension; ++idy) { itkImage.direction.data[idx + idy * dimension] = direction[idy + idx * dimension]; } } var pointData = vtkImage.getPointData(); var vtkArray; if (pointData.getTensors() !== null) { itkImage.imageType.pixelType = ITKPixelTypes.DiffusionTensor3D; vtkArray = pointData.getTensors(); } else if (pointData.getVectors() != null) { itkImage.imageType.pixelType = ITKPixelTypes.Vector; vtkArray = pointData.getVectors(); } else { vtkArray = pointData.getScalars(); } itkImage.imageType.componentType = vtkArrayTypeToItkComponentType.get(vtkArray.getDataType()); if (copyData) { // Copy the data array itkImage.data = vtkArray.getData().slice(0); } else { itkImage.data = vtkArray.getData(); } return itkImage; } var ITKHelper = { convertItkToVtkImage: convertItkToVtkImage, convertVtkToItkImage: convertVtkToItkImage }; export default ITKHelper;