Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | 544x 544x 544x 544x 544x 544x 544x 544x 544x 544x 544x 544x 544x 544x 544x 544x 544x 544x | import { vec3 } from 'gl-matrix'; import type { Point3, Mat3, ImagePlaneModule, ImagePixelModule, IImageCalibration, } from '../types'; import { EPSILON } from '../constants'; import type IImage from '../types/IImage'; import { buildMetadata } from './buildMetadata'; import type { VOILUTFunctionType } from '../enums'; type ReturnImageDataMetadata = { imagePlaneModule: ImagePlaneModule; imagePixelModule: ImagePixelModule; bitsAllocated: number; numVoxels: number; numberOfComponents: number; origin: Point3; direction: Mat3; dimensions: Point3; spacing: Point3; voiLUTFunction: VOILUTFunctionType; modality: string; scalingFactor: number; calibration: IImageCalibration; scanAxisNormal: Point3; }; /** * Calculates image metadata based on the image object. It calculates normal * axis for the images, and output image metadata * * @param image - stack image containing cornerstone image * @param imagePlaneModule - image plane module containing image orientation information * @param imagePixelModule - image pixel module containing pixel data information * @param getNumCompsFromPhotometricInterpretation - function to get number of components from photometric interpretation * @returns image metadata: bitsAllocated, number of components, origin, * direction, dimensions, spacing, number of voxels. */ export function getImageDataMetadata(image: IImage): ReturnImageDataMetadata { const { imagePlaneModule, imagePixelModule, voiLUTFunction, modality, scalingFactor, calibration, } = buildMetadata(image); let { rowCosines, columnCosines } = imagePlaneModule; // if null or undefined Iif (rowCosines == null || columnCosines == null) { rowCosines = [1, 0, 0] as Point3; columnCosines = [0, 1, 0] as Point3; } const rowCosineVec = vec3.fromValues( rowCosines[0], rowCosines[1], rowCosines[2] ); const colCosineVec = vec3.fromValues( columnCosines[0], columnCosines[1], columnCosines[2] ); const scanAxisNormal = vec3.create(); vec3.cross(scanAxisNormal, rowCosineVec, colCosineVec); let origin = imagePlaneModule.imagePositionPatient; // if null or undefined Iif (origin == null) { origin = [0, 0, 0]; } const xSpacing = imagePlaneModule.columnPixelSpacing || image.columnPixelSpacing; const ySpacing = imagePlaneModule.rowPixelSpacing || image.rowPixelSpacing; const xVoxels = image.columns; const yVoxels = image.rows; // Note: For rendering purposes, we use the EPSILON as the z spacing. // This is purely for internal implementation logic since we are still // technically rendering 3D objects with vtk.js, but the abstracted intention // of the stack viewport is to render 2D images const zSpacing = EPSILON; const zVoxels = 1; //TODO NEED TO CHECK IT !!!!! Iif ( !imagePixelModule.photometricInterpretation && image.sizeInBytes === 3 * image.width * image.height ) { image.numberOfComponents = 3; } const numberOfComponents = image.numberOfComponents || _getNumCompsFromPhotometricInterpretation( imagePixelModule.photometricInterpretation ); return { numberOfComponents, origin, direction: [...rowCosineVec, ...colCosineVec, ...scanAxisNormal] as Mat3, dimensions: [xVoxels, yVoxels, zVoxels], spacing: [xSpacing, ySpacing, zSpacing], numVoxels: xVoxels * yVoxels * zVoxels, imagePlaneModule, imagePixelModule, bitsAllocated: imagePixelModule.bitsAllocated, voiLUTFunction, modality, scalingFactor, calibration, scanAxisNormal: scanAxisNormal as Point3, }; } /** * Calculates number of components based on the dicom metadata * * @param photometricInterpretation - string dicom tag * @returns number representing number of components */ function _getNumCompsFromPhotometricInterpretation( photometricInterpretation: string ): number { // TODO: this function will need to have more logic later // see http://dicom.nema.org/medical/Dicom/current/output/chtml/part03/sect_C.7.6.3.html#sect_C.7.6.3.1.2 let numberOfComponents = 1; if ( photometricInterpretation === 'RGB' || photometricInterpretation?.includes('YBR') || photometricInterpretation === 'PALETTE COLOR' ) { numberOfComponents = 3; } return numberOfComponents; } |